計算機組成與設計(二)指令

指令集:一個給定的計算機體系結構所包含的指令集合,一種是人們編程書寫的形式,另一種是計算機所能識別的形式。
共同目標:找到一種語言,可方便硬件和編譯器的設計,且使性能最佳,同時使成本和功耗最低。

MIPS指令集:
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
硬件設計原則
1:簡單源於規整
例如:由高級語言轉換成彙編語言
a=b+c;
d=a-e;

add a, b, c
sub d, a, e

2:越小越快(寄存器個數限制爲32)
(1)大量的寄存器可能會使時鐘週期變長
(2)受指令格式位數的限制
(在MIPS中可以用一個“$”符後面跟兩個字符代表一個寄存器)
數據傳送指令:存儲器和寄存器之間傳遞數據的指令(load指令和store指令)
(將數據從存儲器複製到寄存器的數據傳送指令->load指令)
大端格式:是指數據的高字節保存在內存的低地址中,而數據的低字節保存在內存的高地址中
小端格式:是指數據的高字節保存在內存的高地址中,而數據的低字節保存在內存的低地址中
例如:假設變量h存放在寄存器 $s2中,數組A的基址放在 $s3中,編譯c賦值語句
A[12]=h+A[8];

lw $t0,32($s3)
add $t0,$s2,$t0
sw $t0,48($s3)

寄存器與存儲器相比,訪問時間短、吞吐率高,寄存器中的數據訪問速度快並易於利用,訪問寄存器相對於訪問存儲器功耗更小。因此,爲了獲得高性能和節約功耗,指令集的體系結構必須擁有足夠的寄存器,並且編譯器必須高效地利用這些寄存器。

如果需要使用常數必須先將其從存儲器中取出,例如,要使寄存器$s3加4

lw $t0,AddrConstant4($s1)
add $s3,$s3,$t0

或者使用加立即數的方法

addi $s3,$s3,4

常數0有效使用可以簡化指令集,例如,數據傳送指令正好可以被視爲一個操作數0的加法,因此,MIPS將寄存器$zero至爲0;(由於MIPS支持負常數,所以MIPS中不需要設置減立即數的指令)

表示有符號二進制數的方法(二進制補碼)
在這裏插入圖片描述
採用二進制補碼的優點在於所有負數最高有效位都是1,硬件只需檢測這一位便可知正負,這個位也稱爲符號位
在這裏插入圖片描述
就正如無符號位會發生溢出一樣,對於二進制補碼的操作也可能發生溢出,溢出發生在符號位不正確(即負數符號位爲0,正數符號位爲1)

對於取數指令有符號數和無符號數是有區別的,取回有符號數需要使用符號位填充寄存器的所有剩餘位,稱爲符號擴展;取回有符號位只需用0填充數據左側的剩餘位即可。
(1)對二進制補碼取反,一個數和它按位取反的結果相加,和一定是-1
(2)將一個用n位表示的二進制數轉化成一個用多於n位表示的數(符號擴展)

保持所有指令長度相0同,但不同類型的指令採用不同的指令格式
(R型,用於寄存器)
在這裏插入圖片描述
(I型,立即數)
在這裏插入圖片描述
在這裏插入圖片描述
將MIPS彙編語言翻譯成機器語言
例如:數組A的基址存放在 $t1中,h存放在 $s2中
A[300] = h + A[300];
變成彙編語言

lw $t0,1200($t1)
add $t0,$s2,$t0
sw $t0,1200($t1)

在這裏插入圖片描述
在這裏插入圖片描述
1、指令用數的形式表示
2、和數據一樣,程序存儲在存儲器中,並且可以讀寫
在這裏插入圖片描述
邏輯操作:用於簡化對字中若干位進行打包或者拆包的操作
在這裏插入圖片描述
決策操作
1、beq(branch if equal)相等則分支
2、bne(branch if not equal)不相等則分支
3、無條件分支指令(jump)
4、slt(set on less than)小於則置位,若第一個寄存器小於第二個寄存器,則將第三個寄存器設置爲1,否則設置爲0
5、slti(立即數的小於則置位)
同樣MIPS也提供處理無符號數的sltu指令和sltiu指令

