天天看點

MIPS架構與彙編語言快速入門

http://blog.tianya.cn/blogger/post_show.asp?BlogID=1915807&PostID=18868775

MIPS架構與彙編語言快速入門

  ━ 譯自伊利諾大學網頁。有内容删減和增加。 原文連結為: http://logos.cs.uic.edu/366/notes/MIPS%20Quick%20Tutorial.htm

  

  譯者:Clark J Li 李久

  日期:2009/9/5

  1. 資料類型

  1.1. 資料類型

   位元組(Byte)為8 Bits;

   半字(Half-word) 為16 Bits 即2個位元組;

   字 (Word) 為32 Bits 即4個位元組;

   一個字元需要一個Byte的空間;

   一個整數需要1個Word(4 Byte)的空間;

  1.2. 指令長度

   所有的指令都是32 Bits 的長度;

  2. 寄存器

   MIPS體系架構有32個通用寄存器。在彙程式設計式中,可以用編号 $0 到 $31來表示;

   也可以用寄存器的名字來進行表示, 例如: $sp, $t1, $ra….

   有兩個特殊的寄存器 Lo, Hi, 用來儲存乘法/除法的運算結果;

   堆棧(Stack)的增長方向是: 從記憶體的高位址方向, 向低位址方向;

  

  寄存器編号

  Register Number 寄存器名稱

  Register Alternative Name 寄存器描述

  Description

  0 Zero 第0号寄存器,其值始終為0

  1 $at (Assembler Temporary) 是Assembler保留的寄存器

  2 ~ 3 $v0 ~ $v1 儲存表達式或函數傳回的結果

  4 ~ 7 $a0 ~ $a3 作為函數的前四個入參。在函數調用的過程中不會被儲存。

  8 ~ 15 $t0 ~ $t7 供彙程式設計式使用的臨時寄存器。

   其值在函數調用的過程中不會被儲存。

  16 ~ 23 $s0 ~ $s7 子函數在使用這類寄存器時, 必須保其初始值, 在子函數退出前, 必須恢複其原來的初始值. 其值在函數調用的過程中會被儲存。

  24 ~ 25 $t8 ~ $t9 與$t0 ~ $t7的用法相同.

  26 ~ 27 $k0 ~ $k1 僅供中斷(interrupt/trap)處理函數使用.

  28 $gp 全局指針.

  29 $sp 堆棧指針, 指向堆棧的棧頂。

  30 $s8/$fp 儲存的值/幀指針。

  其值在函數調用的過程中會被儲存。

  31 $ra 傳回位址

  

  3. 程式結構

  彙編源程式代碼本質上是文本檔案。由資料聲明、代碼段 兩部分組成。

  3.1. 資料聲明

  在源代碼中,資料聲明部分以 .data開始。聲明了在代碼中使用的變量的名字。同時,也在RAM中建立了對應的空間。

  

  資料聲明的格式:

   Name: storage_type value(s)

  舉例:

   Var1: .word 3 # 建立了一個占1 Word空間的變量, 并賦初值3

  

  3.2. 代碼段

  在源代碼中,以 .text開始。列出了彙編代碼。 各個不同功能的代碼段,用标簽來辨別。

  

  3.3. MIPS 彙程式設計式例子

  Example:

   .data # data declaration

  var1: .word 23 # declare storage for var1; initial value is 23

  

   .text # Code section

  __start: # __start is a lable

   lw $t0, var1 # load contents of RAM location into register # it means $t0 = var1

  

   li $t1, 5 # $t1 = 5 ("load immediate")

   sw $t1, var1 # store contents of register $t1 into RAM

   # it means var1 = $t1

   done

  

  4. 彙編指令

  4.1. Load/Store指令

   RAM通路相關

  關于RAM的通路隻能使用Load/Store指令。

  

  分類 指令格式 注釋

  Load li register_destination, value 立即數加載。 把value 加載到目标寄存器

   lw register_destination, RAM_source 從RAM源位址處 複制一個Word(4 Bytes)到目标寄存器

   lb register_destination, RAM_source 從RAM源位址處 複制一個Byte到目标寄存器的低端處

  Store sw register_source, RAM_ destination 把源寄存器中的值(4 Bytes)存儲到RAM目的位址中

   sb register_source, RAM_ destination 把源寄存器的低端1個Byte, 存儲到RAM目的位址中

  

   尋址相關指令

  

  分類 指令格式與執行個體 注釋

  Load la $t0, val_1 複制val_1表示的位址到t0寄存器中

  注: val_1是個Label

   lw $t2, ($t0) t0寄存器中的值作為位址,把這個位址起始的Word 複制到t2 中

   lw $t2, 4($t0) t0寄存器中的值作為位址, 把這個位址再加上偏移量4後 所起始的Word 複制到t2 中

  Store sw $t2, ($t0) 把t2寄存器中值(1 Word),存儲到t0的值所指向的RAM中

   sw $t2, -12($t0) 把t2寄存器中值(1 Word),存儲到t0的值再減去偏移量12, 所指向的RAM 中

  

  4.2. 算數運算指令

   算數運算指令的所有操作數都是寄存器,不能直接使用RAM位址或間接尋址。

   操作數的大小都為 Word (4-Byte)

  指令格式與執行個體 注釋

  move $t5, $t1 $t5 = $t1;

  add $t0, $t1, $t2 $t0 = $t1 + $t2; 帶符号數相加

  sub $t0, $t1, $t2 $t0 = $t1 - $t2; 帶符号數相減

  addi $t0, $t1, 5 $t0 = $t1 + 5;

  addu $t0, $t1, $t2 $t0 = $t1 + $t2; 無符号數相加

  subu $t0, $t1, $t2 $t0 = $t1 - $t2; 無符号數相減

  mult $t3, $t4 $t3 乘以 $t4, 把64-Bits 的積,存儲到Lo,Hi中。

  即: (Hi, Lo) = $t3 * $t4;

  div $t5, $t6 Lo = $t5 / $t6 (Lo為商的整數部分)

  Hi = $t5 mod $t6 (Hi為餘數)

  mfhi $t0 $t0 = Hi

  mflo $t1 $t1 = Lo

  

  4.3. 分支跳轉指令

   分支指令

  指令格式與執行個體 注釋

  b target 無條件的分支跳轉,将跳轉到target 标簽處

  beq $t0, $t1, target 如果 $t0 == $t1, 則跳轉到target 标簽處

  blt $t0, $t1, target 如果 $t0 < $t1, 則跳轉到target 标簽處

  ble $t0, $t1, target 如果 $t0 <=$t1, 則跳轉到target 标簽處

  bgt $t0, $t1, target 如果 $t0 > $t1, 則跳轉到target 标簽處

  bge $t0, $t1, target 如果 $t0 >= $t1, 則跳轉到target 标簽處

  bne $t0, $t1, target 如果 $t0 != $t1, 則跳轉到target 标簽處

  

   跳轉指令

  指令格式與執行個體 注釋

  j target 無條件的跳轉, 将跳轉到target 标簽處

  jr $t3 跳轉到t3寄存器所指向的位址處(Jump Register)

  

  4.4. 子函數調用指令

  指令格式與執行個體 注釋

  jal sub_routine_label 執行步驟:

  1. 複制目前的PC(Program Counter)到$ra寄存器中。 因為目前的PC 值就是子函數執行完畢後的傳回位址。

  2. 程式跳轉到子程式标簽sub_routine_label處。

  

  注:子函數的傳回,使用 jr $ra

  

  如果子函數内又調用了其他的子函數,那麼$ra的值應該被儲存到堆棧中。 因為$ra的值總是對應着目前執行的子函數的傳回位址。

【天涯部落格】本文位址http://blog.tianya.cn/blogger/post_show.asp?BlogID=1915807&PostID=18868775