第六章指令系統,尋址方式


用高級語言或者是匯編語言編寫的程序,如果要在計算機上執行,必須要利用編譯程序或者是匯編程序把高級語言編寫的程序,指令,或者是匯編指令變成由0,1代碼組成的機器指令,才能夠在計算機中由計算機的硬件按序進行執行。

機器指令

機器指令;計算機系統的CPU能夠直接識別並且執行的操作命令。一個處理器能夠執行的所有的機器指令構成的集合,我們稱之為指令集。指令集就是計算機系統軟件和硬件的交界面。 軟件通過指令系統告訴計算機硬件做什么操作,計算機硬件通過指令系統把執行結果和硬件狀態返回給軟件。

機器指令如何進行設計?系統當中要有哪些類型的指令、每種類型的指令具體要做什么操作,這些問題都是計算機體系結構設計人員要考慮的內容,而計算機組成設計人員要做的事情就是將計算機系統結構設計師設計的硬件指令用邏輯的方法進行實現。為了講解控制器如何實現指令,首先要了解指令的屬性。

一、指令

(1)指令的格式

操作碼:指令具體做的是什么操作。操作碼不僅指出要做什么操作,有很多機器的指令集中,操作碼還要指令要對什么樣的數據做操作,操作數的尋址方式。操作碼分為兩種:

長度固定的操作碼:用於指令字長較長的情況,為了譯碼過程方便,譯碼電路簡單。

長度可變的操作碼:操作碼分散在指令字的不同字段中。上圖中,操作碼字段內容看似是放在一起的,實際上這只是一種邏輯表示方式,在實際中操作碼字段可以分開,放在不同的位置進行表示。為了支持操作碼長度可變,我們要采用擴展操作碼技術來擴展操作碼的長度。

(2)擴展操作碼技術

這里講解通過保留操作碼一個編碼的碼點作為擴展的標志,對操作碼進行擴展。

要增加操作碼的長度,如果指令的長度是不變的,那么實際上要減少地址碼的位數。
首先假設指令格式如圖所示:

OP:表示操作碼部分。
A1,A2,A3:地址碼部分

假設操作碼和每一個地址碼字段長度均為4位。如果不采用擴展操作碼的方式,從上圖中可知,OP為四位,那這台機器最多只能由16條指令,16條指令無法滿足計算機編寫復雜程序的要求。操作碼的個數就是指令的個數。如果給這樣的指令采用擴展操作碼的方式進行編碼,需要通過減少地址碼的個數來增加指令的條數。

具體的擴展方式如下:

首先四位操作碼編碼:從全0到全1共16個點,這16個點,其中從0000 – 1110的15個點作為操作碼長度為四位的操作碼指令的編碼。剩下的1111作為擴展標志。

8位操作碼: 如果前四位編碼為1111,表明這條指令操作碼部分長度至少為8為,1111就是標志,我們減少了一個地址碼字段,把這個地址碼字段變成了操作碼字段,同樣編碼過程還是從0000 – 1110,共15個點,保留一個點:1111 1111 作為擴展字段繼續進行擴展。此時地址只剩下了A2和A3兩段。

12位操作碼:繼續減少地址碼個數,如果地址指令前面是1111 1111 說明這種編碼方式中,指令的操作碼至少是12位。

16位操作碼:把所有地址碼部分都變成操作碼,即16位操作碼。

對於這種保留碼點的擴展方式,要讓計算機能夠識別出現在讀取的指令他的操作碼到底是多少位,為了讓計算機能夠識別操作碼的位數,那么在操作碼的擴展過程中,必須要遵守短操作碼一定不能是長操作碼的前綴。如果短操作碼是長操作碼的前綴,計算機在指令譯碼的時候,就很難識別這兩條指令。

在整個擴展過程中,可以看出如下規律:

在指令執行的過程中,經常出現的高頻指令采用短操作碼表示,不經常出現的指令用長操作碼表示。

二、指令格式

這里對指令格式進行進一步細致划分:

(1)四地址指令

四地址指令格式如下圖所示:

實際的操作是A1和A2進行操作,把結果保存在A3中,執行完當前指令后,通過A4去取下一條指令。上圖中的指令做的操作可表示如下:

