2013-04-27 71 views
9

是否可以使用GCC从C函数生成汇编语言函数,以便可以从汇编语言程序中调用它们?我知道gcc将C编译为机器代码(可以很容易地将其拆分成汇编语言),并且我已经知道可以对inline assembly language functions in C进行编译,但是我还没有找到从汇编语言程序调用C函数的方法,它是基本上与此相反。从x86汇编语言中调用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

我不记得所有的细节,但你只需要编译目标文件并将它们链接在一起。您只需要知道调用该函数时使用的调用约定。 – 2013-04-27 18:44:54

+1

您可以添加显示您尝试过的汇编代码,并告诉它如何编译失败或其行为错误。答案指出它有什么问题会容易得多。 – hyde 2013-04-27 18:47:53

+3

你可以通过编写一个C函数来学习如何做到这一点,C函数调用你想调用的函数,将其编译为汇编语言('-S'),并研究结果。我也会将您指向“psABI”,但我再也找不到副本了。 – zwol 2013-04-27 18:59:49

回答

17

我从这里回忆,所以我可能会在一两个细节上稍微偏离。不过,我希望这足以让你朝着正确的方向前进。

您将需要告诉GCC汇编程序,您的例程printSomething()没有在您的程序集文件中定义。在'C'中,您可以使用extern关键字。对于装配,您需要使用.globl

.globl printSomething 

如果使用与GCC不同的汇编器,关键字可能会有所不同。

下一个大问题是'我该如何传递参数'?这非常依赖于你的处理器和操作系统。由于问题的标题指示x86,因此我将假设您正在使用16位或32位模式以及标准x86 ABI(与Windows和Linux之间的x86-64不同)。 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和汇编文件编译为目标文件,链接目标文件然后执行。

我希望这会有所帮助。

+0

现在我想知道是否可以使用GCC从C函数实际生成x86汇编程序。是否有可能将C程序中的每个函数转换为等效的汇编语言函数,使用GCC或其他C编译器? – 2013-05-09 23:24:04

+1

@AndersonGreen - 您可以随时尝试使用-S选项。 “gcc -S file.c”会将“file.c”转换为程序集(将其命名为file.s)。或者,如果您已经拥有可执行文件,则可以使用“objdump -d exe_file> exe_file.asm”反汇编“exe_file”并将结果转储为“exe_file.asm”。 – Sparky 2013-05-10 02:06:51

+0

@Sparky在x86程序约定中,每个函数在返回给调用者之前都有'leave'或等价指令。我认为在你的例子中'addl $ 0x10,%esp'是多余的。 – StrikeW 2015-08-22 06:35:52