MIPS学习笔记(1)

文章目录

  • MIPS学习笔记(1)
    • 背景
    • 指令与立即数
    • 数据传输指令
    • MIPS基本决策机制
    • 乘除法指令
    • 算术溢出
    • 位运算指令
    • 移位指令
    • 不等式
    • 伪指令
    • 实现函数
    • 函数调用约定
    • 存储型程序概念
    • R型指令
    • I型指令
    • B类指令
    • J型指令
    • 汇编实战
    • 反汇编实战

背景

CISC(Complex Instruction Set Computing)

RISC(Reduced Instruction Set Computing)

MIPS是RISC的典型代表

RISC基本策略:

  1. 指令字长:所有指令长度都是1个字(32位)
  2. 寻址模式:基址+偏移量
  3. 访存:load与store

主流ISA:

  1. Intel 80x86 —— PC、服务器
  2. ARM(Advanced RISC Machine)—— 手机、平板
  3. PowerPC —— 航空电子设备、网络设备……

寄存器:

  1. 被内置于CPU中
  2. 速度极快(<1ns)
  3. 数量少

指令与立即数

MIPS内的寄存器:

  1. 数量为32个(编号为0~31)
  2. 宽度为32位
  3. 无正负
  4. 表示方法:$x(0<=x<=31)

MIPS指令的一般性语法格式: op dst, src1, src2

​ op:指令的基本功能

​ dst:保存结果的寄存器

​ src1:第一个操作数; src2:第二个操作数

加法操作:add dst, src1, src2

减法操作:sub dst, src1, src2

每条指令只有一种操作,每行一个指令

注释语句以“#”开始

0号寄存器($0 / $zero):0的专属寄存器,其值恒为零

立即数:指令中出现的常量数值

含有立即数的指令:op dst, src, imm

​ op+i表示对立即数的操作(eg:addi $s1, $s2, 5)

数据传输指令

由于MIPS只能对寄存器与立即数进行运算,因此必须有特定的数据传输指令实现主存单元与寄存器的数据交换

​ LOAD类:主存单元→寄存器

​ STORE类:寄存器→主存单元

数据传输的语法格式:op reg, off(base)

​ reg:操作的寄存器

​ base:存储基址的寄存器(因为是地址,base的值为无符号数)

​ off:偏移量(单位为字节,可正可负)—— 偏移量必须为4的倍数

读写的存储单元实际地址为:base+off

加载字:lw reg, off(base)

存储字:sw reg, off(base)

加载字节:lb reg, off(base) lbu为无符号扩展

存储字节:sb reg, off(base)

​ 注意:读入字节最高位视为符号位,向高24位扩展

加载半字:lh reg, off(base) lhu为无符号扩展

存储半字:sh reg, off(base)

如果变量比寄存器多,则把常用的变量保存在寄存器中,其他不常用的保存在存储器中

大印第安:最高有效字节在字内的最低地址

小印第安:最高有效字节在字内的最高地址

MIPS基本决策机制

MIPS没有语句块的概念(不同于C语言的if-else、while等)

每条指令都对应一个word地址,使用标号标记其后的指令的地址 → **“标号名” + ‘:’ **

通过跳转机制调到标号处,实现转移

相等时转移(Branch If Equal):beq reg1, reg2, label

不等时转移(Branch If Not Equal):bne reg1, reg2, label

无条件转移(Jump):j label

C语言中for、while、do-while都可以改为MIPS

乘除法指令

乘除法指令结算结果不是直接写入32个通用寄存器中,而是保存在两个特殊寄存器HI与LO

2条专用指令读写HI/LO:

​ move from high:mfhi dst

​ move from low:mflo dst

乘法操作:mult src1, src2

​ LO保存结果的低32位,HI保存结果的高32位

除法操作:div src1, src2

​ LO保存商,HI保存余数

算术溢出

当计算结果的位数超出计算机硬件的实际可存储位数时,即为溢出

MIPS会检测溢出(溢出时产生错误),但是有unsigned关键字的算术指令忽略溢出

overflow detection no overflow detection
add dst, src1, src2 addu dst, src1, src2
addi dst, src1, src2 addiu dst, src1, src2
sub dst, src1, src2 subu dst, src1, src2