例如:假設i和k存放在寄存器 $s3 和 $s5中,數組save的基址存放在寄存器 $s6中
while(save[i] == k)
i +=1;

//第一步需要將save[i]讀入一個臨時寄存器中,在讀入之前需要計算它的地址,並增加一個標籤lop,以便循環末端能夠跳回該指令
loop:sll $t1,$s2,2//reg $t1=i*4
add $t1,$t1,$s6
lw $t0 ,0($t1) //將save[i]讀入一個臨時寄存器
bne $t0,$s5,Exit //如果save[i]不等於k退出循環
addi $s3,$s3,1
j Loop
Exit:

過程(根據提供的參數執行一定任務的存儲的子程序),由於參數能夠傳遞數值並返回結果,因此參數承擔過程與其他程序、數據之間接口的角色。
(1)將參數放在過程可以訪問的位置
(2)將控制轉交給過程
(3)獲得過程所需的存儲資源
(4)執行需要的任務
(5)將結果的值放在調用程序可以訪問的位置
(6)將控制返回初始點
在這裏插入圖片描述
跳轉和鏈接指令(jalr):跳轉到某個地址的同時將下一條指令的地址保存在寄存器 $ra中(返回地址)
寄存器跳轉(jr):無條件跳轉到寄存器所指定的地址

調用程序,將參數值放在 $a0- $a3,然後使用jal x 跳轉到過程x,被調用者執行運算,將結果放在 $ v0 和 $v1,然後使用jr $ra指令將控制返回給調用者
在程序運行時,使用寄存器(程序計數器program counter)保存當前運行的指令地址;即jal指令實際上將PC+4保存在寄存器 $ra中,從而將鏈接指向下一條指令。

假設對於一個過程,編譯器需要使用多於4個參數寄存器和兩個返回值寄存器,“棧”是最理想的數據結構,需要一個指針指向棧中最新分配的地址,以指示下一個過程放置換出寄存器的位置;在每次寄存器進行保存或恢復時,棧指針(stack pointer)以字爲單位進行調整(MIPS爲棧指針準備了第29號寄存器, $sp,將數據放入棧中稱爲壓棧,移除數據稱爲出棧)

棧的增長是按照地址從高到低的順序進行的,意味着數據壓棧時,棧指針減小;而數據出棧時,棧指針增大。

在這裏插入圖片描述
參數變量g、h、i、j對應參數寄存器$a0、 $a1、 $a2和 $a3,f對應 $s0
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
嵌套:將其他所有必須保留的寄存器壓棧 或者 只需保證被調用者不在 $sp以上進行寫操作即可

棧中包含過程所保存的寄存器和局部變量的片段稱爲過程幀(procedure frame)
在這裏插入圖片描述
堆爲新數據分配空間:
在這裏插入圖片描述
內存低端的第一部分是保留的
程序代碼(代碼段)從地址0040 0000開始
靜態數據從1000 0000開始
然後是動態數據,在C中使用malloc命令分配,在JAVA中使用new命令分配(動態數據在某一區域朝着棧的方向向上生長,稱爲堆)
全局指針 $gp應設置爲適當地址以便於訪問數據,初始化爲1000 8000,這樣相對於 $gp的正負16位的偏移量就可以訪問從1000 0000至1000 ffff之間的內存空間。
棧指針初始化爲7fff fffc,並向數據段的方向向下增長

C語言通過malloc函數在堆上分配空間並返回指向它的指針,free函數釋放指針指向的堆空間;忘記釋放空間會導致“內存泄漏”,會逐漸耗盡大量內存以至於操作系統可能崩潰,而過早釋放空間會導致“懸擺指針”,會造成指針指向程序不想訪問的位置。
JAVA使用自動的內存分配和無用單元回收機制來防止類似的錯誤發生。
在這裏插入圖片描述
人機交互:
大多數計算機使用8位的字節來表示字符,即ASCII碼
在這裏插入圖片描述
表示一個字符串的方式有三種:
(1)保留字符串的第一個位置用於給出字符串的長度
(2)附加一個帶有字符串長度的變量
(3)字符串最後的位置用一個字符來標識其結尾
例如,字符串“Cal”在C中用4字節表示
67、97、108、0

