日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

MIPS快速入门(原文+翻译):MIPS Architecture and Assembly Language Overview(持续更新中)

發(fā)布時(shí)間:2023/11/30 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MIPS快速入门(原文+翻译):MIPS Architecture and Assembly Language Overview(持续更新中) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

前言

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

本文不得用于其他用途,侵刪,轉(zhuǎn)載請(qǐng)加上原文鏈接。

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

點(diǎn)此獲取 >>> 英文原文資源鏈接

其實(shí)我并不建議你看翻譯,因?yàn)闊o論如何,翻譯過后都會(huì)造成信息損失甚至錯(cuò)誤,強(qiáng)烈建議直接看英文原文。

0 MIPS架構(gòu)及匯編語言概述

0.1 數(shù)據(jù)類型及字面含義

0.1.1數(shù)據(jù)類型

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

譯者注:
[1] 在MARS模擬器,半字用half
[補(bǔ)充] 在32位環(huán)境下,C語言的char是1個(gè)字節(jié),short是2個(gè)字節(jié),int是4個(gè)字節(jié),可以對(duì)比學(xué)習(xí),關(guān)于有無符號(hào)的問題,請(qǐng)先忽略,不妨之后深入學(xué)習(xí)MIPS數(shù)據(jù)及指令再了解。

0.1.2 字面值[1]

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

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

0.2 寄存器(registers)

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

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

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

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

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

譯者注
[1] 譯者此處將圖片以表格形式表現(xiàn)了出來。
[2] 原文Alternative name,中文意思就是:與寄存器編號(hào)等價(jià)的名字,比如,$2與$v0等價(jià)。
[補(bǔ)充1] 這里我們可以注意到,32個(gè)寄存器被分成了不同類別,它們都有不同的用途,雖然它們都是通用寄存器,但是使用的時(shí)候,還是應(yīng)該盡量按照實(shí)際功能去使用,以免發(fā)生不可知的錯(cuò)誤。
[補(bǔ)充2] 學(xué)習(xí)建議:這部分內(nèi)容,看一看有大概印象即可,不要強(qiáng)行記憶,因?yàn)槌鯇W(xué)者不太可能看得懂這些都是什么,后面需要的時(shí)候再回看,再查閱即可。

1 程序結(jié)構(gòu)

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

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

1.1 數(shù)據(jù)聲明

  • 放置在程序段中,使用編譯器指令.data來標(biāo)識(shí)
  • 聲明在程序中使用的變量名;存儲(chǔ)(的變量)會(huì)被分配到主內(nèi)存(RAM)中

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

  • 在MIPS源程序進(jìn)行數(shù)據(jù)聲明的時(shí)候,需要先加上.data,再進(jìn)行數(shù)據(jù)聲明
  • 在程序中需要用到的數(shù)據(jù),需要先在數(shù)據(jù)段進(jìn)行聲明,并為這些數(shù)據(jù)起名
  • 這些你聲明好的變量(的值),在程序運(yùn)行的時(shí)候,會(huì)被系統(tǒng)分配到主內(nèi)存中

譯者注:數(shù)據(jù)聲明在源程序中應(yīng)該是這樣的

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

1.2 代碼

  • (代碼需要)放在文本(text)部分,并用.text來標(biāo)識(shí)
  • (.text后面的文本)包含程序代碼指令
  • 代碼執(zhí)行的起始點(diǎn)要給定一個(gè)標(biāo)簽,例如main
  • 主代碼的結(jié)束點(diǎn)應(yīng)該使用“退出系統(tǒng)調(diào)用(功能)”,看下面的系統(tǒng)調(diào)用篇

1.3 注釋

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

譯者注:
[1] 這里的注釋,也就是所謂的“單行注釋”。
[補(bǔ)充] 下面的1.4節(jié)在原文中是包含在1.3節(jié)的,譯者這里將其單獨(dú)拿出來,以強(qiáng)調(diào)MIPS源程序結(jié)構(gòu)框架。

1.4 MIPS源程序結(jié)構(gòu)框架示例

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

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

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

.data # 此處進(jìn)行數(shù)據(jù)聲明.text main: # 這是程序入口# 此處編輯程序代碼

2 數(shù)據(jù)聲明

數(shù)據(jù)聲明的形式:

name: storage_type value(s)

