RET在装配中的意义

Rot*_*ayo 22 x86 assembly

我对汇编很新,而且我不明白在proc的最后,你用ret语句写了一个数字时它究竟意味着什么.

像这样:

Function Proc
push ax cx
.
...body...
.
pop cx ax
ret 2 
Function endp
Run Code Online (Sandbox Code Playgroud)

我知道它与函数末尾的堆栈指针应返回的位置有关吗?

如果你能轻松解释它,它真的会对我有所帮助.

Fra*_*ler 23

是的,但ret 2也从堆栈中删除了2个字节的参数.据推测,你的函数被称为:

push some_parameter
call Function
Run Code Online (Sandbox Code Playgroud)

此时,一个cdecl函数 - 一个"调用者清理"函数(通常由C使用) - 需要add sp, 2"清理堆栈",删除参数.这样的功能将以平淡无奇的方式结束ret.

一个stdcall函数,就是你所拥有的,是一个"被调用者清理"函数(例如,由Windows API使用)不需要add sp, 2- 它已经完成了ret 2.

如果您不了解它,call请将返回地址放在堆栈上(并将其ret弹出),这样您就不能只pop在函数内部获取参数.

  • 英特尔的“ret”手动条目有详细信息:https://www.felixcloutier.com/x86/ret (2认同)

小智 19

假设我有一个程序来添加两个单词并留下总和EAX.单词是我想传递给堆栈上的过程的参数.即:

push word1
push word2
call addtwob
Run Code Online (Sandbox Code Playgroud)

该过程看起来像:

addtwob proc

push ebp
mov  ebp,esp
mov  eax, [ebp+6]    
add  eax, [ebp+8]
pop ebp
ret 4

Endp
Run Code Online (Sandbox Code Playgroud)

[ebp+6][ebp+8]地址word2以及word1堆栈. ret 4只是像往常一样返回但是然后将4添加到堆栈指针(esp),这样你就不必pop word2 pop word1在从调用返回后离开堆栈,因此它清理/平衡堆栈而不需要弹出先前的推送.

  • 因此,pop 清除设置的 ebp,ret 清除返回地址并在 ret 清除额外的 4 个字节(即两个字)后设置“4”。这样对吗? (2认同)

小智 9

正如亚历克斯所说,这意味着回归.在x86汇编中,当编译器到达此行时(例如,在子例程的末尾),它会弹出堆栈中的最后一个值,该值应该是返回的地址,并将其分配给IP寄存器.您可以通过编写简单的汇编代码并使用Turbo Debugger进行编译来更好地理解这一点.如果你是新手,那么有一个汇编程序的GUI.你可以在这里找到GUI .

当您在子例程中弹出并向堆栈推送值时,应该存储返回的地址,因为在子路径的末尾需要将其推回到return行之前的堆栈中.

祝好运!