use*_*859 0 x86 assembly stack exit
我正在学习 x86 汇编。我试图了解“退出程序”如何在 x86 上工作。我们有一个代码:
push ebp
mov ebp,esp
//Some stuff here
mov esp, ebp
pop ebp
ret
Run Code Online (Sandbox Code Playgroud)
当处理器执行指令“ret”时:
EIP 将具有从堆栈中弹出的值,即 0。因此处理器将转到 0 地址并尝试执行不包含程序代码/可执行代码的指令。那么,处理器到底发生了什么?是否有条件检查,例如,if EIP = 0 -> exit program? Or if ESP out of bounds -> exit program?`处理器如何理解这条 RET 指令是程序的结尾?
main()从正常的 C 运行时初始化函数调用。写main在任何语言,包括ASM,是编写任何其它功能没有什么不同。
执行开始于_start。如果你自己写_start,它没有什么可返回的,所以你需要做一个_exit(2)orexit_group(2)系统调用。
(否则,当执行从代码的末尾处退出时,会出现段错误,或者如果您尝试这样做ret,它将从堆栈中弹出一个值到程序计数器 (EIP) 中,并且可能会在从可能无效的地址获取代码时出现段错误。)
当您使用 C 编译器进行编译 + 链接时,它会链接到 CRT(C 运行时)启动代码中,_start该代码提供一个初始化 libc 然后调用main. 返回后main,调用它的 CRT 代码运行atexit函数,然后将 main 的返回值传递给退出系统调用。
_start不是函数,它是进程入口点。例如,在 Linux 下,_startESP 的入口指向argc,而不是返回地址。(请参阅 i386 System V ABI。)
这个问题是从不同的角度提出的,但我对另一个最近问题的回答更详细。
与往常一样,使用调试器单步执行是查看正在发生的事情并测试您的理解的好方法。