以上語句的含義是:

  • 為變量創(chuàng)建一個(gè)倉庫(storage)[1],它指定了數(shù)據(jù)類型,給定了變量名和變量的值
  • 變量的值通常會(huì)給定初始值;對(duì)于存儲(chǔ)類型.space,給出要被分配的空間的數(shù)字[2]

注意:標(biāo)簽[3]后面總是跟著冒號(hào):

譯者注:
[1] 可以理解為存儲(chǔ)變量的容器
[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條

  • 創(chuàng)建一個(gè)integer類型的變量,變量名為var2,變量的值初始化為3
  • 創(chuàng)建一個(gè)字符數(shù)組array1,包含2個(gè)字符類型元素,它們的值分別被初始化為a和b
  • 創(chuàng)建一個(gè)空的空間array2,在內(nèi)存中分配40個(gè)連續(xù)的字節(jié),這個(gè)沒有被初始化的storage可能是一個(gè)含有40個(gè)元素的字符數(shù)組,也可能是一個(gè)含有10個(gè)元素的integer數(shù)組,由于不確定,因此建議在注釋中說明space的用途。
  • 3 load/store[1]指令

    • RAM的訪問,只能使用load和store指令[2]
    • 其他的指令只能使用寄存器操作數(shù)

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

    load:

    # 從RAM源位置,復(fù)制1個(gè)字(4個(gè)字節(jié))到目標(biāo)寄存器 lw register_destination, RAM_source# 從RAM源位置,復(fù)制1個(gè)字節(jié)到目標(biāo)寄存器的低序字節(jié) # 并且對(duì)字節(jié)進(jìn)行符號(hào)擴(kuò)展,填充到高位字節(jié)中 lb register_destination, RAM_source

    store:

    # 將源寄存器中的字(型數(shù)據(jù)),存到目標(biāo)RAM(地址)中 sw register_source, RAM_destination# 將源寄存器中的低位字節(jié),存到目標(biāo)RAM中 sb register_source, RAM_destination

    load immediate:

    # 加載立即數(shù)到目標(biāo)寄存器 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] 這里不再翻譯,根據(jù)前面的內(nèi)容相信你能理解
    [補(bǔ)充] 注意,這些指令其實(shí)就是英文全稱的縮寫,記憶起來非常容易,其他指令也一樣,要關(guān)注其英文全稱。

    4 間接尋址和基址尋址

    僅被用于load和store指令。

    load address:

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

    indirect addressing:

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

    未完成

    5 算數(shù)運(yùn)算指令

    • 最多使用3個(gè)操作數(shù)
    • 所有操作數(shù)都是寄存器;沒有RAM或者直接尋址
    • 操作數(shù)的大小都是1個(gè)字
    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

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

  • 指令是英文全稱的縮寫,按照意思即可記憶
  • 指令的后綴代表特殊的含義,例如i代表立即數(shù),u代表無符號(hào)數(shù)
  • 6 流程控制

    • 條件分支的比較,被內(nèi)嵌到了指令之中

    branches:

    b target # unconditional branch to program label target # 無條件跳轉(zhuǎn)到程序標(biāo)簽targetbeq $t0,$t1,target # branch to target if $t0 = $t1 # 如果$t0 = $t1,就跳轉(zhuǎn)到target標(biāo)簽# 下面的同理,不再一一翻譯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 # 無條件跳轉(zhuǎn)到程序標(biāo)簽targetjr $t3 # jump to address contained in $t3 ("jump register")# 跳轉(zhuǎn)到某地址,地址的值在寄存器$t3中

    未完成
    subroutine calls:

    subroutine call: “jump and link” instruction

    jal sub_label # "jump and link"

    subroutine return: “jump register” instruction

    jr $ra # "jump register"

    注意:

    譯者注:原文沒有解釋程序標(biāo)簽target,譯者在這里補(bǔ)充一下

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

    .text # 程序代碼部分 main: <代碼 1>j target_1 # 無條件地跳轉(zhuǎn)到標(biāo)簽target_1的位置# 再從該位置繼續(xù)向下執(zhí)行<代碼 2>target_1:<代碼 2>target_2:<代碼 3> ……

    7 系統(tǒng)調(diào)用與I/O(SPIM模擬器[1]

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

    總結(jié)

    以上是生活随笔為你收集整理的MIPS快速入门(原文+翻译):MIPS Architecture and Assembly Language Overview(持续更新中)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。