基地址寄存器
出自 MBA智库百科(https://wiki.mbalib.com/)
基地址寄存器(Base Address Register,BAR)
目錄 |
什麼是基地址寄存器[1]
基地址寄存器指基數位移定址系統中存放基地址的寄存器。每條捐令的地址部都記有和基地址對應的相對地址,因此執行時要將基地址和相對地址相加才能得到實際地址。
基地址寄存器的載入[2]
設當前正在執行過程的靜態層號是i,則當前過程調用記錄前部的區頭地址表共i+1個單元。當需要訪問本過程中說明的簡單變數或形式參數時,只要求SP+該變數的位移地址,即得該變數所分配的存儲單元地址。而若要訪問在嵌套深度為k(k<i)的過程中說明的變數或形式參數時,其存儲單元地址為(SP+k)+該變數的位移地址。這樣看來,對程式中變數的存取問題似乎已經解決。但是,由於具體機器指令格式上限制,還需要根據具體機器指令格式,進一步討論這一問題。
機器指令格式是一個和硬體有關的問題。以前面假想的電腦為例,和記憶體有關的機器指令的彙編指令格式是
OP R1,d2(R2)
其中,R2是和第二操作數有關的基地址寄存器,d2則是第二操作數的位移地址。在形成實際地址時,基地址寄存器中地址和位移地址相加
(R2) + d2
得到第二操作數地址。一般說來,機器指令中位移區的位數較少(例如12位),這種指令格式完全是為了縮短每一條指令長度而設計的。但是,它給編譯程式形成有效指令帶來了困難。如果指令的位移區只占12位,則該條指令只能訪問相對於基地址的位移在4095個單元內的存儲單元。對於相對地址超出4095的記憶體單元來說,該條指令是無法進行存取的。要存取相對於基地址的位移在4095個單元外的存儲單元中內容,程式必須首先修改基地址寄存器中地址。由此可見,一個過程數據區從存儲分配上看是一個整體,但從具體指令的編址上看,過程數據區又可以劃分成彼此相連的若幹塊。塊的大小和具體機器指令格式有關。為了訪問塊內某存儲單元,必須首先將該塊的首地址取至基地址寄存器,然後按相對於該塊的首地址的位移量來訪問此存儲單元。
前面說過,r3是代碼生成階段的一個保留寄存器,用做特定的用途。例如,可以規定r3用做基地址寄存器。由於硬體特點,r3還被用來存放轉子指令執行後的下一條指令地址。當程式流進入一個過程時,運行時刻執行的過程數據區初始化子程式將該過程數據區首地址送入基地址寄存器r3。換句話說,當過程體剛開始執行時,當前過程調用記錄的第0塊首地址已在r_3中。如果所訪問的存儲單元落在當前過程調用記錄的第O塊,則代碼生成程式就利用r3和保存在符號表登記項的位移地址直接形成指令;否則,必須修改基地址寄存器的值,即將該存儲單元所屬塊的首地址取至基地址寄存器。這個工作可以讓一個專門子程式CHECKBP完成。
運行時刻子程式CHECKBP工作時需要兩個參數:變數所屬過程的嵌套深度和所屬塊號。變數所屬過程的嵌套深度可以從符號表該標識符所屬登記項中得到。變數所屬塊的塊號也可以從保存在符號表登記項的相對地址求得,用邏輯乘截出該相對地址高位變數,就是所屬塊號。塊號和每塊長度相乘,然後再加上此過程調用記錄首地址就得到塊首址:
- 塊首址=過程調用記錄首址+塊號*塊長度
其中,過程調用記錄首址可以根據變數所屬過程的靜態嵌套深度從當前過程調用記錄的區頭地址表中得到。
為了避免經常調用運行子程式CHECKBP,應當註意到下述程式變數訪問的就近原則:程式員在編製程式時,往往將一段程式中所用到的變數集中在一起進行說明。這就使得在一段程式中所訪問的量往往集中於同一塊或者集中於本過程數據區的第0塊。由於假想電腦的寄存器已經分配完畢,可以在運行程式工作區中設立兩個工作單元SP和BP。SP中存放當前正在執行的過程的調用記錄的首地址,BP則存放當前訪問變數所屬數據塊的首地址。運行子程式CHECKBP並不將變數所屬塊的首地址直接送往r3,而是將此地址送往運行時刻的工作單元BP。運行時刻子程式CHECKBP的代碼書寫工作讀者是不難完成的。
為了知道運行時刻r3、SP和BP的情況,在代碼生成程式中設立三個工作變數X、Y和zoX、Y和Z三個變數各有兩個域:levelno和bloekno,分別記錄了運行時刻r3、SP和BP中地址所對應的過程嵌套深度和塊號。進入過程時,運行時刻的過程數據區初始化子程式將當前過程調用記錄的首地址送人r3、SP和BP。與此相對應的代碼生成程式動作必須將此過程的嵌套深度和第0塊標記0送入變數X、Y和Z中。此後,每當代碼生成程式要生成訪問運行棧存儲單元的指令時,都必須檢查所要訪問的變數的所屬塊首址是否已在寄存器r3中。如果該地址並不在k3中,而在工作單元BP(或工作單元SP)中,則生成將BP值傳送到r3的指令(或SP值傳送到r_3的指令)。否則,代碼生成程式生成轉運行時刻子程式CHECKBP的轉子指令,以便將所屬塊的首地址取至工作單元BP,然後再生成將BP值傳送到r3的指令。上述工作可以由子程式CHECKr3來完成,讀者不難寫出該子程式的代碼。註意,和REGVALUE工作區及REGSTATE工作區必須正確反映上一條指令生成後寄存器的值和狀態的道理一樣,代碼生成程式的工作變數X,Y和z也必須正確反映運行時刻r3,SP和BP中地址所對應的過程嵌套深度和塊號。
基地址寄存器的設定[3]
地址的表示方法是基地址寄存器B加上變址寄存器中的相對地址構成,但是基地址寄存器的設定則需在程式中完成。基地址寄存器的設定方法有兩種:以下以12號寄存器為例說明:
例1:BEGINl START
XXXX USING*,12
SAVE(14,12)
LR12,15
…
因為15號寄存器是程式始址(即XXXX),將15號寄存器的內容取到12號寄存器,則基地址寄存器12將XXXX作為基地址置入。
例2:BEGIN2 START
SAVE(14,12)
USING*,12
YYYY BAlR 12
…
因為BALR指令是將下一條指令地扯存入12號寄存器中,而USING是指示彙編程式以現行值為基地址彙編,因此基地址寄存器12將YYYY作為基地址置入。但需註意,在這裡不能把BALR和USING指令寫顛倒了,否則出錯。