2017-04-07 15 views
0

我知道全局數據將存儲在.BSS或.data段中。啓動時存儲的函數內部定義的本地數據在哪裏

但是,如果我在函數內部定義了一些結構數據(如結構體),那麼只有在調用該函數時纔會將該結構放置在堆棧上。

在函數調用之前,編譯器在啓動時何處存儲此數據? 我知道編譯器會根據目標和調用約定等生成不同的彙編代碼,但通常情況下,這個局部結構不會先存儲在某處,以便編譯器知道如何在函數返回時將其放在堆棧上叫什麼名字?提前致謝。

+0

如果你的意思是局部變量被初始化,那麼初始化確實必須存儲在某個地方(很可能是數據段),除非它非常簡單(可能全部字節爲零)。但這是C調用函數時未將本地(自動)變量設置爲預定值的原因的一部分;需要時間/空間來處理通常會被覆蓋的初始化。 –

+0

但是,它是如何知道每次調用結構時都會將結構放在那裏,大小,偏移量等等?這些信息是否存儲在某個地方? – Engineer999

+0

是的,它存儲在某個地方 - 我建議它可能是數據部分,但是我沒有在您的機器上解析生成的彙編語言以查看它是如何完成的;事實上,我沒有檢查我的機器)。編譯器/鏈接器的工作是確保它正確地發生。該標準沒有規定必須如何完成;它只是強制要達到這個效果。 –

回答

0

在全局變量(也是靜態本地)的情況下:
編譯器訪問全局變量作爲特定地址和大小的內存部分。地址最初是一個佔位符(很像變量的名稱)。大小是隱含的,取決於編譯器在彙編/機器代碼中選擇了哪種訪問類型。鏈接器/加載器知道大小,它確保下一個變量不重疊。
地址佔位符在鏈接(例如嵌入式,靜態,就地執行)或加載(例如PC上的應用程序,應用程序)期間被替換。

在局部變量的情況下:
「地址」的值,它被寫入到佔位符,是相對的,對在啓動函數的時間堆疊位置的「頂部」的偏移量。
其他方式與全球佔位符的值相同。堆棧中的位置受訪問哪個變量的影響,可選地爲結構成員使用子偏移量。實際地址被確定爲堆棧位置(即堆棧指針的值)加上在佔位符中找到的相對偏移量。

佔位符實際上是偏移量列表,存儲在一個二進制文件(例如program.exe)中,以及實際的二進制代碼。就像「當你決定在內存中找到這個變量的位置,然後在這裏列出的代碼中的所有地方寫下地址:...」。寫入這些地方將例如在一個字節中放置一個有意義的值,該字節在執行期間將被解釋爲相對「MOV」彙編程序指令的文字偏移量;相對於例如一個指向BSS段開始的段指針。

簡而言之,地址信息在佔位符列表中。這些列表migth根本不在內存中找到,或者不在執行時。一旦程序被加載(包括填充佔位符),這些列表就不再需要了。
大小信息是代碼的一部分(例如,使用8位訪問或32位訪問),它是可變位置佈局的一部分。在前面的變量之後,每個訪問都足夠遠。

因此,即使更短,您所查找的信息在執行過程中一半隱藏,一半不在內存中。

我假設你的問題不是關於變量內的值。只是爲了掩飾它:該值被初始化爲0,一個不變的初始化值,或者特殊情況,根本不存在,在啓動時保留內存中的任何內容。 init值在基本上是常量列表的部分中找到。找到給定變量的常量的位置與佔位符相似。
在局部變量的情況下,編譯器通常不會初始化,但可以配置爲寫入0(這是一種「昂貴的」)。這就是爲什麼在使用它們之前初始化變量是很好的做法。具有顯式初始化的局部變量當然是在堆棧幀設置期間初始化的。