位运算指令

instruction C MIPS
and a=b&c and $s1, $s2, $s3
and immediate a=b&0x1 andi $s1, $s2, $s3
or a=b|c or $s1, $s2, $s3
or immediate a=b|0x5 ori $s1, $s2, $s3
not or a=~(b|c) nor $s1, $s2, $s3
exclusive or a=b^c xor $s1, $s2, $s3
exclusive or immediate a=b^0xF xori $s1, $s2, $s3

移位指令

移位的不同种类:

  1. 方向:左移&右移

  2. 性质:逻辑移位&算术移位

    左移位低位补零;右移位:逻辑移位补0,算术移位补符号位

  3. 移位量:对于32位寄存器,移动位数合理最大取值为31,即0x1F

    表示方式:5位的立即数&某寄存器的值(低5位有意义)

指令 功能 示例
sll 逻辑左移 sll $dst, $src, imm/$x
srl 逻辑右移 srl $dst, $src, imm/$x
sra 算数右移 sra $dst, $src, imm/$x
sllv 逻辑可变左移 sllv $dst, $src, imm/$x
srlv 逻辑可变右移 srlv $dst, $src, imm/$x
srav 算数可变右移 srav $dst, $src, imm/$x

不等式

slt dst, src1, src2: Set on Less Than(如果src1<src2,dst写入1,否则写入0)

slt与bne、beq和$0组合可以实现所有的比较方式

slt的三种情况:

  1. sltu dst, src1, src2: 无符号数比较
  2. slti dst, src, imm: 与常量比较
  3. sltiu dst, src, imm:与无符号数常量比较
位扩展 溢出检测 符号数
Signed lb:扩展 add, addi, sub, mult, div: 检测 slt, slti: 符号数
Unsigned lbu:无扩展 addu, addiu, subu, multu, divu: 不检测 sltu, sltiu:无符号数

伪指令

MIPS定义了一组伪指令,从而使得程序更可读更易编写

注意:伪指令知识增加了可读性,最终要转换为实际指令

  1. move dst, src:把src赋值给dst
  2. la dst, label:(Load Address)加载特定标号对应的地址至dst
  3. li dst, imm:(Load Immediate)加载一个32位立即数至dst

出现的问题:将一条伪指令转换成真实指令时,可能需要多条真实指令,指令之间必须通过寄存器传递信息,若果任意 使用寄存器,则寄存器的内容可能被误写

解决方案:保留**$1 ($at)**作为汇编器的专用寄存器

TAL(True Assembly Language):真实指令,计算机能理解和执行

MAL(MIPS Assembly Language):提供给汇编程序员使用的指令(含伪指令)

实现函数

实现函数的六个步骤

  1. 调用者把参数放置在某个地方以便函数访问
  2. 调用者转移控制给被调用的函数
  3. 函数获取局部变量对应的空间
  4. 函数执行具体功能
  5. 函数把返回值放置在某个地方,然后恢复使用的资源
  6. 返回控制给调用者

寄存器分配:

  1. **$a0$a3**:(编号23)4个传递参数的寄存器
  2. **$v0$v1**:(编号47)2个传递返回值的寄存器
  3. $ra:(编号31)返回地址寄存器,保留着调用者的地址

函数调用指令:

  1. jal label:(Jump and Link)把jal的下一条指令地址保存在$ra,然后跳转到 label*(用于调用函数)*
  2. jr src:(Jump Register)无条件跳转保存在src的地址(通常指$ra)(用于从函数返回)

PC(Program Counter)是一个特殊寄存器,用于保存当前正在执行的指令的地址(对程序员不可见,但是可以通过jal访问)

注:$ra中保存的地址为PC+4而不是PC,否则从函数返回时再次返回jal

保存和恢复寄存器:

  1. 原因:如果被调用函数继续调用函数,$ra被覆盖,且由于寄存器数量少不可能只用寄存器编写实用程序
  2. 寄存器的保存:栈

$sp:栈指针寄存器,指针指向栈底

栈帧:函数为获得保存寄存器而将$sp向0方向调整的空间(栈帧容量=要保存的寄存器数量×4)

