问题
Sometimes I use the following code to avoid stack overflow when taking part in coding competition.
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):
);
}
As far as I know, this asm code backups %esp and moves the stack to _STACK[].
My Question: Why this code cause SIGSEGV on a x86-64 Linux Server(It runs well on my own x86 Linux)? And how to fix it?
I guess, maybe it's because %esp is a 64-bit pointer??
I tried to delete the __asm__ __volatile__("movl %0, %%esp\n": : "g"(_ESP):); and it seems runs well?
回答1:
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. The problem should occur only in computers that have more than 4 GiB of virtual memory address space, because 2^32 bytes = 4 GiB, so in computers that have less than 4 GiB of virtual memory address space, the highest 32 bits will be zeros anyway.
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.
来源:https://stackoverflow.com/questions/15656887/a-modification-to-esp-cause-sigsegv