スタックポインタの値
こんにちは。LKHSです。
自分はレジスタの中では何といっても esp (スタックポインタ)が一番好きなのですが(?)、プログラム中で esp の値を確認したい時があります。
ユーザプロセス中で esp の値を取得するには、インラインアセンブリを用いた以下のようなコードを使用してできます。
unsigned long get_esp() {
__asm__("movl %esp, %eax");
}
int main() {
unsigned long esp;
esp = get_esp();
printf("esp = 0x%08lx\n", esp);
return 0;
}
アセンブリを確認してみます。
[...]
get_esp:
.LFB2:
pushq %rbp
.LCFI0:
movq %rsp, %rbp
.LCFI1:
#APP
movl %esp, %eax <= __asm__("movl %esp, %eax");
#NO_APP
leave
ret
[...]
ただし、これだと esp の値は get_esp() が呼び出された時の値となるので、厳密に現在の esp の値を取得するには、拡張インラインアセンブリを用いた以下のようなコードを使用すればできます。
unsigned long esp;
__asm__("movl %%esp, %0":"=g"(esp));
printf("esp = 0x%08lx\n", esp);
アセンブリを確認してみます。
[...]
main:
.LFB2:
pushq %rbp
.LCFI0:
movq %rsp, %rbp
.LCFI1:
subq $16, %rsp
.LCFI2:
#APP
movl %esp, -8(%rbp) <= __asm__("movl %%esp, %0":"=g"(esp));
#NO_APP
movq -8(%rbp), %rsi
movl $.LC0, %edi
movl $0, %eax
call printf
movl $0, %eax
leave
ret
[...]
また、カーネルコンテキスト中でユーザプロセスがシステムコールを発行した時の esp の値を取得するには、カーネルスタックに esp の値が積まれるので、以下のようなコードを使用してできます。
struct pt_regs * regs; regs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) current->thread_info)) - 1; printk(KERN_INFO "esp = 0x%08lx\n", regs->esp);
esp の値取り放題ですね。他にも方法ありましたら教えて下さい。




コメント