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


    http://blog.chinaunix.net/uid-27018250-id-3867588.html

    bss 未初始化的全局数据

    data 已经初始化的全局数据

    text 代码段,机器指令

    rodata 字符串常量

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

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

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

    点击(此处)折叠或打开

    1. int printf(const char* format, ...);
    2. int global_init_var = 84; //已初始化的全局变量
    3. int global_uninit_var;    //未初始化的全局变量
    4. char *str1 = "hello world!"; //字符串常量
    5. void func1(int i)
    6. {
    7.   printf("%d ", i);
    8. }
    9. int main(void)
    10. {
    11.   static int static_var = 85; //已初始化的静态局部变量
    12.   static int static_var2;     //未初始化的静态局部变量 
    13.   char *str2 = "22222";       //字符串常量
    14.   int a = 1;
    15.   int b;
    16.   func1(static_var+static_var2+a+b);
    17.   return a;
    18. }


    上面代码保存为1.c,编译生成目标文件1.o:

    点击(此处)折叠或打开

    1. gcc -c 1.c

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

    点击(此处)折叠或打开

    1. objdump -s -d 1.o


    目标文件结构和内容如下(只保留.bss段、.text段、.data段、.rodata段):

    点击(此处)折叠或打开

    1. 1.o: file format elf32-i386
    2. Contents of section .text:
    3.  0000 5589e583 ec188b45 08894424 04c70424 U......E..D$...$
    4.  0010 0d000000 e8fcffff ffc9c355 89e583e4 ...........U....
    5.  0020 f083ec20 c7442414 11000000 c7442418 ... .D$......D$.
    6.  0030 01000000 8b150800 0000a100 00000001 ................
    7.  0040 c28b4424 1801c28b 44241c01 d0890424 ..D$....D$.....$
    8.  0050 e8fcffff ff8b4424 18c9c3            ......D$... 
    9. Contents of section .data:
    10.  0000 54000000 00000000 55000000          T.......U... 
    11. Contents of section .rodata:
    12.  0000 68656c6c 6f20776f 726c6421 0025640a hello world!.%d.
    13.  0010 00323232 323200                     .22222. 
    14.     
    15. Disassembly of section .text:
    16. 00000000 <func1>:
    17.    0:    55                     push %ebp
    18.    1:    89 e5                  mov %esp,%ebp
    19.    3:    83 ec 18               sub $0x18,%esp
    20.    6:    8b 45 08               mov 0x8(%ebp),%eax
    21.    9:    89 44 24 04            mov %eax,0x4(%esp)
    22.    d:    c7 04 24 0d 00 00 00   movl $0xd,(%esp)
    23.   14:    e8 fc ff ff ff         call 15 <func1+0x15>
    24.   19:    c9                     leave 
    25.   1a:    c3                     ret 
    26. 0000001b <main>:
    27.   1b:    55                       push %ebp
    28.   1c:    89 e5                    mov %esp,%ebp
    29.   1e:    83 e4 f0                 and $0xfffffff0,%esp
    30.   21:    83 ec 20                 sub $0x20,%esp
    31.   24:    c7 44 24 14 11 00 00     movl $0x11,0x14(%esp)
    32.   2b:    00 
    33.   2c:    c7 44 24 18 01 00 00     movl $0x1,0x18(%esp)
    34.   33:    00 
    35.   34:    8b 15 08 00 00 00        mov 0x8,%edx
    36.   3a:    a1 00 00 00 00           mov 0x0,%eax
    37.   3f:    01 c2                    add %eax,%edx
    38.   41:    8b 44 24 18              mov 0x18(%esp),%eax
    39.   45:    01 c2                    add %eax,%edx
    40.   47:    8b 44 24 1c              mov 0x1c(%esp),%eax
    41.   4b:    01 d0                    add %edx,%eax
    42.   4d:    89 04 24                 mov %eax,(%esp)
    43.   50:    e8 fc ff ff ff           call 51 <main+0x36>
    44.   55:    8b 44 24 18              mov 0x18(%esp),%eax
    45.   59:    c9                       leave 
    46.   5a:    c3                       ret

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

    点击(此处)折叠或打开

    1. Contents of section .data:
    2.  0000 54000000 00000000 55000000 T.......U...

    因为已初始化的全局变量和已初始化的局部静态变量经常放在.data段里,因为偶的CPUX86是小端,低字节放低位,54000000转化十进制为84,55000000转化为十进制为85,刚好对应代码中的global_init_var = 84和static_var = 85。

    然后我们来看一下.rodata段的数据:

    点击(此处)折叠或打开

    1. Contents of section .rodata:
    2.  0000 68656c6c 6f20776f 726c6421 0025640a hello world!.%d.
    3.  0010 00323232 323200                     .22222.

    .rodata里面你可以看到有个数据,分别为“hello world!”、“%d ”、"22222",这三个数据分别对应了代码中的三个字符串常量。所以字符串常量一般放在“.rodata”段里。

    接下来就是代码段.text:

    点击(此处)折叠或打开

    1. Contents of section .text:
    2.  0000 5589e583 ec188b45 08894424 04c70424 U......E..D$...$
    3.  0010 0d000000 e8fcffff ffc9c355 89e583e4 ...........U....
    4.  0020 f083ec20 c7442414 11000000 c7442418 ... .D$......D$.
    5.  0030 01000000 8b150800 0000a100 00000001 ................
    6.  0040 c28b4424 1801c28b 44241c01 d0890424 ..D$....D$.....$
    7.  0050 e8fcffff ff8b4424 18c9c3            ......D$...

    看到.text段中的两个以"55 89 e5 83 ec ec 18 8b 45"和"89 e5 83 e4 f0 83 ec 20"开头的数据。分别对应汇编代码编译以后的机器指令(十六进制数据相同),见如下:

    点击(此处)折叠或打开

    1. Disassembly of section .text:
    2. 00000000 <func1>:
    3.    0:    55                       push %ebp
    4.    1:    89 e5                    mov %esp,%ebp
    5.    3:    83 ec 18                 sub $0x18,%esp
    6.    6:    8b 45 08                 mov 0x8(%ebp),%eax
    7.    9:    89 44 24 04              mov %eax,0x4(%esp)
    8.    d:    c7 04 24 0d 00 00 00     movl $0xd,(%esp)
    9.   14:    e8 fc ff ff ff           call 15 <func1+0x15>
    10.   19:    c9                       leave 
    11.   1a:    c3                       ret 
    12. 0000001b <main>:
    13.   1b:    55                       push %ebp
    14.   1c:    89 e5                    mov %esp,%ebp
    15.   1e:    83 e4 f0                 and $0xfffffff0,%esp
    16.   21:    83 ec 20                 sub $0x20,%esp
    17.   24:    c7 44 24 14 11 00 00     movl $0x11,0x14(%esp)
    18.   2b:    00 
    19.   2c:    c7 44 24 18 01 00 00     movl $0x1,0x18(%esp)
    20.   33:    00 
    21.   34:    8b 15 08 00 00 00        mov 0x8,%edx
    22.   3a:    a1 00 00 00 00           mov 0x0,%eax
    23.   3f:    01 c2                    add %eax,%edx
    24.   41:    8b 44 24 18              mov 0x18(%esp),%eax
    25.   45:    01 c2                    add %eax,%edx
    26.   47:    8b 44 24 1c              mov 0x1c(%esp),%eax
    27.   4b:    01 d0                    add %edx,%eax
    28.   4d:    89 04 24                 mov %eax,(%esp)
    29.   50:    e8 fc ff ff ff           call 51 <main+0x36>
    30.   55:    8b 44 24 18              mov 0x18(%esp),%eax
    31.   59:    c9                       leave 
    32.   5a:    c3                       ret

    所以说代码编译后的机器指令经常被放在代码段里。

    再看一下.bss段,输入命令:

    点击(此处)折叠或打开

    1. objdump -x -s -d 1.o

    查看:

    点击(此处)折叠或打开

    1. Sections:
    2. Idx Name Size VMA LMA File off Algn
    3. 2 .bss 00000004 00000000 00000000 0000009c 2**2
    4.                   ALLOC

    看到.bss的大小为4,《程序员自我修养》上说只有static_var2存放到.bss段,而global_uninit_var只是一个未定义的“COMMON符号“没有放在任何段里,这是跟不同的语言与不同的编译器实现有关。看完书后在来补充吧。

    最后,说bbs段在文件中不不占用空间,请参考下面代码:
    1.

    点击(此处)折叠或打开

    1. #include <stdio.h>
    2. int main(void)
    3. {
    4.   return 0;
    5. }

    编译查看大小:

    点击(此处)折叠或打开

    1. root@women:/usr/local/src# gcc -c 1.c
    2. root@women:/usr/local/src# size 1.o
         text       data        bss        dec        hex    filename
           66          0          0         66         42    2.o
    3. root@women:/usr/local/src# ls -l 1.o
    4. -rw-r--r-- 1 root root 852 8月 27 11:03 2.o


    2.比上面代码多了16字节的”int a[10] = {0};“

    点击(此处)折叠或打开

    1. #include <stdio.h>
    2. int a[10] = {0};
    3. int main(void)
    4. {
    5.   return 0;
    6. }

    再来编译查看大小:

    点击(此处)折叠或打开

    1. root@women:/usr/local/src# gcc -c 2.c
    2. root@women:/usr/local/src# ll 2.o
    3. -rw-r--r-- 1 root root 868 8月 27 11:13 2.o
    4. root@women:/usr/local/src# size 2.o
    5.    text     data     bss     dec     hex    filename
    6.      66     0     40     106     6a    2.o

    两段代码便以后,BSS段大小发生了变化多了40个字节,但是实际文件大小只相差16个字节,刚好就是加入代码的”int a[10] = {0};“这十六个字节。所以说bbs段在文件中不不占用空间。

  • 相关阅读:
    Lc20-Valid Parentheses
    Lc262-行程和用户
    Lc197-Rising Temperature
    Lc196-删除重复的电子邮箱
    Lc185-部门工资前三高的所有员工
    Lc18-四数之和
    Lc17-电话号码的字母组合
    Netty Java NIO 基本介绍 之 Selector,ServerSocketChannel , SocketChannel (二)
    Netty(二)工作原理模型
    Netty 异步模型
  • 原文地址:https://www.cnblogs.com/diegodu/p/5603886.html
Copyright © 2020-2023  润新知