如果地址字段均指示主存的地址,則這個操作共需訪問4次存儲器(取指令一次,取兩個操作數兩次,存放結果一次)。

設指令字長為32位,操作碼固定為8位,並且每個地址碼的長度相同,則每個地址碼的長度均為6位,如下圖:

得到尋址范圍如下 = 2^6 = 64b。這個尋址范圍非常小,可訪問的內存空間非常小。如果訪問寄存器還可以,如果訪問內存,這樣的指令幾乎是不可用的。

如何通過減少地址碼的個數來增加地址碼的長度,從而增加尋址范圍,在這條指令中,A4指明了下一條指令的地址,實際在現代計算機中,我們采用PC寄存器表示下一條要執行的指令的地址。如果我們采用PC來代表A4,地址碼就可以減少一個,指令就由四地址指令變成了三地址指令。

(2)三地址指令

格式如下:

如果指令長度32位保持不變,那每個地址碼的長度就會增加,如下:

而這條指令所表示的操作為:A1和A2中的操作數做相應的運算,將結果保存在A3中。

這種操作同樣需要四次訪存操作:取指令一次,取兩個操作數兩次,存放結果一次。

由於地址碼個數的減少,每個地址碼長度增加:尋址范圍為:2^8 = 256b。

通過上面,我們使用PC寄存器代替了地址碼A4,減少了地址碼的個數,增加地址碼長度,從而增加尋址范圍,我們可以繼續減少地址碼的個數來增加地址碼的長度,如:我們使用A1或者A2來代替A3。把運算結果不保存在A3存儲單元,而是保存到某一個參加運算的原操作數地址單元中,這樣就可以再次減少一個地址碼。地址碼由三地址變成了兩地址。

(3)二地址指令

兩地址指令格式如下:

他表示,內存單元A1地址中的內容和A2地址中的內容,做OP規定的操作,把結果保存在A1中,或者把結果保存在A2中,如下:

 

上面這種操作的訪存次數依然是4次:取指令一次,取兩個操作數兩次,存放結果一次。

地址碼由三個變成了兩個,每個地址碼字段的長度增加,尋址范圍 = 2^12 = 4K

如果我們把操作結果不是保存在A1或者A2中,而是將其保存在一個指定的寄存器中,我們就可以進一步減少訪存次數,如將操作結果保存在ACC,這樣就只有3次訪存。

如果我們把某一個操作數以隱含指定的方式就保存在ACC中,要進行某個操作,一個操作數必須在ACC中,另外一個操作數在內存中,ACC內容和內存內容做操作,結果保存在ACC中,這樣就可以再一次減少地址碼個數,從兩地址變成單地址。這個地址只需要指明參加運算的出了ACC之外的另一個操作數在內存單元中的地址即可。

(4)一地址指令

一地址指令格式如下:

 

他的操作為,A1內存單元中的內容和ACC寄存器中的內存做OP指定的操作,結果保存在ACC中。操作表示如下:

這種操作需要兩次訪存:取指令,取A1操作數。

地址碼減少為1個:尋址范圍 = 2^24 = 16M

(5)零地址指令

即無地址碼。如:對ACC中數據進行清零,取反,對ACC中某一位數據進行特定的操作,或者判斷ACC中的數據是否為0,是否全1等。還有堆棧類的指令,如在堆棧型計算機中,加法操作只需要操作碼即可,不需要操作數,因為ADD表示棧頂的兩個數做加法,把結果再一次保存在棧頂。

對前面的分析,可以看出當用一些硬件資源代替指令字中的地址碼字段后:
1、可擴大指令的尋址范圍
2、可縮短指令字長
3、可減少訪存次數

(6)當指令的地址字段為寄存器時

 

上面的R1,R2,R3是寄存器的編碼,因為寄存器的個數在計算機中是非常有限的,如,如果有16個寄存器,那么只需要四位長度的二進制數就足夠了,這樣:
1、可縮短指令字長
2、指令執行階段不訪存

三、指令字長

根據前面的分析,可以很容易看出指令字長取決於:

 

指令字長固定的情況下:指令字長 = 存儲字長

指令字長可變:指令字長將會按字節整數倍變化

操作數類型和操作類型

(一)操作數的類型