在這裏插入圖片描述

//假設數組x和y的基地址在$a0和$a1中,而i在$s0中,strcpy調整棧指針然後將保存的寄存器$s0保存在棧中
strcpy:
addi $sp,$sp,-4
sw $s0,0($sp)

add $s0,$zero,$zero
//循環的開始
L1:add $t1,$s0,$a1//address of y[i] in $t1
lbu $t2,0($t1) //$t2 = y[i]
//採用類似的方法將x[i]的地址放在$t3中,然後將$t2中的字符保存到該地址中
add $t3,$s0,$a0
sb $t2,0($t3)
//如果是0則退出循環
beq $t2,$zero,L2 //如果爲0,則go to L2
addi $s0,$s0,1
j L1
L2:lw $s0,0($sp)
addi $sp,$sp,4
jr $ra 

JAVA使用unicode進行字符編碼,默認使用16位來表示一個字符
在這裏插入圖片描述
MIPS中32位立即數和尋址
在這裏插入圖片描述

lui $s0,61//使用命令lui加載高16位
//執行完上面的質量$s0的值爲0000 0000 0011 1101 0000 0000 0000 0000
//插入低16位,十進制表示是2304
ori $s0,$s0,2304

分支和跳轉中的尋址
J型除了6位操作碼之外,其餘位都是地址字段
在這裏插入圖片描述
和跳轉指令不同,條件分支指令除了規定分支地址之外還必須指定兩個操作數
在這裏插入圖片描述
(PC相對尋址:使用PC來作爲增加地址的寄存器,可轉移到離當前指令距離爲215個字的地方 )

MIPS對所有條件分支使用PC相對尋址,因爲這些指令的跳轉目標接近分支地址;另一方面,跳轉鏈接指令並非總是靠近調用者的過程,所以它們通常使用其他尋址方式。即J型格式爲過程調用提供長地址

在PC相對尋址所加的地址設計爲字地址而非字節地址,16位的字地址相對於字節地址擴大了4倍;同樣,26位字段也是字地址,表示爲28位的字節地址。
在這裏插入圖片描述
在這裏插入圖片描述
如何使用遠距離分支轉移
在這裏插入圖片描述
在這裏插入圖片描述
(1)立即數尋址:操作數是位於指令自身中的常數
(2)寄存器尋址:操作數是寄存器
(3)基址尋址:操作數在內存中,其地址是指令中基址寄存器和常數的和
(4)PC相對尋址:地址是PC和指令中常數的和
(5)僞直接尋址:跳轉地址由指令中26位字段和PC高位相連而成

任務之間需要同步(synchronize),否則就有發生數據競爭的危險,導致數據錯誤而引起程序運行結果的改變。
同步機制依賴硬件的同步指令,這些指令可由用戶調用(加鎖lock和解鎖unlock同步操作),創建一個僅由單個處理器操作的區域,互斥區
在多處理器中實現同步需要一組硬件原語,提供對存儲單元進行原子讀和原子寫的能力,使得在進行存儲器原子讀和原子寫操作時任何其他操作都不能插入。

原子交換原語來演示如何建立基本同步機制(這個原語是將寄存器中的一個值和存儲器中一個值相互交換)
假定使用存儲器中某個單元來表示一個鎖變量:0表示解鎖,1表示上鎖;一個處理器嘗試對鎖單元加鎖,方法是用一個寄存器中的1與該鎖單元的值進行交換;交換之後鎖單元的新值爲1,返回值如果是1,表明這個鎖已經被其他處理器佔用;否則返回值是0,表示鎖是自由的,上鎖成功。

