計算機體系結構量化研究方法——指令集原理
指令集體系結構時程序員或者編譯器編寫人員能夠看到的計算機部分。
指令集體系結構的分類
處理器中內部存儲類型是最基本的區別,所以關注這一部分,主要包括棧、累加器或寄存器組。操作數可以顯示命名,也可以隱式命名:在棧體系結構中,操作數隱式位於棧的頂部,在累加器體系結構中,操作數隱式爲累加器。通用寄存器體系結構只有顯示操作數,或者爲寄存器或者爲存儲器位置。
實際上有兩種類型的寄存器計算機。一種可以用任意指令來訪問存儲器,成爲寄存器-存儲器體系結構,另一類則只能用載入和存儲指令訪問存儲器,稱爲載入-存儲體系結構。第三類將所有操作數都保存在存儲器中,稱爲存儲器-存儲器體系結構。一些指令集體系結構的寄存器要多於單個累加器,但對這些特殊寄存器,的使用設置了一些限制。此類體系結構有時被稱爲擴展累加器或專用寄存器計算機。
通用寄存器計算機之所以會出現,主要有兩點,第二寄存器快於存儲器,第二,對編譯器來說,使用寄存器要比使用其他內部存儲形式的效率更高。更重要的是寄存器可用於保存變量。當變量被分配到寄存器中,可以降低存儲器通信流量、加快程序速度,提高代碼密度。
下面是各個的優勢和劣勢。
存儲器尋址
一個體繫結構必須定義如歌解釋存儲器地址以及如何制定這些地址。
解釋存儲器地址
對字節進行排序,有兩種不同的約定方式。
小端字節順序將地址放在雙字的最低有效位置。
大端字節順序將地址放在雙字的最高有效位置。
在許多計算機中,對大於一字節的對象進行尋址時都必須是對齊的。
尋址方式
尋址方式是體系結構如何指定要發訪問對象的地址。除了存儲器中的位置之外,尋址方式還指定常量和寄存器。在使用存儲器位置時,由尋址方式指定的實際存儲器地址稱爲有效地址。
尋址模式能夠大幅減少指令數目,他們也會增加構建計算機的複雜度。
位移量尋址方式
在使用位移量類型的尋址方式是,一個主要的問題就是所用位移量的範圍。根據所使用的各種位移量的大小,可以決定支持哪些位移量的大小。
立即數或直接操作數尋址方式
在進行算是運算、比較和移動時,如果希望將常量放在寄存器中,可以使用立即數。重點是要知道是對所有的運算都支持立即數還是僅對一部分運算支持。
操作數的類型與大小
操作數的類型有字符、半字、字、單精度浮點、雙精度浮點。整數幾乎都是用二進制的補碼數字表示,
指令集中的操作
大多數指令集體系結構支持的操作符可以入表所示。執行最多的指令是一個指令集中的簡單操作。
控制流指令
關於改變控制流的指令,沒有非常一致的術語。
我們可以區分4種不同類型的控制流變化:
- 條件分支(佔絕大多數)
- 跳轉
- 過程調用
- 過程返回
控制流指令的尋址方式
控制流指令中的目標地址在任何情況下都必須制定。在絕大多數的情況下,這個目標是在指令中明確的,但返回是一個重要例外。指定目標的最常見方法是將被駕到的程序計數器(PC)的位移量。這類成爲PC相對指令。採用PC相對尋址還可以是代碼的運行不受裝載位置的影響,這一特性稱爲與位置無關。
如果在編譯是不知道目標位置,爲了實現返回和間接跳轉,需要一種不同於PC相對尋址方法,這時,必須要有一種動態指定目標的方法,使目標能在運行時發生變化。這種動態尋址可能非常簡單,只需要給豬包含目標地址的寄存器名稱就可以。
條件分支選項
由於大多數控制流改變的都是分支,所以決定如何指定分支條件是很重要的。
過程調用選項
過程調用和返回包含包括控制轉移,還可能涉及一些裝填保存過程;至少必須將返回地址保存在某個地方,有的保存在特殊的連接寄出去你中,有時只操作在GPR中。
在保存寄存器時,有兩種基本約定,要麼保存在調用位置,要麼保存在被調用的過程內部。
- 調用者保存:是指發出調用的過程必須保存它希望再調用之後進行訪問的寄存器。
- ** 被調用者保存**: 被調用過車必須保存它希望使用的寄存器,而調用者不受限制。
指令集編碼
上述選擇會影響到如何對這些指令進行編碼,表示爲供計算機執行的二進制形式,這種形式不僅影響到程序經過編譯後的大小,還會影響到處理器的實現。處理器必須對這種表示形式進行譯碼,快速找出操作和操作數。操作在操作碼中指定。主要是如何將尋址方式和操作結合在一起。
編碼指令的三種基本變體:變長編碼、定長編碼、混合編碼。
RISC中的精簡代碼
32位定長格式已經成爲一種負擔,爲應對着這一種情況,提供了新的版本,同時擁有16位和32位指令。
編譯器的角色
由於所執行的大多數指令都是編譯器的輸出,所以指令集體系結構基本上就是編譯器目標。
編譯器的結構
編譯器編寫人員首要目標是正確性——所有有效程序的編譯解結果都必須是正確的。第二個目標是編譯後的代碼速度。
正確編寫編譯器是一件很複雜的事情,而所能完成的優化程序主要受這一複雜度的限制。儘管採用多變掃描結構可以幫助降低編譯器的複雜性,但也要求編譯器必須進行排序。
根據轉移類型,可以將先帶你編譯器執行的優化進下如下分類:
- 高級優化: 一般對源代碼執行並輸出結果傳送之後的優化掃描;
- 本地優化: 僅對直行代碼段內的代碼進行優化
- 全局優化: 將本地優化擴展到分支範圍之外,並引入一組專爲優化循環的轉換
- 寄存器分配: 將寄存器與操作數關聯在一起
- 與處理器相關的優化: 嘗試充分利用特定的體系結構
寄存器分配
寄存器分配在加快代碼速度和使其他優化發揮效果放慢扮演的角色,可以說他是最重要的優化之一。今天的寄存器分配方法以着色問題的技術爲基礎。
優化對性能的影響
編譯器技術對架構師決策的影響
編譯器預高級語言之間的互動顯著影響着程序利用指令集體系結構方式。這裏主要有兩個問題:如何對變量進行分配和尋址?需要多少個寄存器才能對變量進行適當分配?
- 棧用於分配本地變量。
- 全局數據區用於靜態分配所聲明的對象
- 堆用於分配那些不符合棧規則的動態對象。
架構師如何幫助編譯器編寫人員
大多數程序都具有局部簡單性。
編譯器編寫人員在工作時,通常會遵循他們自己對一條體系結構基礎原理的推論:加快常見情況的速度、保證少見情況的正確性。
1、提供正則性,只要可能,指令集的三個要素(操作碼、數據類型和尋址方式)應當是正交的。
2、提供原型而非解決方案。
3、簡化候選項之間的平衡。指出那種指令序列最爲合適。
4、提供一些指令,將編譯時的已知量綁定爲常量。
謬論和易犯錯誤
錯誤:
- 設計專門支持高級語言結構的高級指令集功能
- 不考慮編譯器,僅通過指令集體系結構的創新來縮小代碼規模
謬論:
- 存在典型程序這樣一種東西
- 有缺陷的體系結構不可能獲得成功(80x86)
- 可以設計一種沒有缺陷的體系結構