简体   繁体   English

从x86汇编语言调用C函数

[英]Calling C functions from x86 assembly language

Is it possible to generate assembly language functions from C functions using GCC, so that they can be invoked from an assembly language program? 是否可以使用GCC从C函数生成汇编语言函数,以便可以从汇编语言程序调用它们? I know that gcc compiles C to machine code (which can easily be disassembled into assembly language), and I already know that it's possible to inline assembly language functions in C , but I haven't yet found a way to invoke C functions from assembly language programs, which is basically the inverse of this. 我知道gcc将C编译为机器代码(很容易被反汇编成汇编语言),我已经知道可以在C中内联汇编语言函数 ,但我还没有找到一种方法从汇编中调用C函数语言程序,基本上与此相反。

Here, I'm attempting to inline a C function in an x86 assembly program. 在这里,我试图在x86汇编程序中内联一个C函数。 If inlining isn't possible, then is there some other way to invoke a C function from an assembly language program? 如果无法内联,那么还有其他方法可以从汇编语言程序中调用C函数吗?

.686p
.model flat,stdcall
.stack 2048

.data

.code
start:

invoke  ExitProcess, 0

printSomething PROC ;now I'm attempting to inline a C function here
    void printSomething(thingToPrint){
        printf("This is a C function that I want to invoke from an assembly language program.");
        printf("There must be some way to do this - is it possible somehow?");
    }
printSomething ENDP

end start

I'm going from memory here, so I may be off slightly on a detail or two. 我要从记忆中走出来,所以我可能会稍微偏离一两个细节。 However, it should I hope be enough to get you going in the right direction. 但是,我希望能够让你朝着正确的方向前进。

You're going to need to tell the GCC assembler that your routine printSomething() is not defined in your assembly file. 您需要告诉GCC汇编程序您的例程printSomething()未在汇编文件中定义。 In 'C' you would use the extern keyword. 在'C'中,您将使用extern关键字。 For assembly you will need to use .globl . 对于装配,您需要使用.globl

.globl printSomething

If you are using a different assembler than GCC's, the keyword may be different. 如果您使用的是与GCC不同的汇编程序,则关键字可能会有所不同。

The next big question is 'how do I pass the arguments'? 下一个重要问题是“如何通过论证”? This very much depends upon your processor AND OS. 这在很大程度上取决于您的处理器和OS。 Since the title of your question indicates x86, I am going to assume that you are using either the 16-bit or 32-bit modes and the standard x86 ABI (as opposed to x86-64 which is also differs between Windows and Linux). 由于您的问题标题表示x86,我将假设您使用的是16位或32位模式和标准x86 ABI(而不是x86-64,Windows和Linux之间也不同)。 The C parameters are passed to the called routine by pushing them onto the stack. 通过将C参数推入堆栈,将C参数传递给被调用的例程。 They are pushed onto the stack from right to left. 它们从右到左被推到堆叠上。

Thus, 从而,

printSomething (arg1, arg2, arg3, arg4);

translates to ... 转换为......

pushl arg4
pushl arg3
pushl arg2
pushl arg1
call  printSomething
addl  $0x10, %esp

You may be asking yourself, what is this 你可能会问自己,这是什么

addl $0x10, %esp

? We passed (aka pushed) four 32-bit arguments to the routine (onto the stack). 我们将四个32位参数传递(通过推送)到例程(进入堆栈)。 Although the routine knows to expect those arguments, it is NOT responsible for popping them off the stack. 虽然例程知道期望这些参数,但它不负责将它们从堆栈中弹出。 The caller is responsible for that. 来电者对此负责。 So, after we return from the routine, we adjust the stack pointer to discard the four 32-bit arguments we previously pushed onto the stack. 因此,在我们从例程返回之后,我们调整堆栈指针以丢弃先前推入堆栈的四个32位参数。

In the above example, I am assuming that we are operating in 32-bit mode. 在上面的例子中,我假设我们在32位模式下运行。 If it were 16-bit mode, it would be ... 如果它是16位模式,它将是......

pushw arg4
pushw arg3
pushw arg2
pushw arg1
call  printSomething
addw  $0x8, %sp

I realize that in your example, printSomething() only takes one (1) argument and in my example I used four (4). 我意识到在你的例子中, printSomething()只接受一(1)个参数,在我的例子中我使用了四(4)。 Just adjust my example as is needed. 只需根据需要调整我的示例。

For the final steps, you will need to compile both your C and assembly files into object files, link the object files and then execute. 对于最后的步骤,您需要将C和汇编文件编译为目标文件,链接目标文件然后执行。

I hope this helps. 我希望这有帮助。

For x86_64, note that you have to be careful with some extra things: 对于x86_64,请注意你必须小心一些额外的东西:

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

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