4.2.1指令尋址和數據尋址
4.2.1.1指令尋址:
順序尋址: 取出指令后PC指向下一條需執行指令的地址。
1)順序尋址:
定長指令字結構尋址:
假設指令字長 = 存儲字長 = 16bit = 2Byte,且主存按字編址。則每次取出指令后PC + 1;若主存按字節編址,意味着每條指令都會占兩個地址,則每次取出指令后PC + 2。
變長指令字結構尋址:指令字長 = 存儲字長 = 16bit,主存按字節編址。假設相同顏色的是同一條指令。
假設從0開始,CPU無法判斷指令長度,因此CPU會每次先讀入一個字,並區分按字節編址還是按字編址,使得程序計數器PC + “一個指令長度”,本次敘述的是按字節編址,因此PC + 4,若按字編址,PC + 2。操作碼被包含在第一個字,CPU根據操作碼判斷讀取指令是幾地址指令,由此確定指令占用多少字節,並繼續讀取后續。
2)跳躍尋址:
下一條指令的地址碼不由程序計數器指出,而是由本條指令給出下條指令地址碼的計算方式。
定長指令字結構尋址,指令字長 = 存儲字長 = 16bit,主存按字編址。意味着每條指令占用一個字,兩個字節;變長指令字結構尋址,與順序尋址中變長指令字結構的情況可類比,不一一贅述,主存按字節編址的情況與順序須知可以類比得出,也不贅述。
如上圖,仍然假設CPU從0開始讀入指令,從0~2都是順序尋址,此時,執行完指令2時,PC指向的是指令3,接下來,CPU讀入指令3,PC + 1,PC指向4,CPU執行指令3,指令3是JMP,無條件跳轉指令,跳轉到7,此時PC重新指向,指向7。
4.2.1.2 數據尋址:
確定本條指令的地址碼指向的真實地址,是指如何在指令中表示一操作數的地址,與跳躍尋址並不相同。由於數據尋址的方式較多,為了便於區別,會在指令字的形式地址前面設置幾個bit作為尋址方式位,這幾位是尋址特征。每個形式地址前面都會有一個尋址方式位。
4.2.2 數據尋址的方式
一地址指令:
二地址指令:
介紹十種數據尋址方式,由於10 < 16 = 24,因此十種情況用4個bit表示足以。假設指令字長 = 機器字長 = 存儲字長,假設操作數是3。
4.2.2.1 直接尋址
指令字中的形式地址A就是操作數3的真實地址EA,CPU根據形式地址去主存中相應地址找到數據3並將其放入ACC中進行計算。取指令,執行指令一共訪問主存兩次。直接尋址過程簡單,但操作數的地址范圍有限,且操作數地址發生變化時指令需要再修改。
4.2.2.2 間接尋址
指令的形式地址碼A指向主存中某個有效地址EA,EA中存儲着操作數的真實地址,可以用EA = (A)來表示,其中(A)表示地址A所指向的主存單元里的數據,取指令訪問存儲一次,執行指令訪問存儲兩次一共三次。間接尋址擴大了尋址范圍,便於編寫匯編程序,但是由於需要多次訪存,因此執行指令速度會慢。 間接尋址可以多層“套娃”,間接尋址可以與C語言中的一級指針、二級指針、多級指針類比理解。
4.2.2.3 寄存器尋址
指令中的形式地址碼Ri指向某個編號為Ri的寄存器寄存器中存放操作數,取指令訪存一次,執行指令不需要訪存。寄存器尋址執行指令不需要訪存,因此執行速度快,支持向量或者矩陣運算,但由於價格昂貴,寄存器個數有限。
4.2.2.4 寄存器間接尋址
指令中Ri指向某個編號為Ri的寄存器,寄存器中存放操作數在主存中的真實地址EA,EA = (RI),取指令訪存一次,執行指令訪存一次共兩次。寄存器間接尋址比一般間接尋址更快。
4.2.2.5 隱含尋址
如兩個操作數的運算,一個操作數的地址存放在指令的形式地址碼A中,另一個操作數B在ACC中,操作數B被指令隱含在ACC中。縮短了指令長度,但需要增加存儲操作數或者隱含操作數地址的硬件。
4.2.2.6 立即尋址
指令的形式地址碼就是操作數本身,一般用補碼表示,#表示立即尋址特征。取指令訪存一次,執行指令不訪存,指令執行時間短,但形式地址碼的位數限制了操作數的表示范圍。
4.2.2.7 基址尋址
指令中形式地址碼A加上基址寄存器中的內容就是操作數的有效地之EA,EA = (BR) + A,如上圖,CPU中的基址寄存器可以,可以采用專用的寄存器,也可以采用通用寄存器,但是若采用通用寄存器,需要在指令中用若干bit表示為Ri,來指明使用了編號Ri的通用寄存器作為基址寄存器。
關於基址尋址過程:
還是采用講義里的筆記截圖,假設這一段程序的指令,在主存中的地址不是從0開始,而是從100或者其他地址開始。程序運行前,CPU將BR的值修改為當前要執行程序的起始地址,存放到操作系統的程序控制塊PCB中。PC指向程序指令起始地址100,第一條指令是取出操作數a,a存放在主存地址碼為105 = 100 + 5的位置。基址尋址適用於多道程序設計,可擴大尋址范圍,可用於編寫經常浮動的程序。
4.2.2.8 變址尋址
指令中形式地址碼A加上基址寄存器中的內容就是操作數的有效地之EA,EA = (IX) + A,如上圖,CPU中的基址寄存器可以,可以采用專用的寄存器,也可以采用通用寄存器,但是若采用通用寄存器,需要在指令中用若干bit表示為Ri,來指明使用了編號Ri的通用寄存器作為基址寄存器。
關於變址尋址過程:
假設要執行一段程序
for(int i = 0, i < 10; i ++)
{
sum = sum + a[i];
}
PC指向第二條指令,PC + 1,取操作數到IX中,此時IX為0,下一條指令的形式地址指向7,則ACC中的操作數0,與 7 + (IX) 得到的地址中的數據相加再放到ACC中,完成一次數組元素加法操作,執行指令IX + 1,則是for循環中的i++,比較IX中的數據與10,則是執行判斷i < 10。執行指令5,滿足指令中的條件,跳轉到指令2,重復前述步驟。后續指令執行較為簡單,不再贅述。變址尋址適用於循環程序。
4.2.2.9 相對尋址
指令中的形式地址碼A加上PC中的內容形成的有效地址碼EA,EA = (PC) + A,A是相對於PC的偏移量,可正可負,用補碼表示。
仍然是講義中的例子,假設把for循環移動到其他位置,此時就需要用相對尋址,假設for循環程序的起始地址是M,則執行指令到M + 3時,PC + 1 = M + 4,此時(PC) + A,得到M,完成一次循環。相對尋址使得for循環有關程序可以在整個程序內任意浮動,而不用修改指令中的形式地址。
4.2.2.10 堆棧尋址
操作數放在堆棧中,使用堆棧指針(Stack Pointer,SP)作為操作數有效地址,按照FIFO先進先出的原則管理堆棧存儲器。可分為硬堆棧和軟堆棧,硬堆棧是寄存器堆棧,在CPU中用指定寄存器來存放堆棧,不需要訪存就能完成尋址;從主存中划分出一段存儲空間來作為堆棧的是軟堆棧,軟堆棧需要一次訪存。
假設用4個寄存器實現堆棧,CPU從堆棧區按順序,取出棧頂元素放到ACC中,SP + 1,指向次棧頂元素,取出次棧頂元素放到X中。計算完畢,把計算結果壓入棧,SP - 1,完成一次加法操作,減法操作亦然。如下圖。
有些情況下棧頂的位置可能在地址數值較小的位置,也可能在地址數值較大的位置,需要詳細區分。
計算上述加法過程中,硬堆棧不訪存,軟堆棧每次壓入棧或者彈出棧的操作,都需要訪存。
關於堆棧寄存器,在后續的CPU基本結構中也會涉及到。