C语言 从 x86 汇编语言调用 C 函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16255608/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Calling C functions from x86 assembly language
提问by Anderson Green
Is it possible to generate assembly language functions from C functions using GCC, so that they can be invoked from an assembly language program? 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 函数生成汇编语言函数,以便可以从汇编语言程序中调用它们?我知道 gcc 将 C 编译为机器代码(可以很容易地反汇编成汇编语言),并且我已经知道可以在 C 中内联汇编语言函数,但是我还没有找到从汇编中调用 C 函数的方法语言程序,这基本上与此相反。
Here, I'm attempting to inline a C function in an x86 assembly program. If inlining isn't possible, then is there some other way to invoke a C function from an assembly language program?
在这里,我试图在 x86 汇编程序中内联 C 函数。如果内联是不可能的,那么还有其他方法可以从汇编语言程序中调用 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
回答by Sparky
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. In 'C' you would use the externkeyword. For assembly you will need to use .globl.
您将需要告诉 GCC 汇编器您的例程printSomething()未在您的汇编文件中定义。在“C”中,您将使用extern关键字。对于汇编,您需要使用.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. 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). The C parameters are passed to the called routine by pushing them onto the stack. They are pushed onto the stack from right to left.
下一个大问题是“我如何传递参数”?这在很大程度上取决于您的处理器和操作系统。由于您的问题的标题指示 x86,我将假设您使用的是 16 位或 32 位模式以及标准的 x86 ABI(而不是 x86-64,它在 Windows 和 Linux 之间也有所不同)。C 参数通过将它们压入堆栈传递给被调用的例程。它们从右到左被推入堆栈。
Thus,
因此,
printSomething (arg1, arg2, arg3, arg4);
translates to ...
翻译成……
pushl arg4
pushl arg3
pushl arg2
pushl arg1
call printSomething
addl addl pushw arg4
pushw arg3
pushw arg2
pushw arg1
call printSomething
addw ##代码##x8, %sp
x10, %esp
x10, %esp
You may be asking yourself, what is this
你可能会问自己,这是什么
##代码##? We passed (aka pushed) four 32-bit arguments to the routine (onto the stack). 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 位参数传递(也称为推送)到例程(到堆栈上)。尽管例程知道需要这些参数,但它不负责将它们从堆栈中弹出。调用者对此负责。因此,从例程返回后,我们调整堆栈指针以丢弃我们之前压入堆栈的四个 32 位参数。
In the above example, I am assuming that we are operating in 32-bit mode. If it were 16-bit mode, it would be ...
在上面的例子中,我假设我们在 32 位模式下运行。如果是 16 位模式,它将是...
##代码##I realize that in your example, printSomething()only takes one (1) argument and in my example I used four (4). Just adjust my example as is needed.
我意识到在您的示例中,printSomething()仅采用一 (1) 个参数,而在我的示例中,我使用了四 (4) 个参数。只需根据需要调整我的示例。
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.
我希望这有帮助。

