深入了解計算機系統(4.1)------Y86指令集體系結構
本章我們将進入處理器體系結構介紹的神秘海洋中,我們熟悉的手機,電腦等裝置的核心硬體都離不開處理器。處理器可以稱的上是人類創造的最複雜的系統之一,一塊手指大小的矽片,可以容納一個完整的高性能處理器、大的高速緩存,以及用來連接配接外部的邏輯電路。而且由于摩爾定律,從性能上講,今天一塊晶片上的處理器,已經使得三十年前比房間那麼大的超級計算機都相形見绌了。
那麼可能有人會問,我們軟體開發者,永遠都不會自己去設計處理器,那我們為什麼要學習處理器的實作?
①、首先處理器的設計是非常有趣而且重要的,處理器設計包括很多好的工程實踐原理,它需要完成複雜的任務,而結構又要盡可能的簡單和規則,我們去了解事物是怎樣工作的有其内在的價值。
②、處理器是整個計算機能正常工作的重要組成部分,了解處理器如何工作能幫助我們了解整個計算機如何工作。
③、雖然我們不用去設計處理器,但是我們工作的産出很多都是在包含處理器的硬體系統上運作的,了解它能讓我們工作更有效率。
我們知道計算機系統底層硬體隻識别機器語言,而處理器就是用來執行一系列指令,每條指令執行某個簡單的操作。比如兩個數相加,彙編指令 ADD 會被編碼為一個或多個位元組組成的二進制格式。
這裡一個處理器支援的指令和指令的位元組級編碼稱為它的指令集體系結構(Instruction-Set Architecture,ISA)。
而不同的處理器家族,比如Intel IA32、IBM/Freescale PowerPC和AMD處理器家族,都有不同的ISA。這和我們上一章講的彙編語言是直接面向處理器(Processor)的程式設計語言,不同類型的CPU 有不同的機器指令系統,也就有不同的彙編語言是一樣的。不同的處理器,其指令集體系結構也不一樣,也就是說一個程式編譯成在一種機器上運作,就不能在另外一種機器上運作,如何處理這種相容性問題呢?ISA 在編譯器編寫者和處理器設計人之間提供了一個抽象概念層,編譯器編寫者隻需要知道允許哪些指令,以及它們是如何編碼的;而處理器設計者必須建造出這些指令的處理器。
1、Y86指令
本篇部落格我們主要講解的是Y86指令體系結構。首先我們要知道的是Y86指令是不存在的,這是本書的作者受到 IA32指令,也就是“x86”的啟發,所假想出來的一種處理器體系結構,與 "x86" 相比,Y86指令集的資料類型、指令和尋址方式都要少一些,位元組級編碼也比較簡單。但是它仍然足夠完整,能夠寫一些簡單的處理證書的程式,而設計一個Y86處理器要求我們面對許多處理器設計者同樣面臨的問題。是以學習Y86處理器的設計是很有必要的。
定義一個指令集體系結構,會包括定義各種狀态元素,指令集和它們的編碼、一組程式設計規範和異常處理事件。
Y86程式中的每條指令都會讀取或者修改處理器狀态的某些部分,這便稱為程式員可見狀态,這裡的程式員既可以是用彙編代碼寫程式的人,也可以是産生機器級代碼的編譯器。在處理器實作中,隻要我們保證機器級程式能夠通路程式員可見部分,就不需要完全按照ISA 隐含的方式來表示群組織這個處理器狀态。
和IA32一樣,Y86程式員可見部分包括:寄存器、存儲器、條件碼、PC(程式計數器)、程式狀态。
在Y86當中,寄存器也是有8個,每一個寄存器可以存儲一個字,也就是一個32位二進制。條件碼是一個一位二進制的寄存器,儲存着最近的算術或邏輯運算所造成的影響的資訊。PC則是程式計數器,記錄目前正在執行的指令的位址。存儲器則是一個很大的位元組數組,儲存着程式和資料,Y86的程式可以使用虛拟位址(類似于數組的下标)來通路存儲器,硬體和作業系統會将虛拟位址翻譯為實際的位址。最後一個程式狀态(stat),它則代表着程式的運作情況。它會訓示程式是否正常運作,或者發生了某個特殊事件。
下圖是 Y86 ISA 各個指令的描述,左邊是指令的彙編碼表示,右邊是位元組編碼。它隻包括四位元組整數操作。

