看看这个汇编代码.它专为32位x86设计,将由nasm编译
...
my_function:
pop %eax
...
ret
main:
push 0x08
call my_function
Run Code Online (Sandbox Code Playgroud)
我很久以前就已经知道我们可以使用堆栈在主程序和函数之间传递参数.我希望eax包含0x08,但这是假的,我无法解释原因.我该怎么做才能获取我的函数参数?
首先,如果您希望与平台上的其他语言或库进行交互,请务必阅读该平台的已定义界面.可以使用各种调用机制.
在您的情况下,call指令将返回地址推送到堆栈.您可以使用一些算术和参数来访问您的参数esp.我将假设您使用32位代码(和32位堆栈宽度)eax.我正在使用intel语法,因为我可以在不查找任何内容的情况下编写它:
my_function:
mov eax, [esp+4] ; Move the contents of ESP+4 into EAX
; ESP should be pointing at the 32 bit RIP.
; ESP+4 should be the pushed parameter.
...
ret
main:
push 0x08
call my_function
Run Code Online (Sandbox Code Playgroud)
在你的评论中,你会问这个答案,如果这代表内存泄漏.答案是不." 原因是调用者负责清理它添加到堆栈中的任何内容.基于已编写的其他注释的更完整示例可能如下所示:
my_function:
push ebp ; Store the current stack frame
mov ebp, esp ; Preserve ESP into EBP for argument references
and esp, 0xfffffff0; Align the stack to allow library calls
mov eax, [ebp+8] ; Move the contents of EBP+4 into EAX
; EBP should be pointing at the 32 bit RIP.
; EBP+4 should be the pushed parameter.
... ; Do lots of cool stuff
mov esp, ebp ; Restore the stack and ebp
pop ebp
ret
main:
push 0x08
call my_function
pop ebx ; Clean up the stack
Run Code Online (Sandbox Code Playgroud)
请注意,当我们对齐堆栈时(如果您不确定为什么会发生这种情况,您将在研究平台的调用标准时很快找到它)到16字节边界,我们甚至不会弄清楚如何esp变化很大.由于ebp它将作为我们的"书签",我们可以放弃esp对齐或可能是局部变量分配而无需另外考虑.
在函数结尾中,我们ebp返回到esp,esp当调用函数时,它恢复到它的原始值,从而清理已经发生的任何本地分配和对齐操作.最后,我们pop ebp离开堆栈,将返回指针作为函数内堆栈的最终值.我们现在回来了.
回来后我们用流行音乐清理.
或者,可以使用返回来清理堆栈,该返回指定堆栈上要释放的字节数.这完全取决于您的调用标准是指定调用者清理还是被调用者清理.
除了大卫的回答之外,这是另一个例子
push 0 ; fourth parameter
push 4 ; third parameter
push 4 ; second parameter
push [eax] ; first parameter
call printf
Run Code Online (Sandbox Code Playgroud)
在 C 或 C++ 中相同
somefunction(first,second,third,fourth);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
27808 次 |
| 最近记录: |