6

私は次のことを理解しようとしています:

C の小さな Hello World プログラムが与えられた場合

#include <stdio.h>

int main()
{
    int i;
    for(i=0; i < 10; i++)
    {
        printf("Hello, world!\n");
    }
}

これを gcc でコンパイルし、結果の .out ファイルを objdump を使用して調べると、次のような結果が得られます。

08048374 <main>:
8048374:       55                      push   ebp
8048375:       89 e5                   mov    ebp,esp
8048377:       83 ec 08                sub    esp,0x8
804837a:       83 e4 f0                and    esp,0xfffffff0
804837d:       b8 00 00 00 00          mov    eax,0x0
8048382:       29 c4                   sub    esp,eax
8048384:       c7 45 fc 00 00 00 00    mov    DWORD PTR [ebp-4],0x0
804838b:       83 7d fc 09             cmp    DWORD PTR [ebp-4],0x9
804838f:       7e 02                   jle    8048393 <main+0x1f>
8048391:       eb 13                   jmp    80483a6 <main+0x32>
8048393:       c7 04 24 84 84 04 08    mov    DWORD PTR [esp],0x8048484
804839a:       e8 01 ff ff ff          call   80482a0 <printf@plt>
804839f:       8d 45 fc                lea    eax,[ebp-4]
80483a2:       ff 00                   inc    DWORD PTR [eax]
80483a4:       eb e5                   jmp    804838b <main+0x17>
80483a6:       c9                      leave  
80483a7:       c3                      ret    
80483a8:       90                      nop    
80483a9:       90                      nop    
80483aa:       90                      nop    

結果の .out ファイルの値の最初の列はメモリ アドレスです。私の理解が正しければ、これらのアドレスには他の列に続く命令が含まれています。

ここで私の質問: ファイルを別のマシン (または同じマシンの別の場所) にコピーし、ファイルを再度ダンプすると、プログラムはメモリ内の別の場所にあるため、これらのアドレスは別のものに変更されるはずです。正しいですか? しかし、それを行うと、まったく同じ出力、同じアドレス値が得られます。何故ですか?この最初の列の意味を明らかに誤解しています。誰か、これらのアドレスが正確に何であるかを説明してもらえますか? 前もって感謝します!

更新:私が今理解しているように、Paul R の回答とさらにウィキペディアを読んだおかげで、これらのアドレスは、コードが実行されるマシンのオペレーティング システムによってコードが実行される仮想アドレス空間を参照しています。これらの仮想アドレスは、オペレーティング システムによって実際のマシンの絶対アドレスにマップされます。

4

2 に答える 2

8

左の列のアドレスは、実行時にコードがロードされる (仮想) アドレスです。コードが位置に依存しない場合を除き、正しく実行するにはこれらのアドレスにロードする必要があります。

于 2012-08-09T11:00:26.710 に答える
2

32ビットOSのすべてのプロセスは、独自の4GB仮想メモリ領域で実行されます。この領域はカーネルとプロセスの間で共有され、通常は3GB / 1GBのメモリ分割として使用されます。ここで、0x00000000から始まる下位3GBのメモリ領域はアプリケーションによって使用され、上位1GBはカーネルによって使用されます。

ここで、アプリケーションの下位3GBのユーザースペース領域を検討すると、領域はさらに、テキストセグメント、初期化されたデータセグメント、初期化されていないデータセグメントなどのさまざまなセグメントに分割されます。

したがって、作成したコードは、この例では08048374から始まるテキスト領域に配置されます。

したがって、アセンブリコード全体は、リンク段階で事前定義されているため、実行に使用するマシンに関係なく、この仮想アドレスに配置されます。したがって、このアドレスは変更されません。お役に立てれば。

于 2012-08-09T11:27:16.833 に答える