首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从x86汇编语言调用C函数

从x86汇编语言调用C函数
EN

Stack Overflow用户
提问于 2013-04-27 18:39:32
回答 2查看 49.9K关注 0票数 31

用GCC的C函数生成汇编语言函数,可以从汇编语言程序中调用汇编语言函数吗?我知道gcc将C编译成机器代码(可以很容易地分解成汇编语言),而且我已经知道inline assembly language functions in C是可能的,但是我还没有找到从汇编语言程序调用C函数的方法,这基本上是相反的。

在这里,我试图在x86程序中内联一个C函数。如果内联是不可能的,那么还有其他方法从汇编语言程序调用C函数吗?

代码语言:javascript
运行
复制
.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
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-04-28 13:43:21

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

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

代码语言:javascript
运行
复制
.globl printSomething

如果您使用的汇编程序与GCC的不同,关键字可能是不同的。

下一个大问题是“我该如何传递论点”?这在很大程度上取决于处理器和操作系统。由于问题的标题表示x86,我将假设您使用的是16位或32位模式和标准x86 ABI (与x86-64不同,x86-64在x86和Linux之间也不同)。C参数通过将它们推到堆栈上传递给调用的例程。它们从右向左推到堆栈上。

因此,

代码语言:javascript
运行
复制
printSomething (arg1, arg2, arg3, arg4);

翻译成..。

代码语言:javascript
运行
复制
pushl arg4
pushl arg3
pushl arg2
pushl arg1
call  printSomething
addl  $0x10, %esp

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

代码语言:javascript
运行
复制
addl $0x10, %esp

?我们将四个32位参数传递给例程(也就是推到堆栈上)。尽管例程知道需要这些参数,但它并不负责将它们从堆栈中弹出。打电话的人对此负责。因此,在我们从例程返回后,我们调整堆栈指针,以丢弃我们先前推到堆栈上的四个32位参数。

在上面的例子中,我假设我们是在32位模式下工作.如果是16位模式的话.

代码语言:javascript
运行
复制
pushw arg4
pushw arg3
pushw arg2
pushw arg1
call  printSomething
addw  $0x8, %sp

我意识到在您的示例中,printSomething()只使用一个(1)参数,在我的示例中使用了四个(4)。只要调整我的例子是必要的。

对于最后的步骤,您需要将C文件和程序集文件编译成对象文件,链接对象文件,然后执行。

我希望这能帮到你。

票数 37
EN

Stack Overflow用户

发布于 2019-05-27 15:17:15

对于x86_64,请注意,您必须小心处理一些额外的事情:

  • 在进行C调用之前,堆栈必须对齐16位. 如果在程序集中定义函数,调用函数的函数会将返回值放入堆栈中,使其不对齐,因此必须以某种方式减去8个字节,通常是push %rbp。 这把我带到了这里,例如:64 assembly function lead to segmentation fault (SIGSEGV) instead of an abort signal?
  • 如果您出于某种原因正在从程序集中执行call (TODO为什么要这样做?)你必须担心:

代码语言:javascript
运行
复制
- marking all the non-callee saved registers as clobbered
- the red zone for your arguments

下面是一个例子:Calling printf in extended inline ASM

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16255608

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档