操作數:指令要處理的數據。主要分為以下四種類型:
1、地址:在跳轉指令中,操作數部分就是地址或者是相對地址,如果是絕對地址,這個地址就是一個無符號數。如果是相對尋址,他就是一個有符號數。
2、數字:定點數,浮點數,十進制數。
3、字符:ASCII
4、邏輯數:邏輯操作。

(二)數據在存儲器中的存放方式

如,12345678H在計算機中的存放方式。

大端方式:

小端方式:

下面看看,按照字節編址,數據在計算機中是如何進行存放的,這里假設計算機存儲字長64位,機器字長32位。

存儲字長64位,說明CPU在訪存過程中,一次訪存最多可以拿到一個長度為64位的數據。若機器字長32位,那64位的數據就是一個雙字。

(1)從任意位置開始

存放情況如下圖所示:

 

半字 :一個字長為32位4字節,半字指的是16位雙字節。

對於這種存放方式:

優點:對內存空間的利用非常好,不會浪費內存資源。

缺點:除了訪問一個字節之外,訪問其它任何類型的數據, 都可能花費兩個存儲周期的時間,才能將數據讀出來或者寫進去。讀寫控制比較復雜,因為要判斷數據的長度,數據是不是跨存儲字進行存取。計算機中內存是計算機運算速度的瓶頸,如果我們采用這種方式進行存儲數據,訪存的速度不會太快,那如何保證任何類型的數據在一個存儲周期都能將其取出來呢。下面看第二種方式。

(2)從一個存儲字的起始位置開始訪問

每次存取數據不管是什么類型的,都從一個存儲字的開始位置進行訪問。如果是這樣,則存放如下:

這樣存儲,任何一種類型的數據,都能保證在一個內存周期完成讀寫操作,並且讀寫控制非常簡單。但是,浪費了寶貴的存儲資源,圖中的黑色部分都是被浪費的內存資源。

那有沒有一種方式,即能夠減少資源的浪費,有能夠保證任何一種類型的數據(長度都要小於存儲字長),在一個主存周期中都能夠訪問。下面看第三種方式。

(3)邊界對准方式。

從地址的整數倍位置開始進行訪問,地址的整數倍開始進行訪問,具體如下圖所示:

如上圖中,一個字節進行存儲的時候,可以存儲在任何一個內存單元中。如果是一個雙字,我們假設的是雙字是8個字節,也就是占用了8個編址單位,對他進行存儲的時候,起始地址從地址編碼是8的倍數的存儲單元開始,在上圖的內存結構中,就是每次從一個存儲字的起始地址進行存放。如果是一個半字,半字的字長為兩個字節,那存儲的時候,把他放在地址是偶數的起始地址開始存放。如果是一個字,長度為四個字節,那就從地址的地址編碼為4的整數倍的位置開始存放。

這種方式,能夠保證任何一種類型的數據(長度都要小於存儲字長),進行訪問的話,一個存儲周期就能夠得到或者是寫入要訪問的數據。這種方式是前兩種方式的折中,數據存放的起始位置是數據長度的整數倍。這個數據長度用編址單位進行計算,如上圖中的編址單位是字節,那就看存取的數據長度為多少個字節,那他的起始地址就是字節數的整數倍。這種方式既保證了在一個存取周期中能夠完成數據的訪問,也減少了存儲空間的浪費。

(三)操作類型

(1)數據傳送

在不同的存儲介質中進行數據的傳送。比如源和目的之間:

(2)算數邏輯操作

常見操作如下:

8086中常見的指令如下:

(3)移位操作

算術移位,邏輯移位,循環移位(帶進位和不帶進位)

(4)轉移

1、無條件轉移

JMP,執行到這樣的指令,直接轉移到目標地址。

2、條件轉移

在一些計算機中稱之為分支指令,如:

3、調用和返回

1、遇到調用指令,調用子程序1,程序的控制流就會發生轉移,在子程序1上進行指令。
2、在子程序1上執行過程中,遇到調用指令,調用子程序2,程序的控制流發生跳轉,執行子程序2。
3、開始執行子程序2
4、遇到return指令返回。在哪里就行的調用就會返回到什么地方。
5、返回到子程序1繼續執行。
6、執行過程中遇到調用指令,調用子程序2,程序控制流跳轉到子程序2.
7、開始執行子程序2
8、遇到return指令返回。
9、返回開始執行子程序1
10、子程序1執行結束以后,返回到主程序
11、主程序繼續執行
12、主程序執行結束

