6

我试图了解以下内容:

给定一个 C 语言的小型 Hello World 程序

#include <stdio.h>

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

当您使用 gcc 编译它,然后使用 objdump 检查生成的 .out 文件时,您会得到如下内容:

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

The addresses in the left column are the (virtual) addresses at which your code will be loaded when it's run. Unless the code is position-independent it will need to be loaded at these addresses to run correctly.

于 2012-08-09T11:00:26.710 回答
2

Every process in a 32-bit OS runs in its own 4GB virtual memory area. This area is shared between the kernel and your process, normally in as a 3GB/1GB memory split, where the lower 3GB memory area starting from 0x00000000 is used by the application while the upper 1GB is used by the kernel.

Now if we consider the lower 3GB user space area of the application, the area is further divided into different segments such as text segment, initialized data segment, uninitialized data segment etc.

因此,您编写的代码放置在该文本区域中,在您的示例中恰好从 08048374 开始。

因此,整个汇编代码都放置在这个虚拟地址中,而不管您用来运行它的任何机器,因为这是在链接阶段预先定义的。因此,该地址不会改变。希望这可以帮助。

于 2012-08-09T11:27:16.833 回答