MIPS有32個通用寄存器($0-$31),各寄存器的功能及匯編程序中使用約定如下:
下表描述32個通用寄存器的別名和用途
;REGISTER |
NAME |
USAGE |
$0 |
$zero |
常量0(constant value 0) |
$1 |
$at |
保留給匯編器(Reserved for assembler) |
$2-$3 |
$v0-$v1 |
函數調用返回值(values for results and expression evaluation) |
$4-$7 |
$a0-$a3 |
函數調用參數(arguments) |
$8-$15 |
$t0-$t7 |
暫時的(或隨便用的) |
$16-$23 |
$s0-$s7 |
保存的(或如果用,需要SAVE/RESTORE的)(saved) |
$24-$25 |
$t8-$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:($v0-$v1)用於子程序的非浮點結果或返回值,對於子程序如何傳遞參數及如何返回,MIPS范圍有一套約
定,堆棧中少數幾個位置處的內容裝入CPU寄存器,其相應內存位置保留未做定義,當這兩個寄存器不夠存
放返回值時,編譯器通過內存來完成。
$4..$7:($a0-$a3)用來傳遞前四個參數給子程序,不夠的用堆棧。a0-a3和v0-v1以及ra一起來支持子程序/過程
調用,分別用以傳遞參數,返回結果和存放返回地址。當需要使用更多的寄存器時,就需要堆棧(stack)
了,MIPS編譯器總是為參數在堆棧中留有空間以防有參數需要存儲。
$8..$15:($t0-$t7)臨時寄存器,子程序可以使用它們而不用保留。
$16..$23:($s0-$s7)保存寄存器,在過程調用過程中需要保留(被調用者保存和恢復,還包括$fp和$ra),MIPS
提供了臨時寄存器和保存寄存器,這樣就減少了寄存器溢出(spilling,即將不常用的變量放到存儲器的過程),
編譯器在編譯一個葉(leaf)過程(不調用其它過程的過程)的時候,總是在臨時寄存器分配完了才使用需要
保存的寄存器。
$24..$25:($t8-$t9)同($t0-$t7)
$26..$27:($k0,$k1)為操作系統/異常處理保留,至少要預留一個。異常(或中斷)是一種不需要在程序中顯示
調用的過程。MIPS有個叫異常程序計數器(exception program counter,EPC)的寄存器,屬於CP0寄存器,
用於保存造成異常的那條指令的地址。查看控制寄存器的唯一方法是把它復制到通用寄存器里,指令mfc0(move from system control)可以將EPC中的地址復制到某個通用寄存器中,通過跳轉語句(jr),程序可以
返回到造成異常的那條指令處繼續執行。MIPS程序員都必須保留兩個寄存器$k0和$k1,供操作系統使用。
發生異常時,這兩個寄存器的值不會被恢復,編譯器也不使用k0和k1,異常處理函數可以將返回地址放到這
兩個中的任何一個,然后使用jr跳轉到造成異常的指令處繼續執行。
$28:($gp)為了簡化靜態數據的訪問,MIPS軟件保留了一個寄存器:全局指針gp(global pointer,$gp),全局指針
只想靜態數據區中的運行時決定的地址,在存取位於gp值上下32KB范圍內的數據時,只需要一條以gp為基
指針的指令即可。在編譯時,數據須在以gp為基指針的64KB范圍內。
$29:($sp)MIPS硬件並不直接支持堆棧,你可以把它用於別的目的,但為了使用別人的程序或讓別人使用你的程
序, 還是要遵守這個約定的,但這和硬件沒有關系。
$30:($fp)GNU MIPS C編譯器使用了偵指針(frame pointer),而SGI的C編譯器沒有使用,而把這個寄存器當作保
存寄存器使用($s8),這節省了調用和返回開銷,但增加了代碼生成的復雜性。
$31:($ra)存放返回地址,MIPS有個jal(jump-and-link,跳轉並鏈接)指令,在跳轉到某個地址時,把下一條指令的
地址放到$ra中。用於支持子程序,例如調用程序把參數放到$a0~$a3,然后jal X跳到X過程,被調過程完成后
把結果放到$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實現
實際為
add $t0,$0,$t1
使用偽指令可以簡化任務,匯編程序提供了比硬件更豐富的指令集。
$1:即$at,該寄存器為匯編保留,由於I型指令的立即數字段只有16位,在加載大常數時,編譯器或匯編程序需要
把大常數拆開,然后重新組合到寄存器里。比如加載一個32位立即數需要 lui(裝入高位立即數)和addi兩條
指令。像MIPS程序拆散和重裝大常數由匯編程序來完成,匯編程序必需一個臨時寄存器來重組大常數,這
也是為匯編 保留$at的原因之一。
$2..$3:($v0-$v1)用於子程序的非浮點結果或返回值,對於子程序如何傳遞參數及如何返回,MIPS范圍有一套約
定,堆棧中少數幾個位置處的內容裝入CPU寄存器,其相應內存位置保留未做定義,當這兩個寄存器不夠存
放返回值時,編譯器通過內存來完成。
$4..$7:($a0-$a3)用來傳遞前四個參數給子程序,不夠的用堆棧。a0-a3和v0-v1以及ra一起來支持子程序/過程
調用,分別用以傳遞參數,返回結果和存放返回地址。當需要使用更多的寄存器時,就需要堆棧(stack)
了,MIPS編譯器總是為參數在堆棧中留有空間以防有參數需要存儲。
$8..$15:($t0-$t7)臨時寄存器,子程序可以使用它們而不用保留。
$16..$23:($s0-$s7)保存寄存器,在過程調用過程中需要保留(被調用者保存和恢復,還包括$fp和$ra),MIPS
提供了臨時寄存器和保存寄存器,這樣就減少了寄存器溢出(spilling,即將不常用的變量放到存儲器的過程),
編譯器在編譯一個葉(leaf)過程(不調用其它過程的過程)的時候,總是在臨時寄存器分配完了才使用需要
保存的寄存器。
$24..$25:($t8-$t9)同($t0-$t7)
$26..$27:($k0,$k1)為操作系統/異常處理保留,至少要預留一個。異常(或中斷)是一種不需要在程序中顯示
調用的過程。MIPS有個叫異常程序計數器(exception program counter,EPC)的寄存器,屬於CP0寄存器,
用於保存造成異常的那條指令的地址。查看控制寄存器的唯一方法是把它復制到通用寄存器里,指令mfc0(move from system control)可以將EPC中的地址復制到某個通用寄存器中,通過跳轉語句(jr),程序可以
返回到造成異常的那條指令處繼續執行。MIPS程序員都必須保留兩個寄存器$k0和$k1,供操作系統使用。
發生異常時,這兩個寄存器的值不會被恢復,編譯器也不使用k0和k1,異常處理函數可以將返回地址放到這
兩個中的任何一個,然后使用jr跳轉到造成異常的指令處繼續執行。
$28:($gp)為了簡化靜態數據的訪問,MIPS軟件保留了一個寄存器:全局指針gp(global pointer,$gp),全局指針
只想靜態數據區中的運行時決定的地址,在存取位於gp值上下32KB范圍內的數據時,只需要一條以gp為基
指針的指令即可。在編譯時,數據須在以gp為基指針的64KB范圍內。
$29:($sp)MIPS硬件並不直接支持堆棧,你可以把它用於別的目的,但為了使用別人的程序或讓別人使用你的程
序, 還是要遵守這個約定的,但這和硬件沒有關系。
$30:($fp)GNU MIPS C編譯器使用了偵指針(frame pointer),而SGI的C編譯器沒有使用,而把這個寄存器當作保
存寄存器使用($s8),這節省了調用和返回開銷,但增加了代碼生成的復雜性。
$31:($ra)存放返回地址,MIPS有個jal(jump-and-link,跳轉並鏈接)指令,在跳轉到某個地址時,把下一條指令的
地址放到$ra中。用於支持子程序,例如調用程序把參數放到$a0~$a3,然后jal X跳到X過程,被調過程完成后
把結果放到$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實現