是否可以使用GCC从C函数生成汇编语言函数,以便可以从汇编语言程序调用它们?我知道gcc将C编译为机器代码(很容易被反汇编成汇编语言),我已经知道inline assembly language functions in C可能了,但我还没有找到一种从汇编语言调用C函数的方法程序,基本上与此相反。
在这里,我试图在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
答案 0 :(得分:22)
我要从记忆中走出来,所以我可能会稍微偏离一两个细节。但是,我希望能够让你朝着正确的方向前进。
您需要告诉GCC汇编程序您的例程 printSomething()未在汇编文件中定义。在“C”中,您可以使用 extern 关键字。对于装配,您需要使用 .globl 。
.globl printSomething
如果您使用的是与GCC不同的汇编程序,则关键字可能会有所不同。
下一个重要问题是“如何传递参数”?这在很大程度上取决于您的处理器和OS。由于您的问题标题表示x86,我将假设您使用的是16位或32位模式和标准x86 ABI(而不是x86-64,Windows和Linux之间也不同)。通过将C参数推入堆栈,将C参数传递给被调用的例程。它们从右到左被推到堆栈上。
因此,
printSomething (arg1, arg2, arg3, arg4);
转换为......
pushl arg4
pushl arg3
pushl arg2
pushl arg1
call printSomething
addl $0x10, %esp
你可能会问自己,这是什么
addl $0x10, %esp
?我们将四个32位参数传递(通过推送)到例程(进入堆栈)。虽然例程知道期望这些参数,但它不负责将它们从堆栈中弹出。来电者对此负责。因此,在我们从例程返回之后,我们调整堆栈指针以丢弃之前压入堆栈的四个32位参数。
在上面的例子中,我假设我们在32位模式下运行。如果它是16位模式,它将是......
pushw arg4
pushw arg3
pushw arg2
pushw arg1
call printSomething
addw $0x8, %sp
我意识到在你的例子中, printSomething()只接受一(1)个参数,在我的例子中我使用了四(4)个。只需根据需要调整我的示例。
对于最后的步骤,您需要将C和汇编文件编译成目标文件,链接目标文件然后执行。
我希望这会有所帮助。
答案 1 :(得分:1)
对于x86_64,请注意一些额外的事项:
在进行C调用之前,堆栈必须对齐16位。
如果您在汇编中定义函数,则调用您函数的函数会将返回值放在堆栈中,并使其未对齐,因此您必须以某种方式减去另外8个字节,通常为push %rbp
。
如果出于某种原因(例如为什么要这么做,为什么要做call
汇编程序),则您必须担心: