从x86汇编语言调用C函数 [英] Calling C functions from x86 assembly language

查看:421
本文介绍了从x86汇编语言调用C函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否有可能产生使用GCC的C函数汇编语言功能,让他们可以从汇编语言程序调用?我知道,GCC编译C到机器code(这可以很容易地分解成汇编语言),我已经知道,它可能的用C 联汇编语言功能,但我还没有找到一种方法,从汇编语言程序调用C函数,这基本上是这样的倒数。

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

  .686p
.MODEL平,STDCALL
.STACK 2048。数据。code
开始:调用了ExitProcess,0printSomething PROC;现在我试图在这里内联C函数
    无效printSomething(thingToPrint){
        的printf(这是我想从汇编语言程序调用C函数。);
        输出(一定有办法做到这一点 - 这可能不知?);
    }
printSomething ENDP年底启动


解决方案

我从内存会在这里,所以我可能会关闭小幅一个或两个细节。但是,应该我希望足以让你在正确的方向前进。

您会需要告诉你的日常 printSomething()未在汇编文件中定义的GCC汇编。在C,你会使用的extern 关键字。对于装配您将需要使用 .globl

  .globl printSomething

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

接下来的一个大问题是我怎么传递参数?这很大程度上取决于你的处理器和操作系统。由于你的问题的标题所示的x86,我会假设你使用的是16位或32位模式和标准的x86 ABI(相对于X86-64这也是不同于Windows和Linux之间)。 C型参数被他们推入堆栈传递给调用程序。他们被压入堆栈从右到左。

因此​​,

  printSomething(ARG1,ARG2,ARG3,ARG4);

转换为...

  pushl ARG4
pushl ARG3
pushl ARG2
pushl ARG1
调用printSomething
ADDL $ 0×10,ESP%

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

  ADDL $ 0×10,ESP%

?我们通过(又名推)4个32位参数的例程(入堆栈)。虽然常规知道要期待这些参数,这是不负责弹出他们堆栈。来电者是负责的。所以,当我们从常规的回报,我们调整堆栈指针丢弃4个32位的参数我们previously压入堆栈。

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

  PUSHW ARG4
PUSHW ARG3
PUSHW ARG2
PUSHW ARG1
调用printSomething
ADDW $ 0x8中,SP%

我意识到,在你的榜样, printSomething()只需要一(1)参数,并在我的例子中,我使用了四个(4)。因为需要调整只是我举的例子。

对于最后一个步骤,您将需要编译两个C和汇编文件到目标文件,链接的目标文件,然后执行。

我希望这有助于。

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.

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?

.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

解决方案

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 extern keyword. For assembly you will need to use .globl.

.globl printSomething

If you are using a different assembler than GCC's, the keyword may be different.

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.

Thus,

printSomething (arg1, arg2, arg3, arg4);

translates to ...

pushl arg4
pushl arg3
pushl arg2
pushl arg1
call  printSomething
addl  $0x10, %esp

You may be asking yourself, what is this

addl $0x10, %esp

? 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.

In the above example, I am assuming that we are operating in 32-bit mode. If it were 16-bit mode, it would be ...

pushw arg4
pushw arg3
pushw arg2
pushw arg1
call  printSomething
addw  $0x8, %sp

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.

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.

I hope this helps.

这篇关于从x86汇编语言调用C函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