MIPS快速入門(原文+翻譯):MIPS Architecture and Assembly Language Overview(持續更新中)

前言

發布該文章的網站已經無法訪問,無法獲得相關翻譯授權,本人的翻譯僅供大家參考學習,盡可能使用直譯,并加上一些譯者注(使用“ [1] ”的形式),以減少信息損失,水平有限,不妥之處還請見諒。

本文不得用于其他用途,侵刪,轉載請加上原文鏈接。

Adapted from: http://edge.mcs.dre.g.el.edu/GICL/people/sevy/architecture/MIPSRef(SPIM).html

點此獲取 >>> 英文原文資源鏈接

其實我并不建議你看翻譯,因為無論如何,翻譯過后都會造成信息損失甚至錯誤,強烈建議直接看英文原文。

0 MIPS架構及匯編語言概述

0.1 數據類型及字面含義

0.1.1數據類型

  • 所有指令都是32位
  • 基本數據類型
    • 字節型:byte(8 bits)
    • 半字:halfword(2 bytes)[1]
    • 字型:word(4 bytes)
  • 一個字符(character)需要1個字節的存儲空間
  • 一個整數(integer)需要1個字(4個字節)的存儲空間

譯者注:
[1] 在MARS模擬器,半字用half
[補充] 在32位環境下,C語言的char是1個字節,short是2個字節,int是4個字節,可以對比學習,關于有無符號的問題,請先忽略,不妨之后深入學習MIPS數據及指令再了解。

0.1.2 字面值[1]

  • 數字(numbers)按照原樣輸入,就是,例如:4
  • 字符(characters)被單引號括起來,例如:'b'
  • 字符串(strings)被雙引號括起來,例如:"A string"

譯者注
[1] 英文為Literal,中文不妨理解為:不同類型數據的表示方法。

0.2 寄存器(registers)

  • 32個通用寄存器
  • 在匯編指令中,寄存器以$開頭。訪問(addressing)寄存器的形式有2種:
    • 使用寄存器的編號,例如,從$0$31[1]
    • 使用與編號等價的寄存器名稱,例如,$t1$sp
  • 特殊的寄存器LoHi用于存儲乘法或除法運算的結果
    • 不能直接訪問LoHi寄存器,它們的內容通過特殊的指令訪問:mfhi(move from Hi)和mflo(move from Lo)[2]
  • 棧的增長方向是從存儲器的高地址走向低地址[3]

譯者注
[1] MIPS有32個通用寄存器,編號為0~31。
[2] 這里不是完全直譯,直譯的話看不懂,給出你原文對比一下:not directly addressable; contents accessed with special instruction mfhi (“move
from Hi”) and mflo (“move from Lo”).
[3] 這意味著棧底在高地址,棧頂在低地址;數據入棧的時候,棧頂指針是從高地址往低地址方向走的,出棧反之。
[補充] 在此再補充一下“字節序”,它與硬件的設計有關,通常x86系列的硬件采用小端序,MIPS大部分與網絡字節序一樣,采用大端序,也有采用小端序的,不過后來增強了可移植性,采用雙端序,既可以使用小端模式也可以使用大端模式。(參考鏈接在此)

這是來自Goodman&Miller的圖9.9[1]注:功能描述請參考原文,這里沒有完全翻譯,對于初學者來說沒有意義。

寄存器編號可代替的名字[2]英文全稱(功能)描述
0$zerozero值恒為0
1$atassembler temporary匯編器保留寄存器
2-3$v0 , $v1values值來自于表達式求值和函數結果
4-7$a0 - $a3arguments存儲子程序調用的前4個非浮點參數,在子程序中不會跨子程序保存
8-15$t0 - $t7temporaries暫存寄存器
16-23$s0 - $s7saved values通用寄存器
24-25$t8 - $t9temporaries臨時變量,與$t0 - $t7一樣
26-27$k0 , $k1kernel reserved操作系統內核保留寄存器,用于中斷處理
28$gpglobal pointer全局指針
29$spstack pointer棧指針,指向棧頂
30$s8 / $fpsaved values / frame pointer幀指針,用于過程調用
31$rareturn address返回地址

也參考了Britton的章節1.9,Sweetman的章節2.21,Larus的附錄章節A.6。

譯者注
[1] 譯者此處將圖片以表格形式表現了出來。
[2] 原文Alternative name,中文意思就是:與寄存器編號等價的名字,比如,$2$v0等價。
[補充1] 這里我們可以注意到,32個寄存器被分成了不同類別,它們都有不同的用途,雖然它們都是通用寄存器,但是使用的時候,還是應該盡量按照實際功能去使用,以免發生不可知的錯誤。
[補充2] 學習建議:這部分內容,看一看有大概印象即可,不要強行記憶,因為初學者不太可能看得懂這些都是什么,后面需要的時候再回看,再查閱即可。