4、陷阱(Trap)與陷阱指令

通常情況下陷指的是意外事故的中斷。

一般不提供給用戶直接使用的陷阱指令:
在執行一條指令過程中,這條指令本身執行過程出現了意外,就要執行陷進指令,比如操作碼非法,操作數訪問越界,或者除法操作中除數為0,都會引發陷進指令,所以通常情況下陷進指令不是直接提供供用戶直接使用的。是在出現問題的時候,出現異常事故的時候,由CPU自動執行的,所以他並不是指令集當中的一些指令,它由硬件自動執行,這種指令稱之為隱指令。

提供給用戶使用的陷阱指令:
也有一些系統中提供用戶使用的陷阱指令供用戶進行使用,比如進行程序調試。

5、輸入輸出

並不是每一種指令集中都有輸入輸出指令,如果IO端口編址空間作為內存編址空間的一部分,那這個指令集就不需要輸入輸出指令,直接用訪存內存的指令就可以對外部設備進行輸入輸出。如果外部設備或者端口有自己的獨立地址空間單獨編址,就需要單獨的輸入輸出指令對外部設備進行訪問。

輸入:將外部設備端口中的內容傳輸到CPU的寄存器中:

輸出:將CPU寄存器的內容輸出到設備的端口中。

尋址方式

如何找到指令或者數據的地址:

從指令和數據角度吧尋址方式划分為兩類:即指令的尋址和指令中數據的尋址。

(一)指令尋址

(1)順序尋址

取完一條指令,順序的取下一條指令,由於指令的地址是保存在PC中的,去完當前的指令,為了取下一條指令,就要把PC內容加1,然后送到PC中。

上面的加1,並不是在任何一個計算機或者指令集中都是加1,實際上1是比較復雜的。如果內存單元的編址單位是字節,每條指令長度是32位4字節,那么順序尋址的時候,每次加的值就是4,如果指令的長度是64字節,那PC加8,如果指令是可變程度的,那么加1操作就更加復雜。

(2)跳躍尋址

由轉移指令指出下一條指令的地址。

如上圖中,程序由多條指令構成,假設指令的地址從0開始,在開始執行程序的時候,PC的值被置0,將LDA指令取出后,PC會自動加1,為取下一條指令做准備,這就是順序尋址。地址為3的地址十一條無條件的跳轉指令,他的目標地址是1,執行完這條指令之后,要找到下一條指令地址,采用的尋址方式就是跳躍尋址,跳到7取出STA指令,之后又是順序尋址。

(二)指令中數據的尋址

數據尋址的方式比較多,下面是指令的格式:

假設給出的是單地址指令。

尋址特征:標識采用什么樣的尋址方式能夠找到操作數所在的地址。

地址字段中給出的是形式地址,形式地址就是在操作碼中給出的地址,形式地址並不是要找到的數據所在的存儲單元或者是寄存器的真實地址。要找到真實地址,需要使用尋址特征和形式地址進行一定的運算或者是轉換才能得到真正的有效地址。

有效地址:操作數的真實地址。

為了講解方便,簡化案例,約定:指令字長 = 存儲字長 = 機器字長。

(1)立即尋址

形式地址A就是操作數,這個數據直接參與操作碼指定的運算。如果采用立即尋址,上面指令的格式就變成如下圖所示:

#:立即尋址的特征,在譯碼過程中,如果發現尋址特征位是#,表示后面的操作數是立即數。立即數可以是正數,也可以是負數,用補碼進行表示。

如果采用立即尋址,操作數在取指令過程中實際已經被取入到了CPU中,所以在指令執行過程中,不需要再次訪存。那么A到底取多長或者A到底占用多少位二進制位比較合適和實際情況有關。

(2)直接尋址

即有效地址 = 形式地址,具體表示如下:

 

EA是有效地址。A給出的就是操作數所在的內存單元的地址,由形式地址直接給出。如:

上圖中表示的是,用LDA指令將內存單元中的數據取到CPU,保存在ACC寄存器中,圖中藍色部分是尋址特征,表示后面的操作數采用的是直接尋址方式,直接給出的就是內存單元的物理地址,我們就可以通過這個給出的地址去訪存這個內存單元,把操作數取出送入ACC寄存器。

