2

有时我在参加编码比赛时使用以下代码来避免堆栈溢出。

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[].


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

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

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

4

1 回答 1

4

It's because in x86-64 assembly modifying a 32-bit register such as esp zeroes the highest 32 bits of the corresponding 64-bit register, rsp in this case. In x86-64 the stack pointer rsp is a 64-bit register.

x86-64 Linux always puts the stack pointer near the top of the user-space range of virtual address space, like 0x7fffffffe6d0 for example, so it's always outside the low 32 bits of virtual address space. The high half of RSP is non-zero and ESP != RSP.

So by modifying esp you make rsp point to an address where your program has no access rights, and thus cause a segmentation fault. In x86-64 code you don't normally use esp at all, and you should replace all instances of esp with rsp in your x86-64 code.

于 2013-03-27T10:56:30.943 回答