看看这个汇编程序代码。它专为32位x86设计,将由nasm
编译 ...
my_function:
pop %eax
...
ret
main:
push 0x08
call my_function
我很久以前就已经了解到我们可以使用堆栈在主程序和函数之间传递参数。 我希望eax包含0x08,但这是假的,我无法解释原因。 我该怎么做才能获取我的函数参数?
答案 0 :(得分:8)
首先,如果您希望与平台上的其他语言或库进行交互,请务必阅读该平台的已定义界面。可以使用各种调用机制。
在您的情况下,call
指令将返回地址推送到堆栈。您可以使用一些算术和esp
来访问您的参数。由于您使用eax
,我将假设32位代码(和32位堆栈宽度)。我使用的是英特尔语法,因为我可以在不查看任何内容的情况下编写它:
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
在你的评论中,你问这个答案,如果这代表内存泄漏。答案是"否。"原因是调用者负责清理它添加到堆栈的任何内容。基于已编写的其他注释的更完整示例可能如下所示:
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
请注意,当我们对齐堆栈时(如果您不确定为什么会发生这种情况,您将在研究平台的调用标准时快速找到它)到16字节的边界,我们不会这样做。甚至试图找出esp
已经改变了多少。由于ebp
将充当"书签"对我们来说,我们可以让esp
移动以进行对齐或者可能是局部变量分配,而无需另外考虑。
在函数结尾语中,我们将ebp
移回esp
,在调用函数时将esp
恢复为原始值,从而清理所有本地分配和已经发生的对齐操作。最后,我们从堆栈中pop ebp
离开,将返回指针作为函数内堆栈的最终值。我们现在回来了。
回来后我们用流行音乐清理。
或者,可以使用返回来清理堆栈,该返回指定堆栈上要释放的字节数。这完全取决于您的调用标准是指定调用者清理还是被调用者清理。
答案 1 :(得分:1)
除了大卫的答案,这是另一个例子
push 0 ; fourth parameter
push 4 ; third parameter
push 4 ; second parameter
push [eax] ; first parameter
call printf
在C或C ++中与
相同somefunction(first,second,third,fourth);
答案 2 :(得分:-1)
请参阅以下说明:-
[BITS 32]
%include "nagoa+.inc"
%include "cfunctions.txt"
[SEGMENT .DATA USE32]
ret_value db "I am the Return Value",0
localvar db "My Local Variable Value",0
[SEGMENT .BSS USE32]
arg_param resb 160
[SEGMENT .TEXT USE32]
my_function:
;save arguments/parameters as this esp+ space will be destroyed by system function calls
mov eax,[esp+4]
;enjoy local variables for processing
;enter 4,0
mov dword [esp-4],localvar
call printf,`Argument/Parmeter=%s and Local Variable=%s`,eax,[esp-4]
add esp,12
;leave
;fill-up return values
mov eax,ret_value
ret
;ret 4
..start:
call puts,`Enter Argument/Parmeter`
add esp,4
call gets,arg_param
add esp,4
push arg_param
CALL my_function
call printf,`Return Value From Called Function=%s`,eax
add esp,4
call exit, 0