从x86汇编语言调用C函数

And*_*een 18 c x86 assembly

是否可以使用GCC从C函数生成汇编语言函数,以便可以从汇编语言程序调用它们?我知道gcc将C编译为机器代码(很容易被反汇编成汇编语言),我已经知道可以在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
Run Code Online (Sandbox Code Playgroud)

Spa*_*rky 23

我要从记忆中走出来,所以我可能会稍微偏离一两个细节.但是,我希望能够让你朝着正确的方向前进.

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

.globl printSomething
Run Code Online (Sandbox Code Playgroud)

如果您使用的是与GCC不同的汇编程序,则关键字可能会有所不同.

下一个重要问题是"如何通过论证"?这在很大程度上取决于您的处理器和OS.由于您的问题标题表示x86,我将假设您使用的是16位或32位模式和标准x86 ABI(而不是x86-64,Windows和Linux之间也不同).通过将C参数推入堆栈,将C参数传递给被调用的例程.它们从右到左被推到堆叠上.

从而,

printSomething (arg1, arg2, arg3, arg4);
Run Code Online (Sandbox Code Playgroud)

转换为......

pushl arg4
pushl arg3
pushl arg2
pushl arg1
call  printSomething
addl  $0x10, %esp
Run Code Online (Sandbox Code Playgroud)

你可能会问自己,这是什么

addl $0x10, %esp
Run Code Online (Sandbox Code Playgroud)

?我们将四个32位参数传递(通过推送)到例程(进入堆栈).虽然例程知道期望这些参数,但它不负责将它们从堆栈中弹出.来电者对此负责.因此,在我们从例程返回之后,我们调整堆栈指针以丢弃先前推入堆栈的四个32位参数.

在上面的例子中,我假设我们在32位模式下运行.如果它是16位模式,它将是......

pushw arg4
pushw arg3
pushw arg2
pushw arg1
call  printSomething
addw  $0x8, %sp
Run Code Online (Sandbox Code Playgroud)

我意识到在你的例子中,printSomething()只接受一(1)个参数,在我的例子中我使用了四(4).只需根据需要调整我的示例.

对于最后的步骤,您需要将C和汇编文件编译为目标文件,链接目标文件然后执行.

我希望这有帮助.

  • @AndersonGreen - 您始终可以尝试使用 -S 选项。“gcc -S file.c”会将“file.c”转换为程序集(将其命名为file.s)。或者,如果您已经有了可执行文件,则可以使用“objdump -d exe_file > exe_file.asm”来反汇编“exe_file”并将结果转储到“exe_file.asm”中。 (2认同)