C で (インライン ASM を使用して) 現在のスタック ポインターを取得しようとすると、奇妙な動作に遭遇しました。コードは次のようになります。
#include <stdio.h>
class os {
public:
static void* current_stack_pointer();
};
void* os::current_stack_pointer() {
register void *esp __asm__ ("rsp");
return esp;
}
int main() {
printf("%p\n", os::current_stack_pointer());
}
標準の gcc オプションを使用してコードをコンパイルすると、次のようになります。
$ g++ test.cc -o test
次のアセンブリが生成されます。
__ZN2os21current_stack_pointerEv:
0000000000000000 pushq %rbp
0000000000000001 movq %rsp,%rbp
0000000000000004 movq %rdi,0xf8(%rbp)
0000000000000008 movq 0xe0(%rbp),%rax
000000000000000c movq %rax,%rsp
000000000000000f movq %rsp,%rax
0000000000000012 movq %rax,0xe8(%rbp)
0000000000000016 movq 0xe8(%rbp),%rax
000000000000001a movq %rax,0xf0(%rbp)
000000000000001e movq 0xf0(%rbp),%rax
0000000000000022 popq %rbp
結果のバイナリを実行すると、SIGILL (Illegal Instruction) でクラッシュします。ただし、コンパイルに少し最適化を追加すると、次のようになります。
$ g++ -O1 test.cc -o test
生成されたアセンブリは、はるかに単純です。
0000000000000000 pushq %rbp
0000000000000001 movq %rsp,%rbp
0000000000000004 movq %rsp,%rax
0000000000000007 popq %rbp
0000000000000008 ret
そして、コードは正常に実行されます。それでは、質問に。Mac OS X で C コードからスタック ポインタを取得するためのより安定した方法はありますか? 同じコードは Linux では問題ありません。