如果假設地址碼中只有一個地址字段,這樣的指令在指令執行過程中,需要訪問一次存儲器。
A的位數決定了操作數的尋址范圍,如果A過短的話尋址范圍會非常小。

這種方式的地址碼字段非常難以修改,編程困難。比如我們要對一個數組的每個值都加1,用循環去做,這樣很難通過這個命令去取出數組的每一個數,除非有另外一條指令,能夠把LOAD指令從內存中取出,並且能夠修改地址碼部分,這樣我們才能用循環完成數組每個值加1的操作。

(3)隱含尋址

把尋址方式隱藏到操作碼中,或者是參與運算某一個數據由操作碼直接給出。如下:

 

上圖中的ADD指令,藍色部分代表尋址特征,這個尋址特征值得是后面的地址碼的尋址方式,這個加法指令需要兩個操作數參與運算,並且要把加法結果進行保存,指令當中給出了一個操作數,另外一個操作采用的就是隱含尋址的方式,這個操作數就隱含在ACC寄存器中。假設尋址特征位給出的是直接尋址,由這個地址只接到指定的內存單元中取出參加操作的一個操作數,另外一個操作數保存在ACC中,ACC中的數據和內存中的數據做加法操作,把計算的結果放入一個暫存器中,再把結果送入ACC。

在8086中:

采用隱含尋址的方式,盡管是兩個操作數參與運算,但是其中的一個操作數我們用隱含的方式給出,所以在指令中我們只需要給出一個操作數地址,這樣減少一個地址碼字段,可以縮短指令長度。

(4)間接尋址

指操作數的地址保存在某一個內存單元中,指令當中出現的是這個內存單元的地址,有效地址在給定的內存單元中進行保存。表示為:

 一次間址:

 

如上圖中,藍色部分依舊是尋址特征,這個尋址特征標示了后面的操作數采用的是間接尋址。

一次間址操作過程:

圖中指令真正的操作數所在的地址,保存在形式地址A所代表的內存單元中,要想取得真正的操作數,需要先通過形式地址A取得真正的有效地址,然后利用有效地址再次訪問內存得到的才是真正的操作數。

在執行指令階段需要訪問兩次內存,第一次取出有效地址,第二次根據有效地址取出真正的操作數。

這種方式可以擴大尋址范圍,盡管A的字段可能比較短,尋址范圍比較小,但是我們可以把EA字段放的很長,從而擴大尋址范圍。

方便編寫程序,可以通過修改EA從而修改真正的操作數所在的地址,這樣指令中的形式地址不需要任何變化,操作數的真正地址就會發生變化。

多次間址:

上圖中,A依舊不是操作數的地址,表示的是能夠找到操作數地址必須要經過的中間過程的地址。
操作過程如下:

先通過A找到地址A1,這個A1並不是我們要的操作數的地址,前面標識1指的是目前這個地址依然是一個間接地址,所以我們需要再次尋址,可能會經過很多次,一直到我們找到的地址前面的標識為0,這個單元中保存的才是有效地址,我們還要利用這個有效地址再次訪存,把操作數取出來,參與指定的操作。

間接尋址舉例:

上圖中執行流程如下:

程序在執行過程中,需要調用子程序,我們用間接尋址來保存程序斷點。子程序的最后一條指令是跳轉指令,這條跳轉指令的尋址方式采用的是簡介尋址。

1、主程序在執行過程中,如果80是一個調用子程序的調用指令,那么81就是程序的斷點,為了能夠返回,程序的斷點必須要進行保存,我們把81保存在A表示的地址單元中,這樣A地址單元中保存的內容就是81.執行完調用指令,程序的控制流進入到子程序執行。

2、子程序開始執行。

3、子程序執行完,進行返回的時候執行JMP指令,並不是直接跳轉到A這個地址,而是跳轉到A這個地址單元中保存的81地址。

4、返回到程序斷點81開始執行。

5、如果地址201依然是一個調用子程序的指令,斷點就是202,我們把斷點202保存在A的地址單元中,A是地址,這個地址中保存的是 202,程序控制流轉入子程序執行。

