1

我一直在玩 GCC 的程序集输出开关:

gcc -S -c helloworld.c

helloworld.c

#include <stdio.h>

int main(void){
    printf("Hello World!\n");
    return 0;
}

helloworld.s

    .file   "helloworld.c"
    .section    .rodata
.LC0:
    .string "Hello World!"
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    $.LC0, %edi
    call    puts
    movl    $0, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (Debian 4.7.2-5) 4.7.2"
    .section    .note.GNU-stack,"",@progbits

在输出helloworld.s文件中,我注意到汇编命令输出“Hello World!” 文字很简单:

call puts

但是,该helloworld.s1文件中没有puts过程汇编代码。我在哪里可以查看此汇编代码?

4

3 回答 3

7

编辑:这实际上不是原始问题的答案,但由于它得到了赞成,信息似乎很有用,所以......


这是 GCC 的优化。由于您的字符串不包含任何格式字符并以换行符结尾,因此 GCC 替换了puts产生相同输出但速度更快的调用(因为它不需要扫描字符串以查找格式说明符)。尝试类似:

int main(int argc, char *argv[]){
    printf("Hello World!\nargc=%d", argc);
    return 0;
}

你会printf在大会上看到你的。

于 2013-03-19T14:52:25.473 回答
2

答案

使用 gcc 标志-fno-builtin

说明

为了提高性能,GCC、Glibc 将共同对标准 C 库进行一些修改。由于 GCC 和 Glibc 几乎适用于所有用户空间应用程序,因此内置函数默认打开,它将printf()只有一个参数的puts()函数调用转换为函数调用。

您还可以通过使用诸如-fno-builtin-printf. 是您可以阻止 GCC 转换的内置函数的完整列表。

是标志的详细说明。

于 2013-03-20T06:47:36.657 回答
2

正如用户unwind提到的:

这是因为您的 C 程序期望与其中包含的标准 C 运行时库链接puts()。如果您愿意,您当然可以在反汇编时挖掘系统上的库文件。

于是我用objdump反汇编libc.a,在section下找到了汇编代码<puts>objdump -d /usr/lib/x86_64-linux-gnu/libc.a

于 2013-03-24T20:03:20.570 回答