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