1 程序結構

  • 純文本文件中只有數據聲明和程序代碼[1](文件名的后綴為.s,以能夠在SPIM模擬器運行[2]
  • 數據聲明部分后面跟著程序代碼部分[3]

譯者注:
[1] 意思是:MIPS源程序要在文本編輯器進行編輯,包含數據聲明和程序代碼。
[2] 推薦使用MARS模擬器來進行運行MIPS程序,這款軟件一定程度兼容SPIM,并且提供了更加豐富的插件。另外,MIPS源程序文件的后綴可以是.s,也可以是.asm
[3] 先聲明數據,然后再寫處理數據的代碼。

1.1 數據聲明

  • 放置在程序段中,使用編譯器指令.data來標識
  • 聲明在程序中使用的變量名;存儲(的變量)會被分配到主內存(RAM)中

譯者注:直譯后表示很難受,可能我水平不夠吧……我用漢語描述一遍

  • 在MIPS源程序進行數據聲明的時候,需要先加上.data,再進行數據聲明
  • 在程序中需要用到的數據,需要先在數據段進行聲明,并為這些數據起名
  • 這些你聲明好的變量(的值),在程序運行的時候,會被系統分配到主內存中

譯者注:數據聲明在源程序中應該是這樣的

.data  # 我要開始寫數據聲明了!variable_name_1: .word 11 # 聲明了一個變量(先不用管語法)# 值:11# 變量名:variable_name_1# <其他數據聲明>……

1.2 代碼

  • (代碼需要)放在文本(text)部分,并用.text來標識
  • .text后面的文本)包含程序代碼指令
  • 代碼執行的起始點要給定一個標簽,例如main
  • 主代碼的結束點應該使用“退出系統調用(功能)”,看下面的系統調用篇

1.3 注釋

在一行上,任何在#之后的內容,將會被(編譯器)認為是注釋[1]

譯者注:
[1] 這里的注釋,也就是所謂的“單行注釋”。
[補充] 下面的1.4節在原文中是包含在1.3節的,譯者這里將其單獨拿出來,以強調MIPS源程序結構框架。

1.4 MIPS源程序結構框架示例

下面是MIPS匯編語言程序的模板:

# 注釋部分給出了程序名和函數描述
# 文件名:Template.s 
# 這是最基本的MIPS匯編語言程序框架.data 	# 這行之后是變量聲明
# ... .text	 # 這行之后的是指令 main: 	# 指出代碼的起始點(第一個要執行的指令) 
# ... # End of program, leave a blank line afterwards to make SPIM happy
# 程序的結尾留出一個空行,讓SPIM高興[1]

譯者注:
[1] make SPIM happy……外國人太有趣了,這句話含義就是,程序結束的時候多一個空行,這樣看起來程序美觀好看。
[補充] 原文程序的注釋太多了,程序結構都看不見了…讓我們留下最寶貴的部分,刪掉冗余部分

.data # 此處進行數據聲明.text
main:	# 這是程序入口# 此處編輯程序代碼

2 數據聲明

數據聲明的形式:

name:	storage_type	value(s)

以上語句的含義是:

  • 為變量創建一個倉庫(storage)[1],它指定了數據類型,給定了變量名和變量的值
  • 變量的值通常會給定初始值;對于存儲類型.space,給出要被分配的空間的數字[2]

注意:標簽[3]后面總是跟著冒號:

譯者注:
[1] 可以理解為存儲變量的容器
[2] 也就是空間的大小
[3] 指的是變量名

例子:

var1: .word 3			# create a single integer variable with initial value 3 
array1: .byte 'a','b' 	# create a 2-element character array with elements initialized to a and b 
array2: .space 40 		# allocate 40 consecutive bytes, with storage uninitialized could be used as a 40-element character array# or a 10-element integer array; a comment should indicate which!

譯者注:分別解釋一下這3條

  1. 創建一個integer類型的變量,變量名為var2,變量的值初始化為3
  2. 創建一個字符數組array1,包含2個字符類型元素,它們的值分別被初始化為ab
  3. 創建一個空的空間array2,在內存中分配40個連續的字節,這個沒有被初始化的storage可能是一個含有40個元素的字符數組,也可能是一個含有10個元素的integer數組,由于不確定,因此建議在注釋中說明space的用途。

3 load/store[1]指令

  • RAM的訪問,只能使用loadstore指令[2]
  • 其他的指令只能使用寄存器操作數

