操做系统:ubuntu 13.04
工具:gcc, objdump, readelf
参考:《程序员自我修养》
代码编译后的机器指令常常被放在代码风中的小蘑菇,代码段名为”.text”;已初始化的全局变量和已初始化的局部静态变量常常放在数据风中的小蘑菇,数据段名为”.data”;未初始化的全局变量和未初始化局部静态变量通常放在“.bss”风中的小蘑菇,.bss在文件中不占据空间。字符串常量通常放在“.rodata”风中的小蘑菇。
经过代码编译后查看文件内部结构来论证一下上面观点,代码以下:
代码:程序员
点击(此处)折叠或打开ubuntu
int?printf(const?char*?format,?…);
int?global_init_var?=?84;?//已初始化的全局变量
int?global_uninit_var;??? //未初始化的全局变量
char?*str1?=?”hello world!”;?//字符串常量
void func1(int?i)
{
printf(“%d\n”,?i);
}
int?main(void)
{
static?int?static_var?=?85;?//已初始化的静态局部变量
static?int?static_var2;?????//未初始化的静态局部变量
char?*str2?=?”22222″;?????? //字符串常量
int?a?=?1;
int?b;
func1(static_var+static_var2+a+b);
return a;
}
上面代码保存为1.c,编译生成目标文件1.o:c#
点击(此处)折叠或打开sass
gcc?-c 1.c
使用objdump来查看目标文件的结构和内容,命令以下:
工具
点击(此处)折叠或打开ui
objdump?-s?-d 1.o
目标文件结构和内容以下(只保留.bss段、.text段、.data段、.rodata段):操作系统
点击(此处)折叠或打开.net
1.o:?file format elf32-i386
Contents of section?.text:
0000 5589e583 ec188b45 08894424 04c70424 U……E..D$…$
0010 0d000000 e8fcffff ffc9c355 89e583e4?………..U….
0020 f083ec20 c7442414 11000000 c7442418?…?.D$……D$.
0030 01000000 8b150800 0000a100 00000001?…………….
0040 c28b4424 1801c28b 44241c01 d0890424?..D$….D$…..$
0050 e8fcffff ff8b4424 18c9c3 ? ? ? ? ???……D$…
Contents of section?.data:
0000 54000000 00000000 55000000 ? ? ? ?? T…….U…
Contents of section?.rodata:
0000 68656c6c 6f20776f 726c6421 0025640a hello world!.%d.
0010 00323232 323200 ? ? ? ? ? ? ? ? ? ??.22222.
Disassembly of section?.text:
00000000?:
0:????55 ????????????????????push?%ebp
1:????89 e5 ???????????????? mov?%esp,%ebp
3:????83 ec 18 ????????????? sub?$0x18,%esp
6:????8b 45 08 ????????????? mov 0x8(%ebp),%eax
9:????89 44 24 04 ?????????? mov?%eax,0x4(%esp)
d:????c7 04 24 0d 00 00 00 ? movl $0xd,(%esp)
14:????e8 fc ff ff ff ??????? call?15?
19:????c9 ????????????????????leave
1a:????c3 ????????????????????ret
0000001b?:
1b:????55 ????????????????????? push?%ebp
1c:????89 e5 ?????????????????? mov?%esp,%ebp
1e:????83 e4 f0 ???????????? ?? and?$0xfffffff0,%esp
21:????83 ec 20 ??????????????? sub?$0x20,%esp
24:????c7 44 24 14 11 00 00 ????movl $0x11,0x14(%esp)
2b:????00
2c:????c7 44 24 18 01 00 00 ????movl $0x1,0x18(%esp)
33:????00
34:????8b 15 08 00 00 00 ?????? mov 0x8,%edx
3a:????a1 00 00 00 00 ????????? mov 0x0,%eax
3f:????01 c2 ?????????????????? add?%eax,%edx
41:????8b 44 24 18 ???????????? mov 0x18(%esp),%eax
45:????01 c2 ?????????????????? add?%eax,%edx
47:????8b 44 24 1c ???????????? mov 0x1c(%esp),%eax
4b:????01 d0 ?????????????????? add?%edx,%eax
4d:????89 04 24 ??????????????? mov?%eax,(%esp)
50:????e8 fc ff ff ff ??????????call?51?
55:????8b 44 24 18 ???????????? mov 0x18(%esp),%eax
59:????c9 ????????????????????? leave
5a:????c3 ????????????????????? ret
咱们先来看一下.data风中的小蘑菇数据:unix
点击(此处)折叠或打开
Contents of section?.data:
0000 54000000 00000000 55000000 T…….U…
由于已初始化的全局变量和已初始化的局部静态变量常常放在.data风中的小蘑菇,由于偶的CPUX86是小端,低字节放低位,54000000转化十进制为84,55000000转化为十进制为85,恰好对应代码中的global_init_var?=?84和static_var?=?85。
而后咱们来看一下.rodata段的数据:
点击(此处)折叠或打开
Contents of section?.rodata:
vps云服务器
0000 68656c6c 6f20776f 726c6421 0025640a hello world!.%d.
0010 00323232 323200 ? ? ? ? ? ? ? ? ? ??.22222.
.rodata里面你能够看到有个数据,分别为“hello world!”、“%d\n”、”22222″,这三个数据分别对应了代码中的三个字符串常量。因此字符串常量通常放在“.rodata”风中的小蘑菇。
接下来就是代码段.text:
点击(此处)折叠或打开
Contents of section?.text:
0000?5589e583 ec188b45?08894424 04c70424 U……E..D$…$
0010 0d000000 e8fcffff ffc9c355?89e583e4?………..U….
0020?f083ec20?c7442414 11000000 c7442418?…?.D$……D$.
0030 01000000 8b150800 0000a100 00000001?…………….
0040 c28b4424 1801c28b 44241c01 d0890424?..D$….D$…..$
0050 e8fcffff ff8b4424 18c9c3 ? ? ? ? ???……D$…
看到.text段中的两个以”55 89 e5 83 ec ec 18 8b 45″和”89 e5 83 e4 f0 83 ec 20″开头的数据。分别对应汇编代码编译之后的机器指令(十六进制数据相同),见以下:
点击(此处)折叠或打开
Disassembly of section?.text:
00000000?:
0:????55?????????????????????? push?%ebp
1:????89 e5??????????????????? mov?%esp,%ebp
3:????83 ec 18?????????????????sub?$0x18,%esp
6:????8b 45?08 ?? ? ? ???????? mov 0x8(%ebp),%eax
9:????89 44 24 04 ???????????? mov?%eax,0x4(%esp)
d:????c7 04 24 0d 00 00 00 ????movl $0xd,(%esp)
14:????e8 fc ff ff ff ??????????call?15?
19:????c9 ????????????????????? leave
1a:????c3 ????????????????????? ret
0000001b?:
1b:????55?????????????????????? push?%ebp
1c:????89 e5??????????????????? mov?%esp,%ebp
1e:????83 e4 f0?????????????????and?$0xfffffff0,%esp
21:????83 ec 20?????????????????sub?$0x20,%esp
24:????c7 44 24 14 11 00 00 ????movl $0x11,0x14(%esp)
2b:????00
2c:????c7 44 24 18 01 00 00 ????movl $0x1,0x18(%esp)
33:????00
34:????8b 15 08 00 00 00 ?????? mov 0x8,%edx
3a:????a1 00 00 00 00 ????????? mov 0x0,%eax
3f:????01 c2 ?????????????????? add?%eax,%edx
41:????8b 44 24 18 ???????????? mov 0x18(%esp),%eax
45:????01 c2 ?????????????????? add?%eax,%edx
47:????8b 44 24 1c ???????????? mov 0x1c(%esp),%eax
4b:????01 d0 ?????????????????? add?%edx,%eax
4d:????89 04 24 ??????????????? mov?%eax,(%esp)
50:????e8 fc ff ff ff ??????????call?51?
55:????8b 44 24 18 ???????????? mov 0x18(%esp),%eax
59:????c9 ????????????????????? leave
5a:????c3 ????????????????????? ret
因此说代码编译后的机器指令常常被放在代码风中的小蘑菇。
再看一下.bss段,输入命令:
点击(此处)折叠或打开
objdump?-x?-s?-d 1.o
查看:
点击(此处)折叠或打开
Sections:
Idx?Name?Size?VMA LMA File off Algn
2?.bss 00000004 00000000 00000000 0000009c 2**2
ALLOC
看到.bss的大小为4,《程序员自我修养》上说只有static_var2存放到.bss段,而global_uninit_var只是一个未定义的“COMMON符号“没有放在任何风中的小蘑菇,这是跟不一样的语言与不一样的编译器实现有关。看完书后在来补充吧。
最后,说bbs段在文件中不不占用空间,请参考下面代码:
1.
点击(此处)折叠或打开
#include?
int?main(void)
{
return 0;
}
编译查看大小:
点击(此处)折叠或打开
root@women:/usr/local/src# gcc -c 1.c
root@women:/usr/local/src# size 1.o
text?? ??? data?? ???? bss?? ???? dec?? ???? hex?? ?filename
66?? ?????? 0?? ?????? 0?? ????? 66?? ????? 42?? ?2.o
root@women:/usr/local/src# ls?-l 1.o
-rw-r–r–?1 root root 852 8月 27 11:03 2.o
2.比上面代码多了16字节的”int?a[10]?=?{0};“
点击(此处)折叠或打开
#include?
int?a[10]?=?{0};
int?main(void)
{
return 0;
}
再来编译查看大小:
点击(此处)折叠或打开
root@women:/usr/local/src# gcc?-c 2.c
root@women:/usr/local/src# ll 2.o
-rw-r–r–?1 root root 868 8月 27 11:13 2.o
root@women:/usr/local/src# size 2.o
text???? data???? bss???? dec?????hex????filename
66???? 0???? 40???? 106???? 6a????2.o
两段代码便之后,BSS段大小发生了变化多了40个字节,可是实际文件大小只相差16个字节,恰好就是加入代码的”int?a[10]?=?{0};“这十六个字节。因此说bbs段在文件中不不占用空间。