プログラミング序論 page11a(update:2017/06/29)

11a.コンパイルとリンク

VisualStadioでのコンパイルとリンクの結果を見てみる。

ソースファイル

extern int ExternFunction(void);/*外部関数のプロトタイプ宣言*/
extern int ExternValue;/*外部変数の宣言*/
static int StaticFunction(void)/*内部結合の関数*/
{
    return 1;
}

int main(void)
{
    static int s=2;/*静的変数かつ局所変数*/
    int ret;/*自動変数かつ局所変数*/
    
    ret=StaticFunction();
    ret+=ExternValue;
    ret+=ExternFunction(s);
    return ret; 
}
int ExternFunction(int s)/*外部結合の関数*/
{
    return 2*s;
}
int ExternValue = 5;/*外部結合の大域変数*/

オブジェクトファイル

main関数内の自動変数はすでにアドレスとの対応付けが行われているが,静的変数と関数については名前のみが記録され,アドレス部分は0で埋められていることが分かる。

※main関数の局所的な静的変数sもアドレスは未定で,リンクでアドレスと対応付けされる。このstaticな局所変数と内部変数を同じ静的メモリ領域に割り当てているので,リンクまでアドレスが決まらないのが原因だろうか?

RAW DATA #3  
  00000000: 05 00 00 00 02 00 00 00 <<静的変数 ExternValue と s

_ExternFunction:
  00000000: 55                 push        ebp
  00000001: 8B EC              mov         ebp,esp
  00000003: 8B 45 08           mov         eax,dword ptr [ebp+8]
  00000006: D1 E0              shl         eax,1
  00000008: 5D                 pop         ebp
  00000009: C3                 ret

_StaticFunction:
  00000010: 55                 push        ebp
  00000011: 8B EC              mov         ebp,esp
  00000013: B8 01 00 00 00     mov         eax,1
  00000018: 5D                 pop         ebp

_main:
  00000020: 55                 push        ebp
  00000021: 8B EC              mov         ebp,esp
  00000023: 51                 push        ecx
  00000024: E8 00 00 00 00     call        _StaticFunction <<結合前でアドレスは0で埋めている
  00000029: 89 45 FC           mov         dword ptr [ebp-4],eax <<mainの自動変数retのアドレスはebp-4
  0000002C: 8B 45 FC           mov         eax,dword ptr [ebp-4]
  0000002F: 03 05 00 00 00 00  add         eax,dword ptr [_ExternValue]
  00000035: 89 45 FC           mov         dword ptr [ebp-4],eax
  00000038: 8B 0D 00 00 00 00  mov         ecx,dword ptr [?s@?1??main@@9@9]<<mainの局所変数sのこと
  0000003E: 51                 push        ecx
  0000003F: E8 00 00 00 00     call        _ExternFunction
  00000044: 83 C4 04           add         esp,4
  00000047: 03 45 FC           add         eax,dword ptr [ebp-4]
  0000004A: 89 45 FC           mov         dword ptr [ebp-4],eax
  0000004D: 8B 45 FC           mov         eax,dword ptr [ebp-4]
  00000050: 8B E5              mov         esp,ebp
  00000052: 5D                 pop         ebp
  00000053: C3                 ret

実行可能ファイル

長いので関係の薄い部分は省いている。

リンクにより結合結果を代入して,オブジェクトでは名前であった部分が,実行可能ファイルではアドレスに書き変わっている。

...............................................
  00401000: 55                 push        ebp
  00401001: 8B EC              mov         ebp,esp
  00401003: 8B 45 08           mov         eax,dword ptr [ebp+8]
  00401006: D1 E0              shl         eax,1
  00401008: 5D                 pop         ebp
  00401009: C3                 ret
...............................................
  00401010: 55                 push        ebp
  00401011: 8B EC              mov         ebp,esp
  00401013: B8 01 00 00 00     mov         eax,1
  00401018: 5D                 pop         ebp
  00401019: C3                 ret
..............................................
  00401020: 55                 push        ebp
  00401021: 8B EC              mov         ebp,esp
  00401023: 51                 push        ecx
  00401024: E8 E7 FF FF FF     call        00401010 <<call命令の機械語は相対アドレスで負の値
  00401029: 89 45 FC           mov         dword ptr [ebp-4],eax
  0040102C: 8B 45 FC           mov         eax,dword ptr [ebp-4]
  0040102F: 03 05 00 30 41 00  add         eax,dword ptr ds:[00413000h]
  00401035: 89 45 FC           mov         dword ptr [ebp-4],eax
  00401038: 8B 0D 04 30 41 00  mov         ecx,dword ptr ds:[00413004h]
  0040103E: 51                 push        ecx
  0040103F: E8 BC FF FF FF     call        00401000
  00401044: 83 C4 04           add         esp,4
  00401047: 03 45 FC           add         eax,dword ptr [ebp-4]
  0040104A: 89 45 FC           mov         dword ptr [ebp-4],eax
  0040104D: 8B 45 FC           mov         eax,dword ptr [ebp-4]
  00401050: 8B E5              mov         esp,ebp
  00401052: 5D                 pop         ebp
  00401053: C3                 ret
..............................................
  00413000: 05 00 00 00 02 00 00 00 FF FF FF FF 01 00 00 00 <<静的変数 ExternValue と s

call命令の跳び先は機械語では相対アドレス

call命令の跳び先は機械語では相対アドレスで記述されているので負の値になっている。

アセンブラではこれを絶対アドレスに換算して示してくれている。

  
00401024: E8 E7 FF FF FF     call        00401010 
00401029: 89 45 FC           mov         dword ptr [ebp-4],eax

call命令の次の機械語の番地00401029を基準としてFFFFFFE7を加算すると桁あふれした部分を無視すれば
00401010となる

※上位のバイトは上位の番地に格納する方式なので「E7 FF FF FF 」の値はFFFFFFE7