6、執行到子程序的最后一條JMP指令,這條指令跳轉采用的依舊是簡介尋址,跳轉並不是跳轉到地址A,而是跳轉到A地址單元中保存的數據202指示的地址。

(5)寄存器尋址

指令的有效地址就是寄存器的編號,表示為:

寄存器尋址過程如圖所示:

指令中的尋址特征指出指令的尋址方式為寄存器尋址,Ri是寄存器編號,參加運算的數據保存在給定編號的寄存器中,因此CPU要在給定的編號的寄存器中取出數據,對數據做相應的操作。

在指令的執行階段不需要訪存,只訪問寄存器,執行速度塊。

寄存器個數有限,所以指令中的地址碼較短,可以縮短指令的字長。

(6)寄存器間接尋址

在這種尋址方式中,操作數保存在內存單元中的,操作數的地址保存在寄存器中,表示為:

尋址過程如下:

圖中藍色部分表示為寄存器間接尋址特征。根據這個特征首先訪問相應的寄存器獲取在內存中真正的操作數的有效地址。再根據有效地址訪問內存,從內存中取出真正的操作數。

這種方式,有效地址在寄存器中,操作數在存儲器中,指令執行階段需要一次訪存。

這種方式非常便於循環程序的編寫,我們需要修改操作數的地址,只需要直接修改寄存器中的內容就可以。

(7)基址尋址

在CPU中設置專用的寄存器作為基址寄存器

參加操作的操作數的有效地址,是基址寄存器中保存的內容加上形式地址。表示為:

基址尋址過程如下:

藍色部分表示尋址特征為基址尋址,尋址過程需要利用一個加法器,BR的內容和A的內容相加,得到的地址是操作數在內存單元中的有效地址,用這個地址去訪問內存單元就可以得到操作數。

利用這種方式可以擴大尋址范圍,因為BR是基址,他給出了尋址的起點,A是一個偏移量,通過調整BR就可以擴大尋址范圍。

有利用多道程序設計,多道程序分時進行執行的時候,程序的起始地址可以把他放在BR中,在執行過程中,動態形成操作數的地址,這種方式稱之為程序的動態定位。

BR內容一般由操作系統或者管理程序確定,用戶不能修改BR內容,如果要修改地址,只能修改形式地址。在多道程序設計中通過動態修改指令中的形式地址進行程序的裝入或者是內存中的定位。

采用通用寄存器作為基址寄存器
尋址過程如下:

在尋址過程中,操作和代用專用的基址寄存器過程類似,依然需要加法器。

可以由用戶指定使用那個寄存器作為基址寄存器,但是程序執行過程中,基址寄存器的內容依然是由操作系統或管理程序決定,用戶不能修改指定的基址寄存器的內容,形式地址A是可以改變的。

(8)變址尋址

在變址尋址中,變址寄存器內容加上形式地址內容等於有效地址。表示如下:

尋址過程如下:

和基址尋址類似,在形成有效地址過程中,我們要利用一個加法器把A的內容和編址寄存器的內容相加,得到的結果就是操作數所在內存單元的有效地址。用這個有效地址訪問內存單元就能夠獲得操作數。

這種方式可以擴大尋址范圍。

IX內容可以修改,在程序執行過程中A的值是固定的,IX的值可以修改。

這種方式便於對數組的操作,如果我們對數組進行循環操作,A表示數組的起始地址,IX可以作為數組的下表來做循環操作。

舉例:使用變址尋址對數組進行操作。如果數組首地址為 D,求 N 個數的平均值。

首先看采用直接尋址方式,過程如下:

由上面可以看出,采用直接尋址,共需要N + 2條指令

下面是變址尋址:

變址尋址方式只需要8條指令就能夠完成這個功能,大大減少了指令在內存中的占用空間。

(9)相對尋址

相對尋址,相對的是當前的PC值,所以有效地址等於PC值加上形式地址,表示如下:

相對尋址過程如下:

 

 

當前指令的地址是1000,當前的PC值就是1000,如果這條指令的尋址特征為相對尋址,PC的值和A的值做加法,得到內存單元中操作數的有效地址。A的值就是操作數相對於PC值的偏移量。

A的位數決定的相對尋址的尋址范圍。

這種有利於程序浮動,所謂程序浮動,指的是程序在內存單元中存儲位置發生變化。

