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

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:寄存器的编号名称及分类
MIPS 体系结构汇编语言快速入门(翻译)_第1张图片
MIPS 体系结构汇编语言快速入门(翻译)_第2张图片

编号 寄存器名 寄存器描述
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)---------------------------------------------------

你可能感兴趣的:(Communications)