在尝试获取 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(非法指令)而崩溃。但是,如果我在编译中添加一些优化:
$ 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 上没有问题。