MIPS 寄存器組和協處理器CP0

MIPS 寄存器組

MIPS 有 32 個通用寄存器($0-$31),各寄存器的功能及彙編程序中使用約定如下:

下表描述 32 個通用寄存器的別名和用途

;REGISTER

NAME

USAGE

$0

$zero

常量 0 (constant value 0)

$1

$at

保留給彙編器 (Reserved for assembler)

$2-$3

v0v0-v1

函數調用返回值 (values for results and expression evaluation)

$4-$7

a0a0-a3

函數調用參數 (arguments)

$8-$15

t0t0-t7

暫時的 (或隨便用的)

$16-$23

s0s0-s7

保存的 (或如果用,需要 SAVE/RESTORE 的)(saved)

$24-$25

t8t8-t9

暫時的 (或隨便用的)

$28

$gp

全局指針 (Global Pointer)

$29

$sp

堆棧指針 (Stack Pointer)

$30

$fp

幀指針 (Frame Pointer)

$31

$ra

返回地址 (return address)

下面給以詳細說明:
$0: 即 $zero, 該寄存器總是返回零,爲 0 這個有用常數提供了一個簡潔的編碼形式。

      move $t0,$t1
   實際爲
       add $t0,$0,$t1
   使用僞指令可以簡化任務,彙編程序提供了比硬件更豐富的指令集。

$1: 即 $at,該寄存器爲彙編保留,由於 I 型指令的立即數字段只有 16 位,在加載大常數時,編譯器或彙編程序需要
把大常數拆開,然後重新組合到寄存器裏。比如加載一個 32 位立即數需要 lui(裝入高位立即數)和 addi 兩條
指令。像 MIPS 程序拆散和重裝大常數由彙編程序來完成,彙編程序必需一個臨時寄存器來重組大常數,這
也是爲彙編 保留 $at 的原因之一。
$2…3:(3:(v0-$v1) 用於子程序的非浮點結果或返回值,對於子程序如何傳遞參數及如何返回,MIPS 範圍有一套約
定,堆棧中少數幾個位置處的內容裝入 CPU 寄存器,其相應內存位置保留未做定義,當這兩個寄存器不夠存
放返回值時,編譯器通過內存來完成。
$4…7:(7:(a0-$a3) 用來傳遞前四個參數給子程序,不夠的用堆棧。a0-a3 和 v0-v1 以及 ra 一起來支持子程序/過程
調用,分別用以傳遞參數,返回結果和存放返回地址。當需要使用更多的寄存器時,就需要堆棧(stack)
了,MIPS 編譯器總是爲參數在堆棧中留有空間以防有參數需要存儲。
$8…15:(15:(t0-$t7) 臨時寄存器,子程序可以使用它們而不用保留。
$16…23:(23:(s0-$s7) 保存寄存器,在過程調用過程中需要保留(被調用者保存和恢復,還包括 $fp 和 $ra),MIPS
提供了臨時寄存器和保存寄存器,這樣就減少了寄存器溢出(spilling, 即將不常用的變量放到存儲器的過程),
編譯器在編譯一個葉(leaf) 過程(不調用其它過程的過程)的時候,總是在臨時寄存器分配完了才使用需要
保存的寄存器。
$24…25:(25:(t8-t9)(t9) 同 (t0-$t7)
$26…27:(27:(k0,$k1) 爲操作系統/異常處理保留,至少要預留一個。異常(或中斷)是一種不需要在程序中顯示
調用的過程。MIPS 有個叫異常程序計數器(exception program counter,EPC) 的寄存器,屬於 CP0 寄存器,
用於保存造成異常的那條指令的地址。查看控制寄存器的唯一方法是把它複製到通用寄存器裏,指令 mfc0 (move from system control) 可以將 EPC 中的地址複製到某個通用寄存器中,通過跳轉語句(jr),程序可以
返回到造成異常的那條指令處繼續執行。MIPS 程序員都必須保留兩個寄存器 $k0 和 $k1,供操作系統使用。
發生異常時,這兩個寄存器的值不會被恢復,編譯器也不使用 k0 和 k1, 異常處理函數可以將返回地址放到這
兩個中的任何一個,然後使用 jr 跳轉到造成異常的指令處繼續執行。
28:(28:(gp) 爲了簡化靜態數據的訪問,MIPS 軟件保留了一個寄存器:全局指針 gp (global pointer,$gp),全局指針
只想靜態數據區中的運行時決定的地址,在存取位於 gp 值上下 32KB 範圍內的數據時,只需要一條以 gp 爲基
指針的指令即可。在編譯時,數據須在以 gp 爲基指針的 64KB 範圍內。
29:(29:(sp) MIPS 硬件並不直接支持堆棧,你可以把它用於別的目的,但爲了使用別人的程序或讓別人使用你的程
序, 還是要遵守這個約定的,但這和硬件沒有關係。
30:(30:(fp) GNU MIPS C 編譯器使用了偵指針 (frame pointer), 而 SGI 的 C 編譯器沒有使用,而把這個寄存器當作保
存寄存器使用($s8), 這節省了調用和返回開銷,但增加了代碼生成的複雜性。
31:(31:(ra) 存放返回地址,MIPS 有個 jal (jump-and-link, 跳轉並鏈接) 指令,在跳轉到某個地址時,把下一條指令的
地址放到 $ra 中。用於支持子程序,例如調用程序把參數放到 a0 a0~a3, 然後 jal X 跳到 X 過程,被調過程完成後
把結果放到 v0,v0,v1, 然後使用 jr $ra 返回。
另外,MIPS 對 CPU 的控制通過協處理器 0(CP0)來完成。
參考資料: http://hi.baidu.com/qq520131714/blog/item/f28933245603072cd40742a6.html MIPS 彙編小貼士
http://blog.csdn.net/jerryutscn/archive/2010/03/10/5365263.aspx 基於 MIPS 架構的 BackTrace 實現

協處理器

深入淺出 MIPS 三 MIPS 的協處理器 CP0

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