码迷,mamicode.com
首页 > 其他好文 > 详细

MIPC Intro

时间:2015-09-14 20:51:32      阅读:226      评论:0      收藏:0      [点我收藏+]

标签:

MIPS Reference Sheet

 

MIPS 是一种汇编语言

汇编语言不像 C 、Java, 其没有 variables,它的 operands 只有 registers

MIPS 一共有 32 个 registers (每个 register 都是 32 bits)

先介绍几个 register 

$16 - $ 23 一般命名为 $s0 - $s7
$8 - $15 一般命名为 $t0 - $t7

 

MIPS 加减操作

add $s0, $1, $s2   # MIPS
a = b + c          # C

sub $s3, $s4, $s5  # MIPS
d = e - f          # C

 

 

由于 一条指令的操作数有限, 一条C语句可能会分成好几条 MIPS 语句

a = b + c + d - e  # C

add $t0, $s1, $s2 # temp = b + c
add $t0, $t0, $s3 # temp = temp + d
sub $s0, $t0, $s4 # a = temp - e

 

由于常数经常出现, 所有常数可以直接表示(叫做 Immediate)

addi $s0, $s1, 10;  # 注意为 addi
a = b + 10;

 

 

由于 0 的使用更加频繁(比如 a = b, 其实就是 a = b + 0), 所以有一个 register 特别的被设定为 0

add $s0, $s1, $zero

 

在 MIPS 中, 有符号数运算(add, addi, sub)会检测是否溢出,而无符号数运算(addu, addiu, subu)则不会检测

 

 

内存操作

从内存读取数据到寄存器

int A[100];
g = h + A[3];

lw $t0, 12($s3)   
add $1, $2, $t0

 

将寄存器数据写入内存

int A[100];
A[10] = h + A[3];

lw $to, 12($s3);   # temp reg $t0 gets A[3]
add $t0, $s2, $t0;  # temp reg $t0 gets h + A[3]
sw $t0, 40($s3);   # send data in reg to A[10] 

 

Note: $s3 为 base register(pointer); 12, 40 是 byte 的偏移量

$s3+12, $s3+40 必须是4的整数倍(因为是以 word(总线长度) 为单位读写内存的)

ps: 还有读取一个 byte 的指令(lb, sb), 格式类似

 

 

MIPS 逻辑运算指令

and 、or 、not 、sll 、srl ... (自己查表)

 

Instructions for Making Decisions

条件跳转

if - statement: 指令为:

beq reg1, reg2, L1  

如果 reg1 的值与 reg2 的值相等, 就跳转到 Label 为 L1的语句, 否则就执行下一条语句

bne 与 beq 类似, 不过条件是 reg1 的值与 reg2 的值不等

无条件跳转

j L1

e.g

if (i==j)
    f = g + h;
else 
    f = g - h;

bne $s3, $4, Else
add $s0, $s1, $s2
j Exit
Else: sub $s0, $s1, $s2
Exit:

 

还有一个 slt 指令

slt reg1, reg2, reg3

 

相当于如果 reg2 < reg3, 则reg1 = 1, 否则 reg1 = 0

这条指令配合前面的 beq、bne 指令, 就可以实现小于时跳转

if(g<h)
    Less;

slt $t0, $s0, $s1
bne $t0, $zero, Less 

 

对应的,针对无符号数有 sltu, Immediates 有 slti

 

MIPS Function

convention:

$a0 - $a3 : 参数的寄存器

$v0-$v1 : 返回值的寄存器

$ra : 返回调用前下一条指令的地址

 

要有这样一个概念, 写的一条条指令存储在内存的 text 段(每条指令占4个byte)

sum(a, b);  // 调用 sum 函数
...
int sum(int x, int y) {   // 定义在他处, 所以调用指令和定义指令的地址往往不连续
    return x+y;
}


# 前面的数字是假设的内存地址
1000 add $a0, $s0, $zero
1004 add $a1, $s1, $zero
1008 addi $ra, $zero, 1016  # 因为调用结束后应该执行1016处的指令
1002 j sum  # 跳转到 sum
1016 ...
...
2000 sum: add $v0, $a0, $a1
2004 jr $ra # 返回到 ra 指令处

 现实中很难知道那条指令在内存何处, 所以上面 addi $ra, $zero, 1016 不现实, MIPS 有 一条 jump and link 指令 (jal)

before:
1008 addi $ra, $zero, 1016
1012 j sum;

After:
1008 jal sum # 相当于 $ra=1012, 跳转到sum

 

 还有一个问题, 函数调用时要设定一些寄存器的值为参数值, 如果之前那些寄存器已经有值且有意义时,该怎么办? A:将这些值压入stack,调用结束后再弹出 (MIPS中 $sp 寄存器 表示栈指针)

int sumSquare(intx, int y) {
    return mult(x, x) + y;        
}

sumSquare:
    addi $sp, $sp, -8;  // 改变栈指针
    sw $ra, 4($sp)    // 将 返回地址压入栈
    sw $al, 0($sp)    // 将 y 压入栈
    add $al, a0, $zero 
    jal mult
    lw $al, 0($sp)  # 取出 y
    add $v0, $v0, $al
    lw $ra, 4($sp)  # 取出返回地址
    addi $sp, $sp, 8  # 恢复栈指针
    jr $ra
...
mult : ...

 

MIPC Intro

标签:

原文地址:http://www.cnblogs.com/whuyt/p/4808053.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!