簡體   English   中英

C編譯程序使用哪些段?

[英]What segments does C compiled program use?

我在OSDev wiki上看到,x86架構的保護模式允許您為代碼和數據創建單獨的段,而您無法寫入代碼段。 Windows(是的,這是平台)將新代碼加載到代碼段中,並在數據段上創建數據。 但是,如果是這種情況,程序如何知道它必須將段切換到數據段? 如果我理解正確,所有地址指令都指向您運行代碼的段,除非您切換描述符。 但我也讀到,如此流行的平面內存模型允許您在一個段內運行代碼和數據。 但我只在與匯編程序有關的情況下閱讀此內容。 那么,請問,Windows上的C編譯代碼是什么情況? 謝謝。

您閱讀的信息已過時。 自1993年以來的Windows版本使用平坦的32位虛擬內存空間。 CS和DS段寄存器的值不再重要,無法更改。 現在仍然存在代碼與數據的概念,現在由內存頁屬性實現。 查看在VirtualProtectEx()API函數的flNewProtect參數中傳遞的允許值。

您很少自己使用此API,屬性由可執行映像加載程序和堆管理器設置。

解釋中的有兩個含義:

  • 8086內存地址段
  • 對象模塊程序部分段

第一個與加載到80386+段寄存器中的內容有關; 它包含一個物理內存起始地址,內存分配長度,允許的讀/寫/執行訪問,以及它是從低到高增長,反之亦然(加上一些更模糊的標志,如“復制引用”)。

第二個含義是目標模塊語言的一部分。 基本上,有一個名為code的段,一個名為data的段(包含初始化的數據),以及一個名為bss未初始化數據的段(以20世紀60年代匯編程序的偽指令命名,表示Block Starting with Symbol )。 當鏈接器組合對象模塊時,它將所有代碼段排列在一起,將所有數據段排列在其他地方,並將bss放在一起。 當加載程序映射內存地址時,它會查看總代碼空間並分配至少該大小的CPU內存分配,並將該段映射到代碼(在虛擬內存情況下)或將代碼讀入已分配的內存中 - 它必須暫時將內存設置為可寫數據。 寫保護通過CPU的分頁機制以及段寄存器完成。 這是為了保護代碼寫入嘗試,例如,通過錯誤的數據地址。 加載程序也為兩個數據段組執行類似的設置。 (除此之外,還有設置堆棧段並分配它,並映射共享映像。)

就x86執行指令而言,每個操作數都有一個相關的段寄存器。 有時這些是明確的,有時它們是隱含的。 通過CS隱式訪問代碼,通過SS進行堆棧,無論何時涉及ESPEBP寄存器,都隱含代碼,並且對大多數其他操作數隱含DS ESFSGS必須在所有其他情況下指定為覆蓋,但某些字符串指令(如movscmps 在平面模型中,盡管CS不允許寫入,但所有段寄存器都映射到相同的地址空間。

因此,為了回答您的上一個問題,CPU一次設置了四個(或更多)段寄存器,以訪問進程的扁平虛擬內存空間。 檢查每個操作數訪問是否適合於該指令(如不增加CS地址),並且還由尋呼保護單元檢查是否允許。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM