如何用内联asm编译这个程序?

时间:2013-08-10 03:58:02

标签: c gcc assembly x86 inline-assembly

我无法编译从教程中获取的程序。它应该打印“Hello World”。

void main() 
{
    __asm__("jmp forward\n\t"
            "backward:\n\t"
            "popl   %esi\n\t"
            "movl   $4, %eax\n\t"
            "movl   $2, %ebx\n\t"
            "movl   %esi, %ecx\n\t"
            "movl   $12, %edx\n\t"
            "int    $0x80\n\t"
            "int3\n\t"
            "forward:\n\t"
            "call   backward\n\t"
            ".string \"Hello World\\n\""
           );
}
Linux下的

gcc 4.7给出了以下错误:

gcc hello.c -o hello
hello.c: Assembler messages:
hello.c:5: Error: invalid instruction suffix for `pop'

还有办法避免为每一行指定双引号吗?

此外,我想知道如何修改程序以使用libc来电printf而不是kernel服务。

1 个答案:

答案 0 :(得分:10)

hello.c: Assembler messages:
hello.c:5: Error: invalid instruction suffix for `pop'

popl在x86-32上可用,但在x86-64上没有(它有popq)。您需要调整汇编代码以使用x86-64,或者需要调用GCC来生成x86-32二进制输出。

假设您要生成x86-32,请使用命令行选项-m32

  

还有办法避免为每一行指定双引号吗?

A :没有。这是因为__asm__()是一个伪函数,它接受字符串参数,因此该字符串遵循C语法。字符串的内容在很少或没有处理的情况下传递给汇编程序。

请注意,在C中,当并置字符串时,它们会连接在一起。例如,"a" "b""ab"相同。

请注意,在汇编语言语法(GAS)中,您可以按换行符或分号分隔语句,如:"movl xxx; call yyy""movl xxx \n call yyy"

  

如何修改程序以使用libc调用printf

A :关注calling convention for C on x86。从右到左推送参数,调用函数,然后清理堆栈。例如:

pushl $5678  /* Second number */
pushl $1234  /* First number */
pushl $fmtstr
call printf
addl $12, %esp  /* Pop 3 arguments of 4 bytes each */

/* Put this away from the code */
fmtstr: .string "Hello %d %d\n"  /* The \n needs to be double-backslashed in C */