コンパイラによるデータの割り当て


以下の結論の信頼性は保証されません.
1.実験方法
  • は2つの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
    ", i); return 0; }
  • 用#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
    は、定義された変数がアドレスを割り当てていることを示す.宣言された外部変数にはアドレスが割り当てられていません.
  • pinツールを用いてglobal実行時の命令シーケンスを得る、さらにそのシーケンスの逆アセンブリシーケンス(左側)を得て、元のglobal.sファイルと比較する:
  • .
  • ...        
    
    %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

  • には、
  • が表示されます.
  • コンパイル時にグローバル変数に割り当てられた論理アドレスは、実行時に変化しません.
  • コンパイル時に局所変数に生成されるのはESPレジスタベースのアドレス式であり、実行時にその式の値が計算される.