MIPS汇编快速入门

标签: MIPS汇编 汇编语言 编程语言 快速入门 转载翻译
原文

MIPS汇编快速入门

数据类型

1.MIPS使用定长指令,所有指令都是32位长的
2.1字节=8位,半字长=2个字节(32位),1字长=4个字节
3.一个字符空间=1个字节
4.一个整形=一个字长=4个字节
5.单个字符用单引号
6.字符串用双引号

寄存器

  • MIPS下一共有32个通用寄存器
  • 在汇编中,寄存器标志以$开头
  • 寄存器表示可以有两种方式:
    1.直接使用该寄存器对应的编号,例如:从$0到$31
    2.使用对应的寄存器名称,例如 t1, t 1 , sp,详见下文
    对于乘法和除法分别有对应的两个寄存器 lo, l o , hi
  • 对于以上两者,不存在直接寻址,必须通过mfhi(“move from hi”)和mflo(“move from lo”)分别来进行访问对应的内容。
  • 栈的走向是从高地址向低地址

MIPS下各个寄存器编号及描述

寄存器编号寄存器名寄存器用途
0zero永远返回0
1$at汇编保留寄存器(不可用作其他用途)
2-3$v0-$v1(value的简写)存储表达式或者函数的返回值
4-7$a0-$a3(Argument简写)存储子程序的前4个参数,在子程序调用过程中释放
8-15$t0-$t7(temp简写)临时变量,同上调用时不保存
16-23$s0-$s7(Save or Static简写?)静态变量?调用时保存
24-25$t8-$t9(Temp简写)算是前面$0-$7的继续,属性同$t0-$t7
26-27$k0-$k1(break off简写?)中断函数返回值,不可做其他用途
28 gp|(GlobalPointer)64k( g p | ( G l o b a l P o i n t e r 简 写 ) 指 向 64 k ( 2^{16}$)大小的静态数据块的中间地址
29$sp(Stack Pointer简写)栈指针,指向栈顶
30$s8/$fp(Save / Frame Pointer)帧指针
31$ra返回地址,目测不可用作其他用途

程序结构

本质就是数据声明+普通文本+程序编码(文件后缀为.s或.asm)
数据声明在代码段之后(在之前也没什么问题)

数据声明

  • 数据段以.data为开始标志
  • 声明变量后,即在主存中分配空间

代码

  • 代码段以.text为开始标志
  • 其实就是各项指令操作
  • 程序入门为main:标志
  • 程序结束标志(见下文)

注释

同C系语言
基本模板

# 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
# 必须多给你一行,你才欢?

数据声明

声明的格式:

变量名:(冒号不可缺少) 数据类型 变量值

通常给变量赋一个初始值,对于.space,需要指明需要多少大小空间(bytes)

加载/保存 指令集

  • 如果要访问内存,只能够使用load/store指令
  • 其他的只能是寄存器操作

load

lw

lw register_destination, RAM_source
从内存中复制RAM_source的内容到对应的寄存器中(w意味word,即该数据大小为4个字节)

lb

lb register_destination, RAM_source
同上,lb为load byte

store

sw

sw register_source, RAM_destination
指将指定寄存器中的数据写入到特定的内存中

sb

sb register_source, RAM_destination
同lb

load immediate

li

li register_destination, value
顾名思义,加载立即数

立即与间接寻址

la (load address 直接给地址)

例如la $to,var1表示的是将var1中的内存地址塞入$to中

间接寻址

地址是寄存器的内容(也可以理解为指针)
lw $t2,($t0) load word at RAM address contained in $t0 into $t2
sw $t2,($t0) store word in register $t2 into RAM at address contained in $t0

加偏移量

lw $t2,4($t0) load word at RAM address ($t0+4) into register $t2,”4” gives offset from address in register $t0
sw $t2,-12($t0) store word in register $t2 into RAM at address ($t0 - 12),negative offsets are fine

算术指令集

  • 最多三个操作数
  • 操作数只能是寄存器,不允许出现地址
  • 所有指令统一是32位
  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
                         运算结果存储在hi,lo(hi高位数据, lo低位数据)
        div $t5,$t6        #  Lo = $t5 / $t6   (integer quotient)
                    #  Hi = $t5 mod $t6   (remainder)
                         商数存放在 lo, 余数存放在 hi
        mfhi    $t0		#  move quantity in special register Hi to $t0:   $t0 = Hi
                          不能直接获取 hi 或 lo中的值, 需要mfhi, mflo指令传值给寄存器
        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

控制流

分支(if else系列)

        b   target      #  unconditional branch to program label target
        beq $t0,$t1,target #  branch to target if  $t0 = $t1
        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

跳转(while,for,goto系列)

        j   target       #  unconditional jump to program label target
                           看到就跳, 不用考虑任何条件
        jr  $t3		#  jump to address contained in $t3 ("jump register")
                          类似相对寻址,跳到该寄存器给出的地址处

子程序调用

    jal sub_label   #  "jump and link"

将当前的程序计数器保存在$ra中,通过上面保存在$ra中的计数器返回到调用前
如果说调用的子程序中有调用了其他子程序,如此往复,则返回地址的标记就用栈来存储。

系统调用与输入/输出 (主要针对SPIM模拟器)

  • 使用syscall,以下指令应该是通用的。
  • 参数所使用的寄存器:$v0,$a0,$a1
  • 返回值使用: $v0
ServiceCode in $v0 对应功能的调用码Arguemnts 所需参数Results 返回值
打印一个整型$v0=1将要打印的整型赋值给$a0
打印一个浮点数$v0=2将要打印的浮点数赋值给$f12
打印双精度浮点数|v0=3将要打印的双精度浮点数赋值给$f12
打印字符串$v0=4将要打印的字符串的地址赋值给$a0
读取一个整型$v0=5将读取的整型赋值给$v0
读取浮点数$v0=6将读取的浮点数赋值给$v0
读取双精度浮点数$v0=7将读取的双精度浮点数赋值给$v0
读取字符串$v0=8将读取字符串地址赋值给$a0,将读取字符串的长度赋值给$a1
sbrk(应该同C中的sbrk()函数一样) 动态分配内存$v0=9$a0=amount 需要分配的空间大小,单位目测是字节将分配好的空间首地址给$a0
退出\v0=10退出

* 打印的字符串应该有一个终止符(’\0’),声明字符串为.asciiz类型即可。
* 对于读取整型,浮点数,双精度浮点数等数据操作,系统会读取一整行(以’\n’为结束)
* 读取字符串时,输入过长就截短,短了不补,最后会加上终止符
* The sbrk service returns the address to a block of memory containing n additional bytes. This would be used for dynamic memory allocation.

  • 52
    点赞
  • 283
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值