对%esp的修改会导致SIGSEGV

有时我使用下面的代码来避免参与编码竞争时的堆栈溢出。

int main() { static const int _STACK_SIZE = MAXN*10; static int _STACK[_STACK_SIZE*2], _ESP; __asm__ __volatile__ ( "movl %%esp, %0\n" "movl %1, %%esp\n": "=g"(_ESP): "g"(_STACK + _STACK_SIZE): ); // Do Something.. __asm__ __volatile__ ( "movl %0, %%esp\n": : "g"(_ESP): ); } 

据我所知,这个asm代码备份%esp并将堆栈移动到_STACK[]


我的问题:为什么这个代码在x86-64 Linux服务器上导致SIGSEGV (它在我自己的x86 Linux上运行良好)? 以及如何解决它?

我想,也许这是因为%esp是一个64位指针?

我试图删除__asm__ __volatile__("movl %0, %%esp\n": : "g"(_ESP):); 它似乎运行良好?

这是因为在x86-64程序集中修改一个32位寄存器(如esp清零相应64位寄存器的最高32位,在这种情况下为rsp 。 在x86-64中,堆栈指针rsp是一个64位寄存器。 只有在具有4 GiB以上虚拟内存地址空间的计算机上才会出现此问题,因为2 ^ 32字节= 4 GiB,因此在计算机中虚拟内存地址空间少于4 GiB的计算机上,最高32位将为零无论如何。

所以通过修改esp你可以使rsp指向你的程序没有访问权限的地址,从而导致分段错误。 在x86-64代码中,通常不使用esp ,而应该用x86-64代码中的rsp替换esp所有实例。