譯者注:
[1] load意為“加載”,可以理解為“讀取”,CPU從內存中讀取信息;store意為“存儲”,可以理解為“寫入”,CPU向內存寫入信息。
[2] MIPS為RICS指令集,相比x86,它的尋址方式很少,只有這兩條指令可以訪問內存,也就是說,其他指令的操作數,不允許出現內存操作數

load

# 從RAM源位置,復制1個字(4個字節)到目標寄存器
lw register_destination, RAM_source# 從RAM源位置,復制1個字節到目標寄存器的低序字節
# 并且對字節進行符號擴展,填充到高位字節中
lb register_destination, RAM_source

store

# 將源寄存器中的字(型數據),存到目標RAM(地址)中
sw register_source, RAM_destination# 將源寄存器中的低位字節,存到目標RAM中
sb register_source, RAM_destination

load immediate

# 加載立即數到目標寄存器
li register_destination, value

舉例[1]

 .data var1: .word 23 		# declare storage for var1; initial value is 23 .text 
__start: lw $t0, var1 		# load contents of RAM location into register $t0: $t0 = var1 li $t1, 5 			# $t1 = 5 ("load immediate") sw $t1, var1 		# store contents of register $t1 into RAM: var1 = $t1  done

譯者注:
[1] 這里不再翻譯,根據前面的內容相信你能理解
[補充] 注意,這些指令其實就是英文全稱的縮寫,記憶起來非常容易,其他指令也一樣,要關注其英文全稱。

4 間接尋址和基址尋址

僅被用于loadstore指令。

load address

la	$t0, var1
  • var1(可能是在程序中被定義的標簽)的RAM地址復制到寄存器$0

indirect addressing

lw	$t2, ($t0)
  • 加載1個字大小的數據到$t2中,數據的地址在$t0中,數據在數據地址指向的內存單元中
sw	$t2, -12($t0)

未完成

5 算數運算指令

  • 最多使用3個操作數
  • 所有操作數都是寄存器;沒有RAM或者直接尋址
  • 操作數的大小都是1個字
add	 $t0,$t1,$t2 	# $t0 = $t1 + $t2; add as signed (2's complement) integers 
sub	  $t2,$t3,$t4 	# $t2 = $t3 D $t4 
addi  $t2,$t3, 5 	# $t2 = $t3 + 5; "add immediate" (no sub immediate) 
addu  $t1,$t6,$t7   # $t1 = $t6 + $t7; add as unsigned integers 
subu  $t1,$t6,$t7   # $t1 = $t6 + $t7; subtract as unsigned integers mult  $t3,$t4 		
# multiply 32-bit quantities in $t3 and $t4, and store 64-bit 
# result in special registers Lo and Hi: (Hi,Lo) = $t3 * $t4 div	  $t5,$t6 		
# Lo = $t5 / $t6 (integer quotient) 
# Hi = $t5 mod $t6 (remainder) mfhi   $t0	 # move quantity in special register Hi to $t0: $t0 = Hi 
mflo   $t1	 # move quantity in special register Lo to $t1: $t1 = Lo # used to get at result of product or quotient move   $t2,$t3 		# $t2 = $t3

譯者注:
這里不翻譯了,表達式能夠看懂,注意觀察指令的規律,使用分治思想理解記憶:

  1. 指令是英文全稱的縮寫,按照意思即可記憶
  2. 指令的后綴代表特殊的含義,例如i代表立即數,u代表無符號數

6 流程控制

  • 條件分支的比較,被內嵌到了指令之中

branches

b	target 		# unconditional branch to program label target # 無條件跳轉到程序標簽targetbeq 	$t0,$t1,target 		# branch to target if $t0 = $t1 # 如果$t0 = $t1,就跳轉到target標簽# 下面的同理,不再一一翻譯blt 	$t0,$t1,target 		# branch to target if $t0 < $t1 
ble 	$t0,$t1,target 		# branch to target if $t0 <= $t1 
bgt 	$t0,$t1,target 		# branch to target if $t0 > $t1 
bge 	$t0,$t1,target 		# branch to target if $t0 >= $t1 
bne 	$t0,$t1,target 		# branch to target if $t0 <> $t1

譯者注:這里的指令,都是英文全稱,比如beq就是branch equal,其余的讀者自行查閱。

jumps

j	    target 		# unconditional jump to program label target # 無條件跳轉到程序標簽targetjr 		$t3 		# jump to address contained in $t3 ("jump register")# 跳轉到某地址,地址的值在寄存器$t3中

未完成
subroutine calls

subroutine call: “jump and link” instruction

jal		sub_label		 # "jump and link"