這種方式非常廣泛的應用於轉移指令。

相對尋址舉例:這個例子是前面介紹過的利用變址尋址方式求數組各個值的平均值。

這個程序中,CPX指令判斷加和次數是否達到了N,如果沒有,就使用BNE指令跳轉到M。而M的值會隨着程序所在存儲空間位置的不同而發生變化。但是當前這條BNE指令和M之間的相對位移是固定的,如果我們采用相對尋址的方式,*是相對尋址的特征位,我們把當前的PC值減3,我們就可以得到這條跳轉指令如果跳轉成功的話,那么下一條指令他的地址。所以可以把BNE M,指令直接改成BNE *-3,所以下一條指令的有效地址為:

在看一個按字節尋址的相對尋址例子:

圖中,2000H位置的指令JMP *+8 采用的是相對尋址,如果指令的字長是兩個字節。如果JMP指令執行完成,那么下一條指令所在地址就應該是當前的PC加8,結果就是2008H。但是機器實際執行的時候並非如此,在現在的計算機中,一條指令只要取完,在他還沒有執行或者是還沒有執行完,PC的值就已經發生了修改,也就是說2000H里面包含的這條JMP指令只要被取出,還沒有執行,PC的值就已經被修改為2002H,因此要想跳轉到正確的目標地址,我們必須對JMP中的偏移地址進行修改,修改為JMP * 06,即這條指令的位移量應該是06,如下圖所示:

(10)堆棧尋址

堆棧的特點:

堆棧是一個先進后出的隊列,堆棧有兩種類型:
硬堆棧: 在堆棧型的計算機中,一般都采用硬堆棧方式,也就是說由多個寄存器作為棧頂,棧底部分在內存中。進行操作的話,如加法操作,將兩個操作數均來自於棧頂,操作完成后將操作結果保存在棧頂。
軟堆棧: 指定的一段內存空間。

棧頂位置由SP寄存器指出。通常情況下,堆棧的棧底是地址最高的,棧頂是低地址。如果我們進行進棧操作,SP – 1,棧頂向上升起,如果是出棧操作,SP + 1,棧頂進行下移。

入棧操作:
SP開始等於2000H,表示當前的堆棧的棧頂在2000H位置。
SP = SP – 1 = 1FFFH,前提是壓入堆棧的數據正好占用了一個編址單位。

出棧操作:
SP開始等於1FFFH,表示當前的堆棧的棧頂在1FFFH位置。
SP = SP + 1 = 2000H。

SP的修改和主存編址方法有關。

1、按字編址:

2、按字節編址:

存儲字長為16位時:

存儲字長為32位時:

 

指令格式舉例

(一) 設計指令格式應考慮各種因素

(1)指令系統的兼容性。

如計算機發展過程中,新設計的指令集,指令數量可能會比較少,用戶利用這個指令集編寫了大量程序完成一些功能,隨着計算機發展要設計新的處理器新的指令集,但是在設計新的指令集的時候,必須要考慮在已有的計算機上已經跑起來的應用,為舊的機器設計的應用程序,最好不經過任何修改就能夠在新的指令集機器上順利執行。否則,用戶購入新的機器需要重新設計應用編寫程序,對用戶來說需要付出很大的代價。對用戶來說是不可接受的,對CPU設計人員來說,如果不能和舊的指令集兼容,則新的處理器就很難占領市場。

(2)其他因素

 

 

(二)IMB360指令格式

共有五中指令格式

(1)RR格式

兩個寄存器參加操作,結果保存在其中的一個寄存器中,指令的長度是16位,操作碼長度是8位,IBM360指令的操作碼長度都是8位。

(2)RX格式

寄存器和存儲器,其中X是編址寄存器, B是基址寄存器,從寄存器所占位數看公有16個寄存器,D是偏移地址,采用基址加編址方式進行尋址。

(3)RS格式

這種是三地址格式,用於寄存器和存儲器之間的操作,比如,在寄存器和內存之間進行成組的數據傳輸,成組的PUSH操作,從R1R3中內容傳送到內存中。

(4)SI格式

 

這種格式是立即數和內存的立即數尋址,地址長度32位。

(5)SS格式

這種是存儲器和存儲器之間的數據進行操作,用於內存之間的數據傳輸。

(三)Intel8086

