您的位置:首页 > 其它

MIPS 体系结构汇编语言快速入门(翻译)

2013-05-27 22:22 302 查看
MIPS 体系结构和汇编语言快速入门(翻译)

译者:Sonic Fu, Northeastern University, Boston, USA

译者按:学习笔记,抛砖引玉!网上有一个版本,不全,这个作为补充。

英文原版: http://logos.cs.uic.edu/366/notes/mips quick tutorial.htm#IOSystemCalls

本文分3部分: 0、引子, 1、寄存器介绍 2、I/O介绍

引子:数据类型和文法

数据类型: 字节,byte占用( 8bit ), halfword占2 byte= 16bit), word占用(4byte = 32bit)

一个字符需要一个Byte的空间;

一个整数需要1个Word(4 Byte)的空间;

MIPS结构的每条指令长度都是32bit

寄存器

MIPS体系架构有32个通用寄存器。在汇编程序中,可以用编号 $0 到 $31来表示;

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

有两个特殊的寄存器 Lo, Hi, 用来保存乘法/除法的运算结果;此2寄存器不能直接寻址,只能用特殊

的指令:mfhi和mflo来aceess其中的内容。

(含义:mfhi = move from Hi, mflo = Move from Low.)

堆栈(Stack)的增长方向是: 从内存的高地址方向, 向低地址方向;

表格1:寄存器的编号名称及分类









编号 寄存器名 寄存器描述

0 Zero 第0号寄存器,其值始终为0

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

2 ~ 3 $v0 ~ $v1 (values)保存表达式或函数返回的结果

4-7 $a0 - $a3 (arguments) 作为函数的前四个入参。在子函数调用的过程中不会被保留。

8-15 $t0 - $t7 (temporaries) Caller saved if needed. Subroutines can use without saving.

供汇编程序使用的临时寄存器。在子函数调用的过程中不会被保留。

16-23 $s0 - $s7 (saved values) - Callee saved.

A subroutine using one of these must save original and restore it before

exiting. 在子函数调用的过程中会被保留。

24-25 $t8 - $t9 (temporaries) Caller saved if needed. Subroutines can use without saving.

供汇编程序使用的临时寄存器。在子函数调用的过程中不会被保留。这是对 $t0 -

$t7的补充。

26-27 $k0 - $k1 保留,仅供中断(interrupt/trap)处理函数使用.

28 $gp global pointer. 全局指针。Points to the middle of the 64K block of memory in the

static data segment.指向固态数据块内存的64K的块的中间。

29 $sp stack pointer 堆栈指针, 指向堆栈的栈顶。

30 $s8/$fp saved value / frame pointer保存的值/帧指针

Preserved across procedure calls其值在函数调用的过程中会被保留

31 $ra return address返回地址

汇编程序结构框架

汇编源程序代码本质上是文本文件。由数据声明、代码段 两部分组成。程序文件应该以.s结尾,以在Spim软件中进行模拟。

数据声明部分

在源代码中,数据声明部分以 .data开始。声明了在代码中使用的变量的名字。同时,也在主存(RAM)中创建了对应的空间。

程序代码部分

在源代码中,程序代码部分以 .text开始。这部分包含了由指令构成的程序功能代码。

代码以main: 函数开始。main的结束点应该调用exit system call,参见后文有关system call 的介绍。

程序的注释

使用#符号进行注释。每行以#引导的部分都被视作注释。

一个MIPS汇编程序框架:

# Comment giving name of program and description of function

# Template.s

# Bare-bones outline of MIPS assembly language program

.data # variable declarations follow this line

# ...

.text # instructions follow this line

main: # indicates start of code (first instruction to execute)

# ...

# End of program, leave a blank line afterwards to make SPIM happy

开始编写MIPS汇编程序:

Content:

数据的声明

程序代码的编写

Part I: 数据的装载和保存(Load/Store 指令)

Part II: 寻址 :只能用load/store 相关指令来实现寻址操作

Part III: 算术相关的指令:Arithmetic Instructions

数据的声明:

格式:

name: storage_type value(s)

创建一个以name为变量名称,values通常为初始值,storage_type代表存储类型。

注意:变量名后要跟一个:冒号

#example:

#-------------------------------------------------------------------------------------

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 it.

string1 .asciiz "Print this.n" #declare a string

#-------------------------------------------------------------------------------------

程序代码的编写:

Part I:数据的装载和保存(Load/Store 指令)

主存(RAM)的存取access只能用load / store 指令来完成。

所有其他的指令都使用的是寄存器作为操作数。

i. load指令:

lw register_destination, RAM_source

# copy word (4 bytes) at

# source_RAM location

# to destination register.

# load word -> lw

lb register_destination, RAM_source

# copy byte at source RAM

# location to low-order byte of

# destination register,

# and sign -e.g. tend to

# higher-order bytes

# load byte -> lb

li register_destination, value

#load immediate value into

#destination register

#load immediate --> li

ii. store指令:

sw register_source, RAM_destination

#store word in source register

# into RAM destination

sb register_source, RAM_destination

#store byte (low-order) in

#source register into RAM

#destination

举个例子:

#-------------------------------------------------------------------------------------

.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

done

#-------------------------------------------------------------------------------------

Part II:寻址 :(只能用load/store 相关指令来实现寻址操作)

装载地址:load address:

la $t0, var1

把var1在主存(RAM)中的地址拷贝到寄存器t0中。var1也可以是程序中定义的一个子程序标签的地

址。

间接寻址:indirect addressing:

lw $t2, ($t0)

主存中有一个字的地址存在t0中,按这个地址找到那个字,把字拷贝到寄存器t2中。

sw $t2, ($t0)

把t2中的字存入t0中的地址指向的主存位置。

基线寻址/索引寻址:based or indexed addressing:

lw $t2, 4($t0)

把t0中地址+4所得的地址所对应的主存中的字载入寄存器t2中,4为包含在t0中的地址的偏移量。

sw $t2, -12($t0)

store word in register $t2 into RAM at address ($t0 - 12),negative offsets are fine

Note: based addressing is especially useful for:

arrays; access elements as offset from base address

stacks; easy to access elements at offset from stack pointer or frame pointer

此次是负的偏移量。

注意:基线寻址在一下场合特别有用:

1、数组:从基址出发寻找数组元素,通过使用偏移量。

2、堆栈:利用从堆栈指针到框架指针之间的偏移量来读写元素。

举个例子:

#-------------------------------------------------------------------------------------

#example

.data

array1: .space 12 # declare 12 bytes of storage

# to hold array of 3 integers

.text

__start:

la $t0, array1 # load base address of array

# into register $t0

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

sw $t1, ($t0) # first array element set to 5;

# indirect addressing

li $t1, 13 # $t1 = 13

sw $t1, 4($t0) # second array element set to 13

li $t1, -7 # $t1 = -7

sw $t1, 8($t0) # third array element set to -7

done

#-------------------------------------------------------------------------------------

Part III 算术相关的指令:Arithmetic Instructions

算数运算指令的所有操作数都是寄存器,不能直接使用RAM地址或间接寻址。

操作数的大小都为 Word (4-Byte)

add $t0,$t1,$t2 # $t0 = $t1 + $t2; add as signed

# (2's complement) integers

sub $t2,$t3,$t4 # $t2 = $t3 Ð $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

# ----------------------------------(To becontinued)---------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: