2012-08-09 28 views
4

我想了解以下信息:编译的C程序存储器地址

考虑用C

#include <stdio.h> 

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

小Hello World程序当你用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 <[email protected]> 
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文件生成的第一列中的内存地址,如果我理解正确的话,这些地址续ain其他栏中的说明。

现在我的问题:如果您将文件复制到另一台计算机(甚至是同一台计算机上的不同位置)并再次转储文件,这些地址应该更改为其他位置,因为程序将位于不同的位置记忆,正确?但如果我这样做,我会得到完全相同的输出,相同的地址值。这是为什么?我明显误解了这第一列的含义,有人请向我解释这些地址究竟是什么?提前致谢!

更新: 现在我明白了,得益于Paul R的回答以及更多维基百科的阅读,这些地址引用了一个虚拟地址空间,其中的代码由运行它的机器的操作系统执行。这些虚拟地址通过操作系统映射到实际机器上的绝对地址。

+0

我想你误解了内存和磁盘的概念。该地址是_memory_中的地址(也称为RAM,以保持简单),而_disk_中不使用这些地址。我建议你多了解一下计算机的基本架构,比如磁盘和内存之间的区别。 – 2012-08-09 11:01:54

+0

“这些地址应该更改为其他内容,因为程序将位于内存中的不同位置,对吗?” - 你没有处理内存中的程序,你正在处理一个目标文件,最终将被加载到内存中。 – 2012-08-09 11:21:20

+0

我明白内存和磁盘之间的区别,我的困惑来自于不知道这些地址是虚拟的 – Asciiom 2012-08-09 11:46:18

回答

6

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

+0

我同意,但他们是相对地址,不是吗? – Razvan 2012-08-09 11:02:22

+0

@Razvan:不一定 - 它取决于代码是否与位置无关。 – 2012-08-09 11:04:11

+2

一般来说,在标准操作系统中,它们不应该是相对地址吗?难道把它们变成绝对地址并不复杂吗?因为你不能保证内存是可用的吗? – Razvan 2012-08-09 11:10:56

1

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

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

所以,代码,您写入被放置在恰好从您的示例中的08048374开始的文本区域中。

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

+0

您应该明确说明您在答案中提到的4 GB,3 GB等的大小仅限于典型的32位虚拟内存操作系统,或者可能会使答案更普遍适用。 – 2012-08-09 11:40:52

+0

是的。编辑上面的答案以反映32位OS参考,同时描述每个进程的4GB虚拟机可用性。谢谢保罗。 – 2012-08-09 13:17:37