LINUX下目标文件的BSS段、数据段、代码段

操作系统:ubuntu 13.04
工具:gcc, objdump, readelf

参考:《程序员自我修养》

代码编译后的机器指令经常被放在代码段里,代码段名为".text";已初始化的全局变量和已初始化的局部静态变量经常放在数据段里,数据段名为".data";未初始化的全局变量和未初始化局部静态变量一般放在“.bss”段里,.bss在文件中不占据空间。字符串常量一般放在“.rodata”段里。

通过代码编译后查看文件内部结构来论证一下上面观点,代码如下:

代码:

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:

gcc -c 1.c

使用objdump来查看目标文件的结构和内容,命令如下:

objdump -s -d 1.o
目标文件结构和内容如下(只保留.bss段、.text段、.data段、.rodata段):
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 <func1>:
   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 <func1+0x15>
  19:    c9                     leave 
  1a:    c3                     ret 

0000001b <main>:
  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 <main+0x36>
  55:    8b 44 24 18              mov 0x18(%esp),%eax
  59:    c9                       leave 
  5a:    c3                       ret

我们先来看一下.data段里数据:

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:
 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 <func1>:
   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 <func1+0x15>
  19:    c9                       leave 
  1a:    c3                       ret 

0000001b <main>:
  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 <main+0x36>
  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 <stdio.h>

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 <stdio.h>

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段在文件中不不占用空间。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
众所周知,人工智能是当前最热门的话题之一, 计算机技术与互联网技术的快速发展更是将对人工智能的研究推向一个新的高潮。 人工智能是研究模拟和扩展人类智能的理论与方法及其应用的一门新兴技术科学。 作为人工智能核心研究领域之一的机器学习, 其研究动机是为了使计算机系统具有人的学习能力以实现人工智能。 那么, 什么是机器学习呢? 机器学习 (Machine Learning) 是对研究问题进行模型假设,利用计算机从训练数据中学习得到模型参数,并最终对数据进行预测和分析的一门学科。 机器学习的用途 机器学习是一种通用的数据处理技术,其包含了大量的学习算法。不同的学习算法在不同的行业及应用中能够表现出不同的性能和优势。目前,机器学习已成功地应用于下列领域: 互联网领域----语音识别、搜索引擎、语言翻译、垃圾邮件过滤、自然语言处理等 生物领域----基因序列分析、DNA 序列预测、蛋白质结构预测等 自动化领域----人脸识别、无人驾驶技术、图像处理、信号处理等 金融领域----证券市场分析、信用卡欺诈检测等 医学领域----疾病鉴别/诊断、流行病爆发预测等 刑侦领域----潜在犯罪识别与预测、模拟人工智能侦探等 新闻领域----新闻推荐系统等 游戏领域----游戏战略规划等 从上述所列举的应用可知,机器学习正在成为各行各业都会经常使用到的分析工具,尤其是在各领域数据量爆炸的今天,各行业都希望通过数据处理与分析手段,得到数据中有价值的信息,以便明确客户的需求和指引企业的发展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值