在討論 32 位 MIPS 架構時,Patterson--Hennessy 解釋說靜態資料段從 開始0x 1000 0000,到 結束0x 1000 FFFF,全域指標$gp默認設定為中間地址0x 1000 8000。據說堆是下一個,因此應該從 開始0x 1001 0000。
然而,一些使用 MARS 的實驗告訴我,中間有一個額外的段,它從0x 1001 0000到0x 1003 FFFF,因此堆只從 開始0x 1004 0000。實際上,當我使用系統呼叫在堆上存盤一個陣列時,該陣列將繼續存盤0x 1004 0000。
當我初始化.data程式頭下的資料時,這個附加段似乎得到了使用。這讓我很困惑,因為我期望初始化的資料.data被認為是靜態的,因此應該存盤在由全域指標控制的段中。
題。行為是否符合MARS標準?如果是,那么這個位于靜態資料和堆之間的附加資料段與位于它前面的靜態資料段有何不同?
uj5u.com熱心網友回復:
你不能太認真地對待這些模擬器。
我沒有理由知道為什么你不能在記憶體中移動東西。聯結器需要知道全域資料符號的位置,以便它可以進行重定位,否則處理器并不關心。
舉例來說,MARS 在“設定”中有一個“記憶體配置”選項,因此,例如,您可以將模擬器設定為記憶體有限的嵌入式處理器,如 64k。
在真實系統上,全域資料將由作業系統程式加載器從程式可執行檔案中加載,資料部分將被放大.bss(最初為零)。然后,通常,堆將從下一個頁面邊界開始。
模擬器不做這些細節——它為所有程式使用一個固定的記憶體模型;因此,例如,它不會像真實系統那樣根據程式集中全域變數的實際數量重新調整堆開始位置。
因此,在我看來,它只是為匯編程式使用的全域存盤保留 256k。
第一個64K使用保留的直接訪問$gp,但MARS默認情況下不放置任何全域資料在那里,如果你強迫資料在0x10000000(通過啟動.data 0x10000000),你可以把符號出現,但這樣做lw $t0, label($gp),其中label內16駐留bitreach of$gp被視為偽指令(擴展為 3 條指令),將 的絕對值添加label到其中的內容$gp然后執行lw- 這將無法正確訪問該全域資料,b/c$gp保存 0x10008000,因此最終會添加兩個指標,當它應該添加label相對于的偏移量時$gp。如果真的想通過正確的 1 指令序列使用全域資料$gp(使用默認記憶體配置模型)您可以使用.eqv而不是定義標簽來定義常量,并自己管理偏移量(是的,但適用于小程式)。
相反,MARS 將默認起始位置.data放在 0x10010000 處,我認為這只是避免了 64k$gp可訪問區域。任何使用資料標簽的指令都被擴展為使用以lui.開頭的多指令序列。
重申一下,在我看來,MARS 只是為匯編程式使用的全域存盤保留 256k,然后在那里啟動堆。
我不會將任何這些解釋為資料和堆之間的另一個部分或段。
此外,如果您閱讀 MARS 默認記憶體配置模型,據說堆疊(下限)限制與堆基數相同,但實際上 MARS 模擬器不會(或不能)實際允許堆疊增長那么大,它會在更高的堆疊位置發出錯誤,真正的限制是 1 或 2 MB 大小。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/374968.html
