7

我无法编译这个取自教程的程序。它应该打印“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\""
           );
}

gcc 4.7在Linux下给我以下错误:

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

还有一种方法可以避免为每一行指定双引号吗?

另外,我想知道如何修改程序以使用libccallprintf而不是kernel服务。

4

1 回答 1

10

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

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

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

还有一种方法可以避免为每一行指定双引号吗?

:没有。这是因为__asm__()它是一个接受字符串参数的伪函数,所以字符串遵循 C 语法。字符串的内容被传递给汇编程序,很少或根本没有处理。

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

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

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

:遵循x86 上 C 的调用约定。从右向左推送参数,调用函数,然后清理堆栈。例子:

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 */
于 2013-08-10T04:24:03.110 回答