简体   繁体   English

如何将变量传递给外部程序集 function

[英]How to pass variables to a external assembly function

How to pass a variable from a C program to a assembly function.如何将变量从 C 程序传递到程序集 function。

Example:例子:

main.c: main.c:

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

main.asm:主.asm:

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

How do I access passthis within asm_function .如何在asm_function passthis

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.编辑:可能应该提到我没有使用操作系统,我正在使用 i686-elf 交叉编译器进行编译,并将其用作 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. 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] ),但是在你push任何东西或移动 ESP 后,偏移量会发生变化。

You can use [ebp+8] after setting up a traditional stack pointer (which doesn't change during the function even when ESP does).您可以在设置传统堆栈指针后使用[ebp+8] (在 function 期间不会更改,即使 ESP 会更改)。

For example, int asm_function(int) can be implemented as:例如, int asm_function(int)可以实现为:

;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] ).对于之后的每个参数,只需简单地添加另一个4 (即,对于第二个参数,使用[ebp+12] )。 As you can see, setting up EBP as a frame pointer adds a lot of overhead for tiny functions.如您所见,将 EBP 设置为帧指针会为小函数增加大量开销。

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:一些非 ELF 系统/ABI 在 C 符号名称前添加前导下划线,因此您应该声明asm_function_asm_function以使您的代码在这些 ABI 中大致等效,如下所示:

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. x86 可能有一些不同的调用约定。 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..这取决于很多事情,例如 windows 与 linux,以及您使用的编译器环境,32 位与 64 位等。

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.最好查看您正在使用的编译器的 output 以查看参数是如何传递的,并在程序集中执行相应的适当方法来接受参数。 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.您可以使用反汇编程序或调试器查看 output。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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