如何在汇编程序x86函数调用

时间:2016-06-22 17:58:10

标签: assembly nasm

看看这个汇编程序代码。它专为32位x86设计,将由nasm

编译
   ...
   my_function:
        pop %eax
        ...
        ret


   main:
       push 0x08
       call my_function

我很久以前就已经了解到我们可以使用堆栈在主程序和函数之间传递参数。 我希望eax包含0x08,但这是假的,我无法解释原因。 我该怎么做才能获取我的函数参数?

3 个答案:

答案 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