2012-08-09 34 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