MIPS 体系结构和汇编语言快速入门.docx
- 文档编号:7161544
- 上传时间:2023-01-21
- 格式:DOCX
- 页数:13
- 大小:49.55KB
MIPS 体系结构和汇编语言快速入门.docx
《MIPS 体系结构和汇编语言快速入门.docx》由会员分享,可在线阅读,更多相关《MIPS 体系结构和汇编语言快速入门.docx(13页珍藏版)》请在冰豆网上搜索。
MIPS体系结构和汇编语言快速入门
MIPS体系结构和汇编语言快速入门
译者:
SonicFu,NortheasternUniversity,Boston,MA,USA
译者按:
有修改,无删减,初学必读。
学习笔记,抛砖引玉!
网上有一个老版本,不如此版全面。
英文原版:
http:
//logos.cs.uic.edu/366/notes/mips%20quick%20tutorial.htm#IOSystemCalls
本文分3部分:
1、寄存器2、程序结构框架3、编写汇编程序
概要:
数据类型和文法
¡数据类型:
字节,byte占用(8bit),halfword占2byte=16bit),word占用(4byte=32bit)
¡一个字符需要一个Byte的空间;
¡一个整数需要1个Word(4Byte)的空间;
¡MIPS结构的每条指令长度都是32bit
寄存器
¡MIPS体系架构有32个通用寄存器。
在汇编程序中,可以用编号$0到$31来表示;
¡也可以用寄存器的名字来进行表示,例如:
$sp,$t1,$ra….
¡有两个特殊的寄存器Lo,Hi,用来保存乘法/除法的运算结果;此2寄存器不能直接寻址,只能用特殊的指令:
mfhi和mflo来aceess其中的内容。
(含义:
mfhi=movefromHi,mflo=MovefromLow.)
¡堆栈(Stack)的增长方向是:
从内存的高地址方向,向低地址方向;
表格1:
寄存器的编号名称及分类
编号
寄存器名称
寄存器描述
0
Zero
第0号寄存器,其值始终为0
1
$at
(AssemblerTemporary)是Assembler保留的寄存器
2~3
$v0~$v1
(values)保存表达式或函数返回的结果
4-7
$a0-$a3
(arguments)作为函数的前四个入参。
在子函数调用的过程中不会被保留。
8-15
$t0-$t7
(temporaries)Callersavedifneeded.Subroutinescanusewithoutsaving.供汇编程序使用的临时寄存器。
在子函数调用的过程中不会被保留。
16-23
$s0-$s7
(savedvalues)-Calleesaved.
Asubroutineusingoneofthesemustsaveoriginalandrestoreitbeforeexiting.在子函数调用的过程中会被保留。
24-25
$t8-$t9
(temporaries)Callersavedifneeded.Subroutinescanusewithoutsaving.供汇编程序使用的临时寄存器。
在子函数调用的过程中不会被保留。
这是对$t0-$t7的补充。
26-27
$k0-$k1
保留,仅供中断(interrupt/trap)处理函数使用.
28
$gp
global pointer. 全局指针。
Pointstothemiddleofthe64Kblockofmemoryinthestaticdatasegment.指向固态数据块内存的64K的块的中间。
29
$sp
stack pointer 堆栈指针,指向堆栈的栈顶。
30
$s8/$fp
savedvalue/ frame pointer保存的值/帧指针
其中的值在函数调用的过程中会被保留
31
$ra
return address返回地址
汇编程序结构框架
汇编源程序代码本质上是文本文件。
由数据声明、代码段两部分组成。
汇编程序文件应该以.s为后缀,以在Spim软件中进行模拟。
(实际上ASM也行。
)
数据声明部分
在源代码中,数据声明部分以.data开始。
声明了在代码中使用的变量的名字。
同时,也在主存(RAM)中创建了对应的空间。
程序代码部分
在源代码中,程序代码部分以.text开始。
这部分包含了由指令构成的程序功能代码。
代码以main:
函数开始。
main的结束点应该调用exitsystemcall,参见后文有关systemcall的介绍。
程序的注释部分
使用#符号进行注释。
每行以#引导的部分都被视作注释。
一个MIPS汇编程序框架:
#Commentgivingnameofprogramanddescriptionoffunction
#Template.s
#Bare-bonesoutlineofMIPSassemblylanguageprogram
.data#variabledeclarationsfollowthisline
#...
.text#instructionsfollowthisline
main:
#indicatesstartofcode(firstinstructiontoexecute)
#...
#Endofprogram,leaveablanklineafterwardstomakeSPIMhappy
编写MIPS汇编程序:
Content:
PartI:
数据的声明
PartII:
数据的装载和保存(Load/Store指令)
PartIII:
寻址
PartIV:
算术运算指令:
ArithmeticInstructions
PartV程序控制指令:
ControlInstructions
PartVI:
系统调用和I/O操作(SPIM仿真)
PartI:
数据的声明
格式:
name:
storage_typevalue(s)
创建一个以name为变量名称,values通常为初始值,storage_type代表存储类型。
注意:
变量名后要跟一个:
冒号
example
var1:
.word3#createasingleinteger:
#variablewithinitialvalue3
array1:
.byte'a','b'#createa2-elementcharacter
#arraywithelementsinitialized:
#toaandb
array2:
.space40#allocate40consecutivebytes,
#withstorageuninitialized
#couldbeusedasa40-element
#characterarray,ora
#10-elementintegerarray;
#acommentshouldindicateit.
string1.asciiz"Printthis.\n"#declareastring
PartII:
数据的装载和保存(Load/Store指令)
¡主存(RAM)的存取access只能用load/store指令来完成。
¡所有其他的指令都使用的是寄存器作为操作数。
i.load指令:
lwregister_destination,RAM_source
#copyword(4bytes)at
#source_RAMlocation
#todestinationregister.
#loadword->lw
lbregister_destination,RAM_source
#copybyteatsourceRAM
#locationtolow-orderbyteof
#destinationregister,
#andsign-e.g.tendto
#higher-orderbytes
#loadbyte->lb
liregister_destination,value
#loadimmediatevalueinto
#destinationregister
#loadimmediate-->li
ii.store指令
swregister_source,RAM_destination
#storewordinsourceregister
#intoRAMdestination
sbregister_source,RAM_destination
#storebyte(low-order)in
#sourceregisterintoRAM
#destination
举个例子:
.data
var1:
.word23#declarestorageforvar1;
#initialvalueis23
.text
__start:
lw$t0,var1#loadcontentsofRAMlocation
#intoregister$t0:
#$t0=var1
li$t1,5#$t1=5("loadimmediate")
sw$t1,var1#storecontentsofregister$t1
#intoRAM:
var1=$t1done
done
PartIII:
寻址:
MIPS系统结构只能用load/store相关指令来实现寻址操作,包含3中寻址方式:
装载地址:
loadaddress,相当于直接寻址,把数据地址直接载入寄存器。
间接寻址:
indirectaddressing,间接寻址,把寄存器内容作为地址
基线寻址/索引寻址:
basedorindexedaddressing,相对寻址,利用补偿值(offset)寻址。
直接寻址/装载地址:
loadaddress:
la$t0,var1
把var1在主存(RAM)中的地址拷贝到寄存器t0中。
var1也可以是程序中定义的一个子程序标签的地址。
间接寻址:
indirectaddressing:
lw$t2,($t0)
主存中有一个字的地址存在t0中,按这个地址找到那个字,把字拷贝到寄存器t2中。
sw$t2,($t0)
把t2中的字存入t0中的地址指向的主存位置。
基线寻址/索引寻址:
basedorindexedaddressing:
lw$t2,4($t0)
把t0中地址+4所得的地址所对应的主存中的字载入寄存器t2中,4为包含在t0中的地址的偏移量。
sw$t2,-12($t0)#offsetcanbenegative
把t2中的内容存入t0中的地址-12所得的地址所对应的主存中,存入一个字,占用4字节,消耗4个内存号,可见,地址偏移量可以是负值。
注意:
基线寻址在以下场合特别有用:
1、数组:
从基址出发,通过使用偏移量,存取数组元素。
2、堆栈:
利用从堆栈指针或者框架指针的偏移量来存取元素。
举个例子:
#example
.data
array1:
.space12#declare12bytesofstorage
#toholdarrayof3integers
.text
__start:
la$t0,array1#loadbaseaddressofarray
#intoregister$t0
li$t1,5#$t1=5("loadimmediate")
sw$t1,($t0)#firstarrayelementsetto5;
#indirectaddressing
li$t1,13#$t1=13
sw$t1,4($t0)#secondarrayelementsetto13
li$t1,-7#$t1=-7
sw$t1,8($t0)#thirdarrayelementsetto-7
done
PartIV算术运算指令:
ArithmeticInstructions
¡算数运算指令的所有操作数都是寄存器,不能直接使用RAM地址或间接寻址。
¡操作数的大小都为Word(4-Byte)
add$t0,$t1,$t2#$t0=$t1+$t2;addassigned
#(2'scomplement)integers
sub$t2,$t3,$t4#$t2=$t3Ð$t4
addi$t2,$t3,5#$t2=$t3+5;"addimmediate"
#(nosubimmediate)
addu$t1,$t6,$t7#$t1=$t6+$t7;
addu$t1,$t6,5#$t1=$t6+5;
#addasunsignedintegers
subu$t1,$t6,$t7#$t1=$t6-$t7;
subu$t1,$t6,5#$t1=$t6-5
#subtractasunsignedintegers
mult$t3,$t4#multiply32-bitquantitiesin$t3
#and$t4,andstore64-bit
#resultinspecialregistersLo
#andHi:
(Hi,Lo)=$t3*$t4
div$t5,$t6#Lo=$t5/$t6(integerquotient)
#Hi=$t5mod$t6(remainder)
mfhi$t0#movequantityinspecialregisterHi
#to$t0:
$t0=Hi
mflo$t1#movequantityinspecialregisterLo
#to$t1:
$t1=Lo,usedtogetat
#resultofproductorquotient
move$t2,$t3#$t2=$t3
PartV程序控制指令:
ControlInstructions
1.分支指令(Branches)
条件分支的比较机制已经内建在指令中
btarget#unconditionalbranchtoprogramlabeltarget
beq$t0,$t1,target#branchtotargetif$t0=$t1
blt$t0,$t1,target#branchtotargetif$t0<$t1
ble$t0,$t1,target#branchtotargetif$t0<=$t1
bgt$t0,$t1,target#branchtotargetif$t0>$t1
bge$t0,$t1,target#branchtotargetif$t0>=$t1
bne$t0,$t1,target#branchtotargetif$t0<>$t1
beqz$t0,lab#Branchtolabif$t0=0.
bnez$t0,lab#Branchtolabif$t0!
=0.
bgez$t0,lab#Branchtolabif$t0>=0.
bgtz$t0,lab#Branchtolabif$t0>0.
blez$t0,lab#Branchtolabif$t0<=0.
bltz$t0,lab#Branchtolabif$t0<0.
bgezal$t0,lab#If$t0>=0,thenputtheaddressofthenext
#instructioninto$raandbranchtolab.
bgtzal$t0,lab#If$t0>0,thenputtheaddressofthenext
#instructioninto$raandbranchtolab.
bltzal$t0,lab#If$t0<0,thenputtheaddressofthenext
#instructioninto$raandbranchtolab.
2.跳转指令(Jumps)
jtarget#unconditionaljumptoprogramlabeltarget
jr$t3#jumptoaddresscontainedin$t3("jumpregister")
3.子程序调用指令
子程序调用指令的实质是跳转并链接(JumpandLink),它把当前程序计数器的值保留到$ra中,以备跳回):
跳转到子程序:
jalsub_label#"jumpandlink",preservepcto$ra
sub_label为子程序的标签,如LOOP,SUB_ROUTINE
从子程序返回:
jr$ra#"jumpregister"jumpasthevalueof$ra
返回到$ra中储存的的返回地址对应的位置,$ra中的返回地址由jal指令保存。
注意,返回地址存放在$ra寄存器中。
如果子程序调用了下一级子程序,或者是递归调用,此时需要将返回地址保存在堆栈中,因为每执行一次jal指令就会覆盖$ra中的返回地址。
PartVI:
系统调用和I/O操作(SPIM仿真)
系统调用是指调用操作系统的特定子程序。
系统调用用来在仿真器的窗口中打印或者读入字符串string,并可显示程序是否结束。
用syscall指令进行对系统子程序的调用。
本操作首先支持$v0and$a0-$a1中的相对值
调用以后的返回值(如果存在)会保存在$v0中。
表二:
系统调用的功能:
Service
Codein$v0
Arguments
Results
print_int
1
print_float
2
print_double
3
print_string
4
read_int
5
integerreturnedin$v0
read_float
6
floatreturnedin$v0
read_double
7
doublereturnedin$v0
read_string
8
$a0=memoryaddressofstringinputbuffer
$a1=lengthofstringbuffer(n)
sbrk
9
$a0=amount
addressin$v0
exit
10
Theprint_stringserviceexpectstheaddresstostartanull-terminatedcharacterstring.Thedirective.asciizcreatesanull-terminatedcharacterstring.
打印字符串的功能认为起始地址为一个空终止符串。
声明字符串使用的.asciiz指示符会建立一个空终止符串。
Theread_int,read_floatandread_doubleservicesreadanentirelineofinputuptoandincludingthenewlinecharacter.
读入整形,读入浮点型和读入双精度的功能会读取一整行,包含换行符。
Theread_stringservicehasthesamesemanticesastheUNIXlibraryroutinefgets.
Itreadsupton-1charactersintoabufferandterminatesthestringwithanullcharacter.
Iffewerthann-1charactersareinthecurrentline,itreadsuptoandincludingthenewlineandterminatesthestringwithanullcharacter.
读入字符串的功能和UNIX库中fgets函数的语法相同。
他会读入n-1个字符到缓存,然后以空字符结尾。
如果少于n-1的字符,它会读到结尾并包含换行符,并以空字符结尾。
Thesbrkservicereturnstheaddresstoablockofmemorycontainingnadditionalbytes.Thiswouldbeusedfordynamicmemoryallocation.
sbrk功能返回一个包含有n个附加字节的存储区的地址,这回被用于动态内存分配。
exit功能用于停止程序运行。
e.g.Printoutintegervaluecontainedinregister$t2
例:
打印在$t2中的整数的值
li$v0,1#loadappropriatesystemcall
#codeintoregister$v0;
#codeforprintingintegeris1
move$a0,$t2#moveintegertobeprinted
#into$a0:
$a0=$t2
syscall#calloperatingsystemto
#performoperation
#e.g.Readintegervalue,storeinRAMlocationwithlabel
#int_value(presumablydeclaredindatasection)
l
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- MIPS 体系结构和汇编语言快速入门 体系结构 汇编语言 快速 入门