退出程序 x86
Exit program x86
我正在学习 x86 汇编。我想了解 "exiting program" 如何在 x86 上工作。我们有一个代码:
push ebp
mov ebp,esp
//Some stuff here
mov esp, ebp
pop ebp
ret
当处理器执行指令时"ret":
EIP会有值,从栈中弹出,即0。
所以处理器将转到 0 地址并尝试执行不包含程序 code/executable 代码的指令。
那么,处理器到底发生了什么?是否有条件检查,例如,if EIP = 0 -> exit program?
Or if ESP out of bounds -> exit program?
`处理器如何理解这条RET指令是程序的结尾?
进程被操作系统终止。如果您看到 return 指令,则在您的函数之前有一个 ("hidden") 函数,然后返回执行。
在 Linux(32 位)环境中终止进程的一种方法是调用特定的系统调用:sys_exit
mov eax, 0 // interrupt code
mov ebx, 0 // argument, in this case: return value
int 0x80
这可能是您的函数之前的函数所做的事情。上面的代码将命令交还给操作系统,然后操作系统退出你的进程。
main()
从正常的 C 运行时初始化函数中调用。用任何语言写main
,包括asm,和写任何其他函数没有区别。
执行从 _start
开始。如果您编写自己的 _start
,它与 return 无关,因此您需要进行 _exit(2)
或 exit_group(2)
系统调用。
(否则当执行从代码末尾掉落时出现段错误,或者如果您尝试 ret
它将从堆栈中弹出一个值到程序计数器(EIP)中,并且可能在代码上出现段错误- 从那个可能无效的地址中获取。)
当您使用 C 编译器编译 + link 时,它 link 在 CRT(C 运行时)启动代码中提供 _start
初始化 libc 然后调用 main
. 在您的 main
return 之后,调用它的 CRT 代码运行 atexit
函数,然后将 main 的 return 值传递给退出系统调用。
_start
不是函数,它是进程入口点。例如,在 Linux 下,在进入 _start
时,ESP 指向 argc
,而不是 return 地址。 (参见 i386 System V ABI。)
这个问题是从不同的角度提出的,但是my answer另一个最近的问题更详细。
一如既往,使用调试器单步执行是查看正在发生的事情并测试您的理解力的好方法。
我正在学习 x86 汇编。我想了解 "exiting program" 如何在 x86 上工作。我们有一个代码:
push ebp
mov ebp,esp
//Some stuff here
mov esp, ebp
pop ebp
ret
当处理器执行指令时"ret":
EIP会有值,从栈中弹出,即0。
所以处理器将转到 0 地址并尝试执行不包含程序 code/executable 代码的指令。
那么,处理器到底发生了什么?是否有条件检查,例如,if EIP = 0 -> exit program?
Or if ESP out of bounds -> exit program?
`处理器如何理解这条RET指令是程序的结尾?
进程被操作系统终止。如果您看到 return 指令,则在您的函数之前有一个 ("hidden") 函数,然后返回执行。
在 Linux(32 位)环境中终止进程的一种方法是调用特定的系统调用:sys_exit
mov eax, 0 // interrupt code
mov ebx, 0 // argument, in this case: return value
int 0x80
这可能是您的函数之前的函数所做的事情。上面的代码将命令交还给操作系统,然后操作系统退出你的进程。
main()
从正常的 C 运行时初始化函数中调用。用任何语言写main
,包括asm,和写任何其他函数没有区别。
执行从 _start
开始。如果您编写自己的 _start
,它与 return 无关,因此您需要进行 _exit(2)
或 exit_group(2)
系统调用。
(否则当执行从代码末尾掉落时出现段错误,或者如果您尝试 ret
它将从堆栈中弹出一个值到程序计数器(EIP)中,并且可能在代码上出现段错误- 从那个可能无效的地址中获取。)
当您使用 C 编译器编译 + link 时,它 link 在 CRT(C 运行时)启动代码中提供 _start
初始化 libc 然后调用 main
. 在您的 main
return 之后,调用它的 CRT 代码运行 atexit
函数,然后将 main 的 return 值传递给退出系统调用。
_start
不是函数,它是进程入口点。例如,在 Linux 下,在进入 _start
时,ESP 指向 argc
,而不是 return 地址。 (参见 i386 System V ABI。)
这个问题是从不同的角度提出的,但是my answer另一个最近的问题更详细。
一如既往,使用调试器单步执行是查看正在发生的事情并测试您的理解力的好方法。