MIPS 体系结构和汇编语言快速入门.docx

上传人:b****5 文档编号:7161544 上传时间:2023-01-21 格式:DOCX 页数:13 大小:49.55KB
下载 相关 举报
MIPS 体系结构和汇编语言快速入门.docx_第1页
第1页 / 共13页
MIPS 体系结构和汇编语言快速入门.docx_第2页
第2页 / 共13页
MIPS 体系结构和汇编语言快速入门.docx_第3页
第3页 / 共13页
MIPS 体系结构和汇编语言快速入门.docx_第4页
第4页 / 共13页
MIPS 体系结构和汇编语言快速入门.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

MIPS 体系结构和汇编语言快速入门.docx

《MIPS 体系结构和汇编语言快速入门.docx》由会员分享,可在线阅读,更多相关《MIPS 体系结构和汇编语言快速入门.docx(13页珍藏版)》请在冰豆网上搜索。

MIPS 体系结构和汇编语言快速入门.docx

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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1