从c调用汇编函数

我想从一个C项目中调用一个汇编中的函数。 这个函数应该调用一个libc函数,让我们说printf() ,但是我一直得到一个分段错误。

在.c文件中,我有这个函数的声明

 int do_shit_in_asm() 

在.asm文件中我有

 .extern printf .section .data printtext: .ascii "test" .section .text .global do_shit_in_asm .type do_shit_in_asm, @function do_shit_in_asm: pushl %ebp movl %esp, %ebp push printtext call printf movl %ebp, %esp pop %ebp ret 

任何指针评论将不胜感激。

 as func.asm -o func.o gcc prog.c func.o -o prog 

Solutions Collecting From Web of "从c调用汇编函数"

push printtext更改为push $printtext

实际上,您正在从地址printtext加载一个值,并推送该值,而不是推送地址。 因此,你传递'test''test'作为一个32位的数字,而不是一个指针, printf正试图把它解释为一个地址并且崩溃。

开始使用汇编语言函数的最好方法之一是在C中编写一个类似的函数,然后使用编译器开关构建汇编语言(在gcc上为-S )。 然后,您可以研究编译器的输出,并根据需要进行修改。

如果您正在调用使用不同调用约定的printf (由于参数数量可变),此功能特别有用。 调用这些函数可能与调用非可变参数函数完全不同。

问题是我正在使用

 pushl printtext 

比较起来

 pushl $printtext 

感谢大家的帮助,并为此浪费时间:P

在这之后:

 push printtext call printf 

你要:

 addl $4, %esp 

进一步解释:

因为你使用x86 Linux,所以我认为调用约定需要被调用者清理参数。 因为在调用printf之前你已经按下了一个指针,所以在该函数的ret指令发生之后,你的堆栈被关闭了4。

更新:

是的,好吧,我已经习惯了英特尔的语法,所以我把自己的观点倒在脑后。 实际上缺少addlesp并不重要,因为你正在靠近你的ret正确地恢复esp 。 我的下一个猜测是,你传递给printf的字符串缺少一个空终止符…让我看看是什么gas

更新2:

好的, gas null会为你终止字符串,所以我想我的第二个预感是错误的。 看起来你发现这个问题,所以重点是没有意义的。