假设我们写了一个C代码文件 code.c包含下面代码:
代码语言:javascript复制int accum = 0;
int sum(int x, int y)
{
int t = x y;
accum = t;
return t;
}
这是用echo命令输入源码的效果,简单的就是最好的:)
一、查看GCC生成的汇编代码
在命令行上用“-S”选项,就能看到C编译器产生的汇编代码:
#gcc -S code.c
注意:这里是大写的-S,如果用小写gcc会说找不到main函数
会在当前目录下生成code.s文件,直接打开即可
这段汇编代码没有经过优化:
代码语言:javascript复制 .file "code.c"
.globl _accum
.bss
.align 4
_accum:
.space 4
.text
.globl _sum
.def _sum; .scl 2; .type 32; .endef
_sum:
pushl �p
movl %esp, �p
subl $4, %esp # 为局部变量t在栈帧上分配空间
movl 12(�p), �x # �x <- y
addl 8(�p), �x # �x <- x y
movl �x, -4(�p) # t <- x y
movl -4(�p), �x # �x <- t
addl �x, _accum # _accum <- t _accum
movl -4(�p), �x # �x <- t
leave # 平衡堆栈: %esp <- �p , popl �p
ret
下面是使用“-O2”选项开启二级优化的效果:
代码语言:javascript复制 #gcc -O2 -S code.c
.file "code.c"
.globl _accum
.bss
.align 4
_accum:
.space 4
.text
.p2align 4,,15 # 使下一条指令的地址从16的倍数处开始,
.globl _sum # 最多浪费15个字节
.def _sum; .scl 2; .type 32; .endef
_sum:
pushl �p # 保存原�p
movl %esp, �p
movl 12(�p), �x # �x <- y
movl 8(�p), �x # �x <- x
popl �p # 恢复原�p
addl �x, �x # �x <- x y
addl �x, _accum # _accum <- _accum x y
ret
GCC产生的汇编代码有点难读,它包含一些我们不关心的信息。所有以 "." 开头的行都是指导汇编器和链接器的命令,称为“汇编器命令”。
代码中已经除去了所有关于局部变量名或数据类型的信息,但我们还是看到了一个对全局变量_accum的引用,这是因为编译器还不能确定这个变量会放在存储中的哪个位置。
二、用GDB查看目标文件的字节表示
首先,我们用反汇编器来确定函数sum的代码长度是19字节。然后我们在文件code.o上运行GNU调试工具GDB,输入命令:
(gdb) x/19xb sum
这条命令告诉GDB检查(简写为"x")19个以十六进制格式表示的字节。
三、反汇编目标文件
在Linux系统中,带 "-d" 命令行选项调用OBJDUMP可以完成这个任务:
#objdump -d code.o
从这里可以看出函数sum的代码长度正好是19字节。
四、生成实际可执行的代码
这需要对一组目标文件运行链接器,而这一组目标代码文件中必须包含有一个Main函数。在 main.c 中有这样的函数:
代码语言:javascript复制 int main()
{
return sum(1,2);
}
然后,我们用如下方法生成可执行文件:
代码语言:javascript复制 #gcc -O2 -o prog code.o main.c
再反汇编:
代码语言:javascript复制 objdump -d prog
00401050 <_sum>:
401050: 55 push �p
401051: 89 e5 mov %esp,�p
401053: 8b 45 0c mov 0xc(�p),�x
401056: 8b 55 08 mov 0x8(�p),�x
401059: 5d pop �p
40105a: 01 d0 add �x,�x
40105c: 01 05 10 20 40 00 add �x,0x402010
401062: c3 ret
这段代码与code.c反汇编产生的代码几乎完全一样。一个主要的区别是左边列出的地址不同。第二个不同之处在于链接器终于确定了存贮全局变量accum的地址。地址由原来的0x0变成了现在的0x402010
本文由来源 21aspnet,由 javajgs_com 整理编辑,其版权均为 21aspnet 所有,文章内容系作者个人观点,不代表 Java架构师必看 对观点赞同或支持。如需转载,请注明文章来源。