​ eg: addi $sp, $sp, -8

注意:栈增长方向为向0增长,堆增长方向为背0增长

局部变量和数组:

  1. 由于寄存器只有32个,因此编译器绝大多数下不可能把函数需要的所有局部变量都分配在寄存器
  2. 局部变量存放在函数自己的栈帧中(函数返回时随着$sp的回调,局部变量随之释放)
  3. 其他局部变量(数组、结构等)同样存储在栈帧中

函数调用约定

寄存器的保护分析

$s0~$s7:程序员变量

  1. 所有函数都要使用程序员变量,程序员变量的生命周期与函数生命周期相同,即进入函数有效,退出函数无效
  2. 保护前提:用哪些,保护哪些
  3. 保护动作:刚进入函数时保存,退出函数前恢复

$ra:函数返回地址

  1. 保护前提:如果继续调用了子函数,则必须保护
  2. 保护动作:刚进入函数时保存,退出函数前恢复

$t0~$t9:临时变量(前提:MIPS约定其服务于表达式计算)

  1. 无需保护的情况:表达式中不调用子函数,故不存在被子函数修改的可能

    需要保护的情况:表达式中调用子函数,故存在被子函数修改的可能

  2. 保护前提:如果其值在子函数调用前后必须保持一致

  3. 保护动作:调用子函数前保存,调用子函数后恢复

$a0~$a3, $v0~$v1:参数,返回值

  1. $a0~$a3:传递给了子函数,故子函数可自由使用

    $v0~$v1:因为子函数会设置返回值,故子函数可自由使用

  2. 保护前提:如果其值在子函数调用前后必须保持一致

  3. 保护动作:调用子函数前保存,调用子函数后恢复

$at:汇编器使用,无需保护

$sp:栈切换(通常属于操作系统范畴)时才需要保护

$fp、$gp:生成复杂存储布局时使用(属于便于范畴)

小结

序号 名称 MIPS汇编约定的用途 分类 保护的前提条件 何时保护与恢复
16~23 $s0~$s7 程序员变量 强保护 如果需要使用 进入函数时保存,退出函数前恢复
31 $ra 函数返回地址 强保护 如果调用子函数 进入函数时保存,退出函数前恢复
———— ———— —————— ———— —————— ————————————
2~3 $v0~$v1 函数返回值 弱保护 如果要求其值在子函数调用前后必须保持一致 调用子函数前保存,调用子函数后恢复
4~7 $a0~$a3 函数参数 弱保护 如果要求其值在子函数调用前后必须保持一致 调用子函数前保存,调用子函数后恢复
8~15,24~25 $t0~$t9 临时变量 弱保护 如果要求其值在子函数调用前后必须保持一致 调用子函数前保存,调用子函数后恢复

Preserved Register:保护寄存器($s0~$s7、$ra)

Non-preserved Register:非保护寄存器($t0~$t9、$a0~$a3、$v0~$v1)

存储型程序概念

存储型程序:

  1. 指令以二进制方式编码
  2. 程序存储在存储器中,可以从存储器中读取程序也可以写入程序(存储方式与数据存储完全相同)
  3. 简化了计算机系统的软件/硬件设计
  4. 存储器技术既可以存储数据,也可以存储程序
  5. 由于存储在存储器单元中,因此指令和数据都有地址

二进制兼容:

  1. 程序是以二进制形式发布的(指令集与程序之间是强相关)
  2. 新机器不仅能运行基于新指令编译产生的新程序,同样也最好能运行老程序
  3. 上述特性被称为向后兼容(Backward Compatible)

把指令当做数看待:

  1. 数据以字为单位,因此MIPS的所有指令的二进制编码宽度均为32位
  2. 指令的32位被划分为若干域(域:占据若干位置,代表特定含义),指令的各个域分别表示指令的不同信息

MIPS的3类指令格式:

  1. I型指令:指令中包含立即数

    lw / sw 的偏移是立即数;beq/bne同样包含有偏移

    srl等移位指令也有4位立即数(移位位数),但不属于I型指令

  2. J型指令:j和jal(jr不是J型指令)

  3. R型指令:所有其他指令

R型指令

指令中包含6个域:

