我用C++编写了一个“危险”的程序,它在不同的堆栈帧之间跳来跳去。目标是从调用堆栈的最低级别跳到一个调用者,做一些事情,然后再次跳回,每次跳过中间所有的调用。
我通过手动更改堆栈基地址(设置%ebp)并跳转到标签地址来实现。这完全有效,gcc和icc都可以使用,而且没有任何堆栈损坏。那天这个程序能正常工作让我非常开心。
现在我正在将同样的程序用C语言重新编写,但它不能正常工作。特别是在使用gcc v4.0.1(Mac OS)时无法正常工作。一旦我跳到新的堆栈帧(正确设置堆栈基指针),以下指令会执行,在调用fprintf之前列出的最后一条指令崩溃,解除对NULL的引用:
我通过手动更改堆栈基地址(设置%ebp)并跳转到标签地址来实现。这完全有效,gcc和icc都可以使用,而且没有任何堆栈损坏。那天这个程序能正常工作让我非常开心。
现在我正在将同样的程序用C语言重新编写,但它不能正常工作。特别是在使用gcc v4.0.1(Mac OS)时无法正常工作。一旦我跳到新的堆栈帧(正确设置堆栈基指针),以下指令会执行,在调用fprintf之前列出的最后一条指令崩溃,解除对NULL的引用:
lea 0x18b8(%ebx), %eax
mov (%eax), %eax
mov (%eax), %eax
我做了一些调试,发现通过手动设置%ebx
寄存器,在切换堆栈帧时(使用我在第一个函数离开前观察到的值),可以解决错误。我读到这个寄存器在gcc中处理“位置无关代码”。
什么是位置无关代码?位置无关代码如何工作?此寄存器指向什么?