halt :這個指令會停止指令的執行。在IA32中有個與之相當的指令 hlt,不過IA32的應用程式不允許使用這條指令,因為它會導緻整個系統暫停運作。而對于Y86來講,執行 halt 指令會導緻處理器停止,并将狀态碼設定為 HLT。
nop:這是一個占位指令,它不做任何事情,後續為了實作流水線,它有一定的作用。
xxmovl:這是一系列的資料傳送指令,其中r代表寄存器,m代表存儲器,i代表立即數。比如rrmovl指令,則代表将一個寄存器的值,賦給另外一個寄存器。
OPl:這包括4個整數操作指令,addl、subl、andl和xorl。他們隻對寄存器資料進行操作。
jXX:包括7個跳轉指令,jmp,jle,jl,je,jne,jge,jg。根據分支指令的類型和條件碼的設定來選擇分支。
cmovXX:包括6個條件傳送指令,cmovle,cmovl,cmove,cmovne,cmovge和cmovg,隻發生在兩個寄存器之間,不會将資料傳送到存儲器。
call:指令将傳回位址入棧,然後跳到目的位址。
ret:call是過程調用,ret是傳回。将傳回位址入PC,并跳到傳回位址。
pushl和popl:指令實作了位址的入棧和出棧
2、指令編碼
指令集的一個重要性質就是位元組編碼必須要有唯一的解釋。任何一個位元組序列要麼是一個唯一的指令序列的編碼,要麼就不是一個合法的位元組序列。
Y86就具有這個性質,因為每條指令的第一個位元組有唯一的代碼和功能組合,給定這個位元組,我們就可以決定所有其他附加位元組的長度和含義。這個性質保證了處理器可以無二義性的執行目标程式代碼。即使代碼嵌入在程式的其它位元組中,隻要從序列的第一個位元組開始處理,我們仍然可以很容易的确定指令序列。反過來,如果不知道一段代碼序列的起始位置,我們就不能準确的确定怎樣将序列劃分為單獨的指令。對于試圖直接從目标代碼位元組序列中抽取出機器級程式的反彙程式設計式和其它一些工具來說,就帶來了困難。
對于如下兩個圖:
下圖是整數操作、條件傳送和分支指令的具體編碼:
下圖是8個程式寄存器對應的辨別符ID
我們應該怎麼确定指令 rmmovl %esp,0x12345(%edx)的位元組編碼?
首先最最上面的一幅圖,我們可以看到rmmovl 的第一個位元組是40,。源寄存器%esp應該編碼放在rA字段中,而基址寄存器%edx 應該編碼放在 rB 字段中,本部落格的第三幅圖我們知道這兩個寄存器的辨別符ID為42。最後偏移量編碼放在4位元組的常數中,我們在0x12345的前面填上0變為4個位元組,也就是位元組序列 00 01 23 45,寫成按位元組反序就是 45 23 01 00。是以整個連接配接起來就是:404245230100
3、Y86異常
對于Y86來說,程式員可見的狀态中包括stat狀态碼,它辨別了程式執行的狀态。這個狀态碼的可能值如下:
對于Y86,當程式遇到異常時,我們就簡單的讓處理器停止執行指令。但是在更完整的設計中,處理器通常會調用一個異常處理程式,這個過程被指定用來處理遇到的某種類型的異常。
4、總結
本篇部落格我們簡單介紹了Y86的指令集結構,相對而言不難了解。後面将會介紹具體的邏輯設計和硬體控制語言HCL。
作者:IT可樂
出處:http://www.cnblogs.com/ysocean/
資源:微信搜【IT可樂】關注我,回複 【電子書】有我特别篩選的免費電子書。
本文版權歸作者所有,歡迎轉載,但未經作者同意不能轉載,否則保留追究法律責任的權利。