编译器对数据的分配

注明: 以下结论的可靠性不予担保。

1. 实验方法

  1. 给出两个C++源代码文件,主要文件如下,辅助文件定义了全局变量g_ext, g_ext_ini。
    #include <stdio.h>
    extern int g_ext;
    extern int g_ext_ini;
    int g_a=10, g_b, g_array1[15], g_array2[5];
    int main()
    {
            int i = 0;
            i = g_array1[3] + g_array2[0] + g_a + g_b+g_ext + g_ext_ini;    
            printf("i=%d\n", i);
            return 0;
    }

  2. 用#gcc -g global.c命令得到二进制文件global;再利用dwarfdump工具输出其调试信息,global.c对应的部分调试信息如下:
    <2><  145>	DW_TAG_variable                                                // 局部变量i
    		DW_AT_name                  i
    		DW_AT_decl_file             1 /home/rallylee/Develop/test/global/global.c
    		DW_AT_decl_line             7
    		DW_AT_type                  <79>
    		DW_AT_location              DW_OP_breg4+28
    <1><  158>	DW_TAG_variable                                                // 全局变量
    		DW_AT_name                  g_ext                                        
    		DW_AT_decl_file             1 /home/rallylee/Develop/test/global/global.c
    		DW_AT_decl_line             2
    		DW_AT_type                  <79>
    		DW_AT_external              yes(1)
    		DW_AT_declaration           yes(1)
    <1><  171>	DW_TAG_variable                                                // 全局变量
    		DW_AT_name                  g_ext_ini
    		DW_AT_decl_file             1 /home/rallylee/Develop/test/global/global.c
    		DW_AT_decl_line             3
    		DW_AT_type                  <79>
    		DW_AT_external              yes(1)
    		DW_AT_declaration           yes(1)
    <1><  184>	DW_TAG_variable                                                // 全局变量
    		DW_AT_name                  g_a
    		DW_AT_decl_file             1 /home/rallylee/Develop/test/global/global.c
    		DW_AT_decl_line             4
    		DW_AT_type                  <79>
    		DW_AT_external              yes(1)
    		DW_AT_location              DW_OP_addr 0x804a014
    <1><  202>	DW_TAG_variable                                                // 全局变量
    		DW_AT_name                  g_b
    		DW_AT_decl_file             1 /home/rallylee/Develop/test/global/global.c
    		DW_AT_decl_line             4
    		DW_AT_type                  <79>
    		DW_AT_external              yes(1)
    		DW_AT_location              DW_OP_addr 0x804a09c
    <1><  220>	DW_TAG_array_type
    		DW_AT_type                  <79>
    		DW_AT_sibling               <236>
    <2><  229>	DW_TAG_subrange_type
    		DW_AT_type                  <107>
    		DW_AT_upper_bound           14
    <1><  236>	DW_TAG_variable
    		DW_AT_name                  g_array1
    		DW_AT_decl_file             1 /home/rallylee/Develop/test/global/global.c
    		DW_AT_decl_line             4
    		DW_AT_type                  <220>
    		DW_AT_external              yes(1)
    		DW_AT_location              DW_OP_addr 0x804a060
    <1><  254>	DW_TAG_array_type
    		DW_AT_type                  <79>
    		DW_AT_sibling               <270>
    <2><  263>	DW_TAG_subrange_type
    		DW_AT_type                  <107>
    		DW_AT_upper_bound           4
    <1><  270>	DW_TAG_variable
    		DW_AT_name                  g_array2
    		DW_AT_decl_file             1 /home/rallylee/Develop/test/global/global.c
    		DW_AT_decl_line             4
    		DW_AT_type                  <254>
    		DW_AT_external              yes(1)
    		DW_AT_location              DW_OP_addr 0x804a040
    可以看出,定义的变量分配了地址;声明的外部变量没有分配地址。
  3. 利用pin工具,得到global运行时的指令序列,进而得到该序列的反汇编序列(左边),与原来的global.s文件进行对比:
  4. ...省略其它函数调用
    
    %push ebp
    %mov ebp, esp
    %and esp, 0xfffffff0
    %sub esp, 0x20
    %mov dword ptr [esp+0x1c], 0x0
    %mov edx, dword ptr [0x804a06c]
    %mov eax, dword ptr [0x804a040]
    %add edx, eax
    %mov eax, dword ptr [0x804a014]
    %add edx, eax
    %mov eax, dword ptr [0x804a09c]
    %add edx, eax
    %mov eax, dword ptr [0x804a0a0]
    %add edx, eax
    %mov eax, dword ptr [0x804a018]
    %lea eax, ptr [edx+eax*1]
    %mov dword ptr [esp+0x1c], eax
    %mov eax, 0x80484e0
    %mov edx, dword ptr [esp+0x1c]
    %mov dword ptr [esp+0x4], edx
    %mov dword ptr [esp], eax
    %call 0x80482f4
    
    ...省略其它函数调用
    
    %mov eax, 0x0
    %leave 
    %ret 
    
    ...省略其它函数调用
    
    .globl main
            .type   main, @function
    main:
    .LFB0:
            .file 1 "global.c"
            .loc 1 6 0
            .cfi_startproc
            pushl   %ebp
    .LCFI0:
            .cfi_def_cfa_offset 8
            movl    %esp, %ebp
            .cfi_offset 5, -8
    .LCFI1:
            .cfi_def_cfa_register 5
            andl    $-16, %esp
            subl    $32, %esp
            .loc 1 7 0
            movl    $0, 28(%esp)
            .loc 1 8 0
            movl    g_array1+12, %edx
            movl    g_array2, %eax
            addl    %eax, %edx
            movl    g_a, %eax
            addl    %eax, %edx
            movl    g_b, %eax
            addl    %eax, %edx
            movl    g_ext, %eax
            addl    %eax, %edx
            movl    g_ext_ini, %eax
            leal    (%edx,%eax), %eax
            movl    %eax, 28(%esp)
            .loc 1 9 0
            movl    $.LC0, %eax
            movl    28(%esp), %edx
            movl    %edx, 4(%esp)
            movl    %eax, (%esp)
            call    printf
            .loc 1 10 0
            movl    $0, %eax
            .loc 1 11 0
            leave

  5. 可以看出:
    • 编译时给全局变量分配的逻辑地址,在运行时没有发生变化。
    • 编译时给局部变量生成的是基于ESP寄存器的地址表达式,运行时会计算出该表达式的值。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值