简体   繁体   中英

How to pass variables to a external assembly function

How to pass a variable from a C program to a assembly function.

Example:

main.c:

void main() {
  unsigned int passthis = 42
  extern asm_function();
  asm_function(passthis)
}

main.asm:

bits 32
global start
section .text
asm_function:
  ...

How do I access passthis within asm_function .

Edit: Probably should've mentioned i'm not using a OS, i'm compiling using a i686-elf cross compiler and am going to use it as a kernel.

If you compile your C into 32-bit code with the default GCC options (not -mregparm=3 like the Linux kernel uses), then on function entry the first argument is on the stack just above the return address (at [esp+4] ), but that offset changes after you push anything or move ESP around.

You can use [ebp+8] after setting up a traditional stack pointer (which doesn't change during the function even when ESP does).

For example, int asm_function(int) can be implemented as:

;bits 32              ; unneeded, nasm -felf32 implies this.
global asm_function   ; include asm_function in ELF .o symbol table for linking
section .text
asm_function:
    push ebp
    mov ebp, esp
    mov eax, [ebp+8]  ; return the first argument
    mov esp, ebp
    pop ebp
    ret

For each parameter after this, just simply add another 4 (ie for the 2nd parameter, use [ebp+12] ). As you can see, setting up EBP as a frame pointer adds a lot of overhead for tiny functions.

Some non-ELF systems/ABIs prepend a leading underscore to C symbol names, so you should declare both asm_function and _asm_function for your code to be roughly equivalent across these ABIs, like so:

global _asm_function
global asm_function  ; make both names of the function global
section .text
_asm_function:
asm_function:        ; make both symbols point to the same place
    push ebp
    mov ebp, esp
    mov eax, [ebp+8]
    mov esp, ebp
    pop ebp
    ret

x86 has probably a handful of different calling conventions. It depends on a number of things, like windows vs. linux, and on what compiler environment you're using, 32-bit vs. 64-bit, etc..

Best probably to look at the output of the compiler you're using to see how the parameter is being passed, and do the corresponding appropriate way of accepting the parameter in your assembly. So if it is pushed on the stack then expect it there, if it is passed in a register, expect it there...

You can look at the output using a disassembler, or using a debugger.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM