编译了c程序存储器地址

时间:2012-08-09 10:56:46

标签: c memory gcc assembly gdb

我想了解以下内容:

给出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的回答以及其他一些维基百科阅读,这些地址引用了一个虚拟地址空间,其中代码由运行它的机器的操作系统执行。这些虚拟地址由其操作系统映射到实际机器上的绝对地址。

2 个答案:

答案 0 :(得分:7)

左列中的地址是运行时代码为loaded的(虚拟)地址。除非代码为position-independent,否则需要在这些地址加载才能正确运行。

答案 1 :(得分:1)

32位操作系统中的每个进程都在其自己的4GB虚拟内存区域中运行。这个区域在内核和进程之间共享,通常是3GB / 1GB内存分区,应用程序使用从0x00000000开始的较低3GB内存区域,而内核使用较高的1GB内存区域。

现在,如果我们考虑应用程序的较低3GB用户空间区域,该区域将进一步划分为不同的段,如文本段,初始化数据段,未初始化数据段等。

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

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