为什么我会通过这种无条件跳转获得 SIGSEGV?

Why do I get a SIGSEGV with this unconditional jump?

我在 Linux 上尝试 运行 这段代码,看看会发生什么:

int fn(void) { return 0; }
int main(void) { __asm__("jmp fn;"); }

我看不出执行被 SIGSEGV 终止的任何原因,但这就是我得到的。我希望流程被重定向到 _start,因为堆栈在 mainfn 中没有以任何方式修改,并且激活记录中的 return 地址应该仍然是"usable".

你能解释一下这背后的原因吗?

return 0 生成类似

的内容
mov [=10=]x0, %eax
ret

其中 ret 从堆栈中弹出 return 地址 并跳转到那里。一个简单的 jmp 不会压入任何 return 地址,因此 ret 将弹出堆栈中的任何内容。