opcode rs rt rd shamt funct
316 5 5 5 5 60

每个域都被视为无符号整数:

  1. 5位域表示范围:0~31
  2. 6位域表示范围:0~63
含义 说明
opcode(6) 指令操作 R型指令的opcode固定为0b000000
funct(6) 与opcode组合,精确定义指令的具体操作 主要服务于R型指令(由于opcode为0,因此根据6位funct,R型指令最多有64个)
rs(5) 指定1st操作数(source寄存器)
rt(5) 指定2nd操作数(target寄存器)
rd(5) 指定结果回写的寄存器(destination寄存器) eg: add rd, rs, rt
shamt(5) 移位指令中的移位位数 移位位数大于31没有意义;除了移位指令,该域恒为0

NOP(0x00000000):即”sll $0, $0, 0“,主要用于解决流水线冲突

I型指令

指令包括6个域:

opcode rs rt immediate
316 5 5 160

具体含义:

含义 说明
opcode(6) 指令操作 I型指令的opcode为非零编码,可有264条指令
rs(5) 指定1st操作数(source寄存器)
rt(5) 指定2nd操作数(target寄存器)
immediate(16) 无符号或有符号数 1. 无符号数:位运算指令(and/or/nor……)、小于置位指令(slti……) 2. 有符号:分支指令(beq/bne……)、访存指令(lw/sw……)

注意

  1. zero_ext():运算前需要进行无符号扩展
  2. sign_ext():运算前需要进行符号扩展

如何计算32位立即数:(addi/ slti/ andi/ ori/……)

  1. 解决方案:不改变指令格式,而是增加一条指令
  2. 增加的指令:lui reg, imm;(Load Upper Immediate),reg高16位写入imm,低16位写入0

通过增加lui,MIPS可以用16位立即数处理任意大小的数据

B类指令

B类指令:分支指令(beq与bne),主要用于构造if-else、while、for,同样具有:opcode,rs,rt,immediate结构。比较rs和rt,根据比较结果决定能够是否转移。

注意:并非所有的B类指令的rt域都是寄存器,需要指定要转移的地址。转移的范围通常很小(<50指令),函数调用和无条件跳转用J型指令

用immediate表示地址:

  • 由于指令存储在主存中,而主存单元可以由基地址+偏移的方式定位
  • B类指令的基地址就是PC

PC相对寻址:PC为基地址,immediate为偏移(二进制补码)

下一条指令的PC值计算方法

  • 比较结果为真:PC = PC + 4
  • 比较结果为假:PC =(PC + 4)+(immediate * 4)

immediate为16位符号数,范围为±215,意味着转移的指令数最大为215条。按照1行C代码对应10条指令,则可转移约3000行C代码

J型指令

J型指令只定义了2个域:

opcode(31~26) instr_index(25~0)
6 26

要点:

  • opcode的位置及位数与R型、I型指令保持一致
  • 其他域合并起来构造大的地址范围