從指令字長來說8086是典型的復雜指令集計算機,指令字長比較多,占用1-6個字節。

一個字節的指令:

6字節指令:

從地址格式來說,也有多種類型的地址格式:

零地址:

一地址:

二地址:


RISC技術

(一)RISC的產生和發展

RISC(Reduced Instruction Set Computer):精簡指令集計算機,和其相對的是CISC(Complex Instruction Set Computer):復雜指令集計算機,早期計算機采用的是復雜指令集,其實最早的計算機他的指令集一定不是非常復雜的,但是在發展過程中,CPU的設計人員,計算機體系結構的設計人員,為了適應應用的發展,為了面向目標程序進行優化,面向高級語言進行優化,面向操作系統進行優化,把目標程序中經常用到的操作,把他變成計算機的指令,來加快應用,指令集逐漸復雜,甚至有些計算機的指令集多達300-400,條,但是太多的指令是沒有必要的。在70年代末80年代初的時候,有人開始考慮計算機的指令集是不是越龐大越好,指令的條數是不是越多越好,指令的功能是不是越強越好,分析的結果是二八規律。即在典型的程序中,百分之80語句,僅僅使用了指令集中百分之20的指令,或者是在程序的執行過程中,百分之80被執行的語句只是百分之20的指令。那么,在指令集中加入的很多很復雜的指令導致計算機系統的控制器設計起來很復雜,甚至是只能用微程序的方式進行設計,導致了百分之20那部分功能比較簡單的指令在復雜指令集的影響下,或者是強功能的指令的影響下,他的運算速度被拖慢。那能否在指令集中只包含百分之20的簡單的指令,以及其他的必要的指令。復雜的指令在指令集中去除,不用硬件實現,涉及到復雜指令的功能,使用簡單的百分之20的指令組合實現,這就是RISC技術。

(二)RISC主要特征

(1)指令集比較小,只選擇使用頻率較高的簡單指令,復雜指令功能由簡單指令組合實現。使得機器的控制設計簡單。

(2)指令長度固定,指令格式種類少,尋址方式少。譯碼簡單,甚至操作碼位置固定,操作數位置固定,在譯碼時候可以取操作數,可以對操作數進行讀操作。提供指令速度。

(3)只有 LOAD,STORE指令訪存,其他指令都不能訪存,其他指令的傳輸操作或者是算數運算,邏輯運算操作,只能在寄存器和寄存器之間執行,並且結果保存在寄存器中。這樣CPU中有比較多的通用寄存器支持這些操作。

(4)指令比較簡單,指令之間的關系簡單,所以精簡指令集的計算機都是采用流水線的方式來做的,而且特別關注提高流水線的效率,在一個時鍾周期內完成一條指令。

(5)為了提高速度,所有的精簡指令集的指令都是采用組合邏輯的方式,也就是用硬聯方式實現控制器,使其速度更快。

(三)CISC主要特征

(1)系統指令復雜龐大,各種指令使用頻度相差大。

(2)指令的長度不固定,指令格式多種多樣,尋址方式也非常多,導致譯碼過程非常復雜,CPU硬件部分設計復雜。

(3)訪存指令不受限制。

(4)CPU中設有專用寄存器

(5)大多數指令需要多個時鍾周期完成,因為指令比較復雜,如果指令都采用硬聯方式實現,硬件系統會非常龐大。

(6)在CPU設計時候,采用微程序控制器,指令被分成若干個微指令,微指令按順序執行完成這條指令要求的功能,微指令組成的微程序保存在控制存儲器中,執行指令的時候需要多次訪問控制存儲器,速度慢。

(四)RISC和CISC比較

(1)RISC指令簡單,控制器在CPU芯片上占用的面積小,更能充分利用VLSI芯片面積。剩余的硬件可以做存儲來提高CPU運行的速度。

(2)RISC更能夠提高計算機的運算速度。指令數、指令格式、尋址方式少, 通用寄存器多,采用 組合邏輯 , 便於實現指令流水。

(3)RISC便於設計,可降低成本。硬件結構簡單,提高可靠性。

(4)RISC不容易實現指令系統的兼容,他的指令格式設計的很緊湊,如果后期增加指令比較難。

 

轉載來源https://blog.csdn.net/b_x_p/article/details/85223641


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM