How can i pass parameters in assembler x86 function call

前端 未结 3 1401

Look at this assembler code. It is designed for 32 bits x86 and will be compiled by nasm

   ...
   my_function:
        pop %eax
        ...
        ret


           


        
相关标签:
3条回答
  • 2020-12-06 05:50

    See below for explanation:-

    [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
    
    0 讨论(0)
  • 2020-12-06 05:53

    Firstly, if you are looking to interface with other languages or libraries on your platform, be sure to read the defined interface for that platform. There are a variety of calling mechanisms that might be used.

    In your case, the call instruction is pushing the return address onto the stack. You can access your parameter by using some arithmetic and esp. I will assume 32 bit code (and a 32 bit stack width) since you are using eax. I'm using intel syntax since I can write that without looking anything up:

    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
    

    In your comments you ask, regarding this answer, if this represents a memory leak. The answer is "No." The reason is that the caller is responsible to clean up anything that it adds to the stack. A more complete example based on the other comments that have been written might look like this:

    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+8 into EAX
                            ; [EBP] should be the saved 32 bit EBP.
                            ; [EBP+4] should be the 32 bit EIP (return address).
                            ; [EBP+8] 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
    

    Notice that when we align the stack (if you're not sure why this is happening, you will quickly find it when you research the calling standard for your platform) to a 16 byte boundary, we don't even try to figure out how much esp has changed. Since ebp will act as a "bookmark" for us, we can let esp move for alignment or perhaps local variable allocation without another thought.

    In the function epilogue we move ebp back into esp, which restores esp to its original value when the function was called, thus cleaning up any local allocations and alignment operations that have happened. Finally, we pop ebp off of the stack, leaving the return address pointer as the final value on the stack within the function. We now return.

    After returning we clean up with a pop.

    Alternatively, it is possible to clean up the stack with a return specifying the number of bytes to free on the stack (eg ret 4). It all depends on whether your calling standard specifies caller cleanup or callee cleanup.

    0 讨论(0)
  • 2020-12-06 06:00

    In Addition to David answers, this is another example

    push 0       ; fourth parameter
    push 4       ; third parameter
    push 4       ; second parameter
    push [eax]   ; first parameter
    call printf
    

    Same in C or C++ as

    somefunction(first,second,third,fourth);
    
    0 讨论(0)
提交回复
热议问题