PC的高4位来自当前指令的高4位,J型指令的转移范围是256MB(只有jr指令可以跳转到4GB内任意地址

汇编实战

每条指令的汇编基本步骤:

  1. 标识出指令类型
  2. 标识出正确的域
  3. 用10进制表示各个域的值
  4. 把各个域的10进制转换为2进制
  5. 用16进制表示整个机器码

反汇编实战

反汇编是汇编的逆过程,即将指令二进制代码转换为汇编代码

反汇编基本步骤:

  1. 用2进制表示指令
  2. 根据opcode标识出指令类型
  3. 用10进制标识出各个域的值
  4. 用标识符表示各个域,并添加相应的表号
  5. 用汇编格式数学代码
  6. 将汇编代码翻译为C

MIPS学习笔记(1)相关推荐

  1. MIPS架构学习笔记

    MIPS架构学习笔记 来源: ChinaUnix博客 日期: 2007.03.13 23:18 (共有条评论) 我要评论 MIPS架构学习笔记                              ...

  2. MIPS汇编语言学习笔记23:if 语句分支指令

    C语言 #include<stdio.h> int main() {int i = 3;if (i < 5){printf("yes!\n");}else{pri ...

  3. MIPS体系结构学习笔记

    MIPS体系结构学习笔记 第一章 概述 第二章 MIPS的体系结构 相关寄存器的时序 32个通用寄存器 通用寄存器的命名 32个浮点寄存器 基本地址空间 第三章 协处理器0(cp0):MIPS处理器控 ...

  4. MIPS汇编语言学习笔记07:打印双精度浮点数

    课程原视频: https://www.bilibili.com/video/BV19J411y7pA?p=7 程序功能: 设定两个双精度浮点型数据,将其相加后打印输出. 代码: .datamyDoub ...

  5. MIPS汇编语言学习笔记11:整数减法 (mult方法)

    任务:整数相乘,并输出打印. 代码: .dataintA: .word 5intB: .word 2 .textli $v0, 1lw $a1, intAlw $a2, intBmult $a1, $ ...

  6. 评价微型计算机总线的性能指标,计算机组成原理学习笔记(3):总线

    文章目录 课程笔记导览 附录:英语解释 第三章 总线 3.1 总线的基本概念 使用总线的原因: 总线的定义 总线上信息的传送 总线结构举例 单总线结构 面向CPU的双总线结构 以存储器为中心的双总线结 ...

  7. 计算机组成原理学习笔记一

    计算机组成原理学习笔记一 计算机发展历程 一.计算机硬件发展 (1)计算机的四代变化 (2)计算机元件更新换代 二.计算机软件发展 三.计算机的分类 计算机系统层次结构 一.计算机系统的组成 二.计算 ...

  8. 嵌入式之uboot源码分析-启动第一阶段学习笔记

    注: 以下的内容来自朱老师物联网大讲堂uboot部分课件 Uboot启动第一阶段start.S执行步骤 1.头文件包含 <config.h>(x210的各种宏定义) <version ...

  9. 从零开始学STM32(学习笔记——第三天)

    CSDN话题挑战赛第2期 参赛话题:学习笔记 参考文章: [教学文章]STM32内部重要功能全记录 [教学文章]STM32内部核心功能大揭秘 [教学文章]STM32内部重要功能全记录 框架:STM32 ...

  10. Golang底层原理学习笔记(一)

    LCY~~Golang底层原理学习笔记 1 源码调试 go源代码地址:GitHub - golang/go: The Go programming language 1.1 源码编译 现在的go语言大 ...

最新文章

  1. Oracle版本对应得使用的jar包
  2. ajax插件库,03.vue-ajax、vue UI 组件库
  3. 多边形填充算法-有序边表法(扫描线算法)
  4. [转]C++模板学习
  5. linux中设置环境变量PATH的方法(转)
  6. 隐藏GridControl的“Drag a column header here to group by that column”
  7. 使用linux 的wget下载国外的域名的地址,下载不了,
  8. PAT甲级1012 (结构体,排序)
  9. 论文 | 研究方法 —— 结构方程
  10. 计算机怎么删除表格,win10系统下Word2010如何删除表格和表格中内容
  11. http请求过程:一,DNS域名解析系统详解
  12. 英语心理测试脸型软件,心理测试:脸型分析自己
  13. 亚麻/苹果/脸书/谷歌/微软面试图鉴
  14. build-essential unmet dependencies 有未满足依赖 解决办法
  15. 2007山东公务员面试真题汇总
  16. opencv Fast特征提取函数
  17. 112、Flutter实现图片放大缩小的动画小
  18. 蓝帽杯web----杰克与肉丝
  19. python14 Prompting and Passing
  20. 【Python网络蜘蛛】:基础 - 爬虫的基本原理

热门文章

  1. 为了对电脑进行保护,已经阻止此应用
  2. matlab中beta是什么软件,软件版本中的beta是什么意思?
  3. 电脑右下角音量键打不开,调不了音量大小的解决方法
  4. uni-app 使用蓝牙打印机ESC/POS指令基础方法
  5. 使用Excel批量生成sql,包括日期格式
  6. js实现首尾相连左右循环切换效果
  7. 数据集中趋势度量:众数、平均数、中位数、几何平均数
  8. 1-思科IOS设备管理
  9. 线粒体基因组常见缩写与术语
  10. eda交通灯控制器波形输入_用VHDL设计交通灯控制器