需要帮助了解如何使用 add esp, 12 弹出堆栈
Need help understanding how to pop stack with add esp, 12
我对这个汇编程序有疑问:
extern printf ; the C function, to be called
SECTION .data ; Data section, initialized variables
a: dd 5 ; int a=5;
fmt: db "a=%d, eax=%d",10,0 ; The printf format, '\n','0'
SECTION .text ; Code section.
global main ; the standard gcc entry point
main: ; the program label for the entry point
push ebp ; calling convention
mov ebp, esp
mov eax, [a] ; put a from store into register
add eax, 2 ; a+2
push eax ; value of a+2
push dword [a] ; value of variable a
push dword fmt ; address of ctrl string
call printf ; Call C function
add esp, 12 ; pop stack 3 times = 4 bytes
mov esp, ebp ; returning convention
pop ebp ; same as "leave" op
mov eax,0 ; normal (no error) return value
ret ; return
我看到接近尾声时弹出堆栈 3 次,等于 4 个字节。但是我不明白为什么要在最后出栈,12怎么等同于“3次=4个字节” 还有,stacked是不是一定要在最后出栈呢?
当你调用一个(子)函数时,CPU需要保存要跳回的值;它为此使用堆栈
所以当你进入函数时,栈顶的值是return地址
此代码将另外 12 个字节添加到堆栈
push eax ; value of a+2
push dword [a] ; value of variable a
push dword fmt ; address of ctrl string
这些推送中的每一个都向[ESP]写入4个字节,并减去ESP的4个字节(减法是因为堆栈向下增长)。在你可以 ret
返回给你的被调用者之前,你必须去掉堆栈上的这 12 个字节。最简单的方法是,他在代码中做了什么:
add esp, 12 ; pop stack 3 times = 4 bytes
另一方面,该函数将当前 ESP 保存在函数顶部的 EBP 中(这会创建一个新的 'stack frame')
push ebp ; calling convention
mov ebp, esp
这样做是为了能够处理被调用者的函数参数和您可能为 [EBP +/- offset] 保留位置的局部变量,并且它使您能够通过加载以前的值来恢复整个堆栈再次:
mov esp, ebp ; returning convention
pop ebp ; same as "leave" op
注意:在这段代码中,堆栈被清理了两次。 (将 12 添加到 ESP(它从系统调用作为参数获得的值中清除堆栈),然后再次从 EBP 加载先前的值。在这种情况下,不需要其中之一
我对这个汇编程序有疑问:
extern printf ; the C function, to be called
SECTION .data ; Data section, initialized variables
a: dd 5 ; int a=5;
fmt: db "a=%d, eax=%d",10,0 ; The printf format, '\n','0'
SECTION .text ; Code section.
global main ; the standard gcc entry point
main: ; the program label for the entry point
push ebp ; calling convention
mov ebp, esp
mov eax, [a] ; put a from store into register
add eax, 2 ; a+2
push eax ; value of a+2
push dword [a] ; value of variable a
push dword fmt ; address of ctrl string
call printf ; Call C function
add esp, 12 ; pop stack 3 times = 4 bytes
mov esp, ebp ; returning convention
pop ebp ; same as "leave" op
mov eax,0 ; normal (no error) return value
ret ; return
我看到接近尾声时弹出堆栈 3 次,等于 4 个字节。但是我不明白为什么要在最后出栈,12怎么等同于“3次=4个字节” 还有,stacked是不是一定要在最后出栈呢?
当你调用一个(子)函数时,CPU需要保存要跳回的值;它为此使用堆栈
所以当你进入函数时,栈顶的值是return地址
此代码将另外 12 个字节添加到堆栈
push eax ; value of a+2
push dword [a] ; value of variable a
push dword fmt ; address of ctrl string
这些推送中的每一个都向[ESP]写入4个字节,并减去ESP的4个字节(减法是因为堆栈向下增长)。在你可以 ret
返回给你的被调用者之前,你必须去掉堆栈上的这 12 个字节。最简单的方法是,他在代码中做了什么:
add esp, 12 ; pop stack 3 times = 4 bytes
另一方面,该函数将当前 ESP 保存在函数顶部的 EBP 中(这会创建一个新的 'stack frame')
push ebp ; calling convention
mov ebp, esp
这样做是为了能够处理被调用者的函数参数和您可能为 [EBP +/- offset] 保留位置的局部变量,并且它使您能够通过加载以前的值来恢复整个堆栈再次:
mov esp, ebp ; returning convention
pop ebp ; same as "leave" op
注意:在这段代码中,堆栈被清理了两次。 (将 12 添加到 ESP(它从系统调用作为参数获得的值中清除堆栈),然后再次从 EBP 加载先前的值。在这种情况下,不需要其中之一