實現單個的原子存儲器操作需要存儲器的讀寫操作都是有單條不可被中斷的指令完成:
(1)指令對,其中第二條指令返回一個表明這對指令是否原子執行的標誌值
(2)在MIPS中,這一指令對包括一條叫做鏈接取數(load linked)的特殊取數指令和叫做條件存數(store conditional)的特殊存數指令;如果鏈接取數指令所指定的鎖單元的內容在相同的地址條件存數指令執行前被改變,那麼條件存數指令就執行失敗(條件存數指令:保存寄存器的值,並且如果執行成功將寄存器的值修改爲1,否則修改爲0;因爲鏈接取數指令返回鎖單元的原始值,條件存數指令執行成功才返回1)

在單處理器中,爲了保證執行不被任何事件所幹擾,條件存數指令在處理器兩條指令之間進行上下文切換時也會失敗

翻譯並執行程序:
在這裏插入圖片描述
加載器的工作步驟:
1、讀取可執行文件頭來確定代碼段和數據段的大小
2、爲正文和數據創建一個足夠大的地址空間
3、將可執行文件中的指令和數據複製到內存中
4、把主程序的參數複製到棧頂
5、初始化機器寄存器將棧指針指向第一個空位置
6、跳轉到啓動例程,將參數賦值到參數寄存器並且調用程序的main函數的,當main函數返回時,啓動例程通過系統調用exit終止程序
在這裏插入圖片描述
UNIX系統中的目標文件通常包含以下6個不同的部分:
(1)目標文件頭:描述目標文件其他部分的大小和位置
(2)代碼段:包含機器語言代碼
(3)靜態數據段:包含在程序生命週期內分配的數據(靜態數據存在於整個程序中;動態數據,隨着程序的需要增長或減小)
(4)重定位信息:標記了一些在程序加載進內存時依賴於絕對地址的指令和數據
(5)符號表:包含未定義的剩餘標記
(6)調試信息:包含一份說明目標模塊如何編譯的簡明描述

動態鏈接庫:由於靜態方法雖然是最快的調用庫程序的辦法,但有以下缺點:

  • 庫程序成爲可執行代碼的一部分,如果發佈新版本的庫(但程序中使用還是舊版本)
  • 在程序運行時,儘管可能不會使用庫中的所有部分,但他們還是會被加載進來
    所以產生動態鏈接庫(dynamically linked library),即在程序運行過程中才被鏈接的庫例程

在這裏插入圖片描述
啓動一個JAVA程序
在這裏插入圖片描述
從C程序手動翻譯成彙編程序;
(1)爲程序變量分配寄存器
(2)爲過程體生成彙編代碼
(3)保存過程調用間的寄存器
在這裏插入圖片描述
1、寄存器的分配與swap過程的第一部分變量的聲明相對應
2、在這裏插入圖片描述
3、在這裏插入圖片描述
ARM與MIPS指令格式主要區別:
1、每條指令的4位條件執行字段不同
2、ARM因爲只用MIPS一半數量的寄存器,所以具有相對較小的寄存器字段
在這裏插入圖片描述
在這裏插入圖片描述
尋址方式:
在這裏插入圖片描述
2、比較和條件分支
MIPS使用寄存器中的值來決定條件分支是否執行,而ARM使用傳統的存儲在程序狀態字中的4位條件碼來決定條件分支是否執行負值(negative)、零(zero)、進位(carry)和溢出(overflow)->這些設置功能是每條指令的可選功能,使用條件分支以判斷所有有符號和無符號的關係。
在這裏插入圖片描述
ARM的特色:
1、由於沒有專門的寄存器存儲0,所以ARM需要單獨的操作碼來完成一些在MIPS中可以簡單使用$zero來完成的操作
2、ARM支持多個字的算術操作
3、ARM的12位立即數字段:首先將右側低8位的有效位填0擴展到32位,然後將所得的數循環右移,移動的位數由高4位的值乘以2決定(這種方式的優點在於可以在32位字的範圍內表達所有2的冪次)
4、ARM還對寄存器組的操作提供了指令支持,這些指令叫做塊(加載和存儲),在指令的16位掩碼的控制下,16個寄存器中的任意組合都可以被一條指令加載或存儲到內存中,這些指令可以保存和恢復程序調用和返回時的寄存器
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章