subroutine return: “jump register” instruction

jr	$ra		 # "jump register"

注意:

譯者注:原文沒有解釋程序標簽target,譯者在這里補充一下

我給出你MIPS源程序的.text部分,我們知道,程序的入口是main標簽,事實上,還可以類似地定義很多標簽,跳轉指令中的target指的就是這些,以下為示例:

.text            # 程序代碼部分 main:  <代碼 1>j	target_1		# 無條件地跳轉到標簽target_1的位置# 再從該位置繼續向下執行<代碼 2>target_1:<代碼 2>target_2:<代碼 3>
……    

7 系統調用與I/O(SPIM模擬器[1]

譯者注:
[1] MARS模擬器兼容了一部分SPIM的系統調用,基本是夠用的,依然推薦使用MARS模擬器。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/384716.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/384716.shtml
英文地址,請注明出處:http://en.pswp.cn/news/384716.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Visual Studio 編譯優化選項:Debug與Release、禁止優化與O1、O2、Ox優化

Debug與禁止優化 Debug模式是調試模式&#xff0c;會有很多冗余的調試代碼&#xff0c;供開發者調試程序使用。 VS是默認使用Debug模式的&#xff0c;我使用的是VS 2017。 在Debug模式下&#xff0c;是默認開啟禁止優化的&#xff0c;我們來查看一下 在左側源文件的main.c處…

【匯編語言】記錄一組數中負數的個數,8086與MIPS匯編程序

題目及解答 統計由DATA開始的字節數據串中負元素的個數&#xff0c;數據個數在COUNT單元&#xff0c;統計結果存入RLT單元。 8086匯編&#xff1a; ; 統計數字中負數的個數【循環中加了個if else】 assume ds:datasg datasg segmentdata db 1,-2,-3,-1,-4,0,-2 count dw 7 ; 數…

【數字邏輯入門】計算機如何存儲1位二進制數

0 前言 本文將會以R-S鎖存器為例&#xff0c;引出鎖存器的核心和本質&#xff0c;之后再帶你構建更多類型的鎖存器&#xff0c;你能夠&#xff1a; 感受到由淺入深的學習方式體會到掌握核心本質的快感深刻理解核心套外殼的設計理念&#xff08;產品迭代1.0–>2.0–>3.0…

【算法訓練】DAY1:整數反轉

1 前言 題目來源于Leetcode。 重點&#xff1a;理清邏輯&#xff0c;忽略細節&#xff0c;模仿高手&#xff0c;五毒神掌 2 題目分析 題目很容易理解&#xff0c;先分成兩個部分 正數負數 先解決正數 最開始想到的是 intchar數組long唯一增加的就是&#xff0c;先判斷整…

【匯編語言】(x86)test與跳轉指令(je jle jge jg jl……)組合的含義

在x86指令集中&#xff0c;經常遇到test指令與條件跳轉指令組合&#xff0c;這是什么含義呢&#xff1f; 博主表示&#xff0c;查了很多資料也沒人完全說清楚…… 這里只用最簡單的&#xff0c;抽象層次進行說明&#xff0c;不講原理。 舉例 test edx,edx jle 某地址含義是&…

【藍橋杯】BASIC-8 回文數(2020-06-08)

題目 試題 基礎練習 回文數 資源限制 時間限制&#xff1a;1.0s 內存限制&#xff1a;512.0MB 問題描述   1221是一個非常特殊的數&#xff0c;它從左邊讀和從右邊讀是一樣的&#xff0c;編程求所有這樣的四位十進制數。    輸出格式   按從小到大的順序輸出滿足條件的…

【算法訓練】Leetcode 1295. 統計位數為偶數的數字(2020.06.09 )

1 題目 1295. 統計位數為偶數的數字 給你一個整數數組 nums&#xff0c;請你返回其中位數為 偶數 的數字的個數。 示例 1&#xff1a; 輸入&#xff1a;nums [12,345,2,6,7896] 輸出&#xff1a;2 解釋&#xff1a; 12 是 2 位數字&#xff08;位數為偶數&#xff09; 345 …

Vivado設置指定源文件進行RTL優化

像VS編譯器設置啟動項一樣&#xff0c;Vivado中&#xff0c;也有類似設計&#xff0c;可以看到&#xff0c;當前選中的是ALU&#xff0c;那么進行RTL優化的時候&#xff0c;會優化RTL的結果&#xff0c;而不是別的&#xff0c;如何改成別的&#xff1f; 在某文件上右鍵單擊選擇…

【完整流程】用VSCode替換Vivado默認編輯器

本文樓主找了很多資料&#xff0c;選出了最有用的資料&#xff0c;按照教程走&#xff0c;就可以順利搞定&#xff0c;先給出畫面 很酷很方便&#xff0c;同時還有 自動補全檢測錯誤列選自動生成仿真測試文件 等重要功能 Vivado原來的編輯器是這樣的…… 關鍵是&#xff0c…

IEDA中JavaDoc的自動生成、手動生成,以及生成html文檔

1 自動生成類的注釋 JavaDoc就是java特有的一種注釋。 1.1 配置 首先&#xff0c;IDEA點擊File-->Settings 然后Editor-->File and Code Templates-->Class 之后在這地方&#xff0c;添加一些代碼 /** * ${description} * * <p> * 創建日期&#xff1a;$…

【java】父類與子類的引用賦值關系

理清楚4個目標 父類引用&#xff08;“名”&#xff09;父類對象&#xff08;“實”&#xff09;子類引用子類對象 理清楚幾個操作 // 父類 public class parent{}// 子類 public class sun{}父類引用指向父類對象 parent p1 new parent();子類引用指向子類對象 son s1 …

IDEA自動生成 構造方法 get set方法

對于一個類&#xff0c;創建好成員變量后 右鍵單擊&#xff0c;選中Generate 然后 這幾個依次是 構造方法getsetget和set 我們可以選中一個&#xff0c;然后選中要生成的變量&#xff0c;點擊OK 這樣就可以自動生成 構成方法get方法set方法

IDEA快速修改類名和文件名

在你要修改的類名上&#xff0c;選中類名&#xff0c;然后 右鍵單擊選中Refactor選中Rename 也可以使用快捷鍵 Win用戶是Shift F6

java中 靜態方法與成員方法何時使用

靜態方法 不操作成員變量&#xff0c;可以直接調用 是用來直接對傳入的數據進行操作的 成員方法 需要操作對象的成員變量的 區別 靜態方法&#xff0c;不能操作成員變量&#xff0c;只是一個操作成員方法&#xff0c;可以操作成員變量&#xff0c;不僅僅是操作&#xff0…

通過編程解決問題的正確思路

1. 先知道我們面對一個怎樣的問題 2. 考慮這個問題在現實生活中&#xff0c;我們要用怎樣的方式去解決 3. 從現實到計算機&#xff0c;如何用編程的思路解決 4. 實現&#xff0c;編碼和測試 5. 迭代 現實問題自然語言解決方案機器語言解決方案編碼實現測試迭代

數據庫設計的核心原則 外鍵的設計 提高插入數據速度

大道至簡&#xff1a;數據庫設計的核心原則 數據庫設計&#xff0c;不得不承認&#xff0c;有很多專業化的理論知識&#xff0c;但是對于初學者來說&#xff0c;只需要大道至簡的原則就可以了。 能不重復的就不重復&#xff0c;太重復的就拆開&#xff0c;使用指定數據做識別…

MySQL提高插入數據的效率(結合JDBC)

0 解決問題最佳途徑&#xff1a;直接找官方 先說明的是&#xff0c;有問題直接去找官方文檔&#xff0c;而不應該去百度搜索&#xff0c;您很容易體驗到&#xff0c;搜索引擎很難快速找到真正對您有價值的解決方案&#xff0c;而官方文檔是最快捷的途徑。 本篇也是基于官方文…

【計算機心理學】先設計再實現 在實現中完善設計

先設計再實現 在物理學中&#xff0c;通常都是先理論證明觀點&#xff0c;再進行實踐&#xff0c;然后&#xff0c;再有世界各地的科學家根據理論進行實驗&#xff0c;以證明觀點正確。 在計算機軟件開發&#xff0c;硬件開發等&#xff0c;都講求先邏輯抽象設計&#xff0c;…

【FPGA VerilogHDL】第一次嘗試:LED燈基礎實驗

0 實驗環境 0.1 軟件環境 ISE 14.7win10vivado 2017.4 0.2 硬件設備 ISE適用的FPGA開發板&#xff1a;ALINK AX309 1 需求 能夠靈活控制4個LED燈 2 Verilog實現 timescale 1ns / 1ps // // Create Date: 14:18:20 08/08/2020 // Module Name: led // Revision…

使用ISE一鍵生成bit文件

我們知道&#xff0c;這幾個&#xff0c;在第一次做好源文件之后&#xff0c;需要一個個進行右鍵單擊-->run&#xff0c;以發現錯誤。 但是之后的調試&#xff0c;只要一點點變化&#xff0c;哪怕是注釋變化&#xff0c;都需要重新run3次&#xff0c;太麻煩了。 不過經過實…