在哪里可以找到GCC组件输出中调用的过程的汇编代码?

时间:2013-03-19 14:36:14

标签: c linux gcc assembly disassembly

我一直在玩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 过程汇编代码。我在哪里可以查看这个汇编代码?

3 个答案:

答案 0 :(得分:7)

编辑:这实际上并不是原始问题的答案,但由于它正在上调,因此信息似乎很有用,所以......


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

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

你会在集会中看到你的printf

答案 1 :(得分:2)

<强>答案

使用gcc标志-fno-builtin

<强>释

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

您还可以通过使用-fno-builtin-printf等标志告诉GCC不要转换特定的内置函数调用。 Here是内置函数的完整列表,您可以阻止GCC转换。

here是旗帜的详细解释。

答案 2 :(得分:1)

正如用户unwind所述:

  

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

所以我使用 objdump 来反汇编libc.a并找到<puts>部分下的汇编代码:objdump -d /usr/lib/x86_64-linux-gnu/libc.a