Assembly
ASM
汇编语言的特性
- 指令与该计算机architecture相匹配
- 不同architecture支持的运算不一定相同
- 所以一个汇编语言在其他不同的architecture上不适用
两种指令集
CISC
- 多而复杂的指令
- 需要复杂的硬件来支持复杂的指令 运行慢
- less work for the compiler
RISC
- 指令简单
- 硬件运行速度快
寄存器 Registers
- 固定数量(32 registers x0 - x31)
- 固定内存大小 (32 bits)
- 支持读写
- 访问速度快,能耗少
- 在CPU内
Registers and Memory
- tradeoff between cost and performance
- memory hierarchy
(总之就是越快越贵 需要快 但也要便宜 就综合一下)
速度快,但是数量有限,经研究发现32个比较合适
registers 是 datapath的一部分
RISCV Registers
32个Registers(x0-x31),寄存器还有其他名字
the Zero Register(x0)
x0(name为zero)永远存0的值,无法改变
RISCV Instructions (op dst,src1,src2)
Arithmetic Instructions
例如add s1,s2,s3
包含immediate(立即数)的算术语法语法:opi dst,src,imm
addi s1,s2,5
注: 没有subi指令,因为可以addi负数,这样减少指令数量
data transfer instruction: memop reg, off(bAddr)
reg:作为src或者dest的寄存器
bAddr:储存内存地址的寄存器
off:偏移量 为立即数
实际访问地址:(bAddr+off)
常用指令为load word(lw)和store word(sw)
Byte instructions
首先 RISCV为little endian,且支持sign extension
lb/sb仅使用reg的最低位
store byte指把reg的最低byte存进目标位置的地址中
store byte的时候,不改变目标地址byte以外的其他byte内容
load byte的时候,reg最低位为填充的byte,其余三位使用sign extension
类似还有half word instructions lh sh
Unsigned Instructions
只有 lhu lbu将数据load进reg的低位后,剩余高位用0填充(Zero padding)
不难知道没有lwu(无需padding)没有sbu,shu
Control Flow Instructions
Decision Making Instructions(using label)
- branch if equal(beq)
- branch if not equal(bne)
- jump(j)
- branch less than(blt)
- branch greater than or equal(bge)
注:有了bge和blt 就不用ble和bgt了,直接交换两个参数即可
loops
本质上还是conditional branch
Program Counter
记录当前正在执行的代码的地址
Instruction Address
指令被装载在Memory的code部分里,每条指令(label)都有地址,PC记录当前指令的地址
Shifting Instructions
shift指令主要分两种:
- Logical shift(zero padding)
- Arithmetic shift(sign extension)
其中只有shift right 保留符号位才有意义
用处:比如可以用lw sw加上shift指令实现lb sb
Other Instructions
Multiplication and Division
Bitwise Instructions
Compare Instructions
和8086不太一样,这里似乎没有flag register 所以还是建议用beq和bne(?)
Environment Call(ecall)
- 调用操作系统
- 操作系统根据寄存器a0的值执行操作(exit print等等)
More about ASM code
Pseudo Instructions
更加可读易懂的指令,在不同architecture翻译成不同的实际指令,主要利于programmer编程
例如
- mv
- Load Immediate(li)
- Load addr(la)(load the addr of a label)
- No Operation(nop)
C to RISCV
这里课上讲了个例子
RISCV functions
function执行过程
- 传参数
- 控制权交给函数
- 函数获得其需要的资源(acquire storage resources it needs)
- 函数执行任务
- 函数送出返回值,清除其他内容(“clean up”)
- 交还控制权
参数有关register
- a0-a7 用于传递函数参数
- a0-a1 函数返回值
如果还需要更过空间,需要使用栈上的空间 - sp 栈顶指针
函数的跳转
- ra register ;return addr register 函数调用结束,返回的指令地址
- jr reg 跳转到reg内保存的地址
- Link: jal reg label 跳转到label 把返回地址保存到reg(通常为ra)
事实上 j是伪指令 实际由jal实现
j label 实际是 jal x0 label (x0不接受任何值) - ret 函数返回函数 实际上是jalr x0,ra,0
保存变量
sp指针指向栈顶元素,且向下增长
\# store t0 to the Stack
addi sp,sp, -4
sw t0,0(sp)
需要清除栈上的变量,直接inc sp即可
Function call convention
介绍函数嵌套调用时的细节
函数嵌套调用,是否会override ra?
- caller and calle的概念
Saved Registers(Calle Saved)
这部分Registers的值在执行calle的前后不会改变
如果calle需要使用,则先把值存在Stack上,返回前再取出,存回寄存器中
- s0-s11(saved registers)
- sp
From caller’s perspective,s0-s11 and sp are totally unchanged
save的工作由calle执行
Volatile Registers(Caller Saved)
这部分寄存器可由calle随意改变,需要caller在调用calle之前先保存在Stack上
- t0-t6(Temporary Registers)
- a0-a7(return addr and arguments)
- ra
对于开始的疑问 在调用嵌套函数的时候,先开辟栈空间把ra a1存在栈上,执行完之后再pop出来恢复状态
Basic Structure of a Function
- the Prologue(保存需要用的寄存器)
- the Body(执行具体任务)
- the Epilogue(恢复改变的寄存器状态)
My Summary:caller在调用calle前后保存和恢复Volatile Registers,calle在函数头尾保存和恢复Saved Registers
Instructions Format
这部分介绍汇编语言指令如何变成CPU可以理解的机器语言
任何东西都以二进制的bits形式存在PC中,可以是数据,也可以是指令,取决于如何理解
RISCV的指令形式分为6类
R Format
使用3寄存器的指令
opcode+funct3+funct7决定具体指令名
rs1 rs2 rsd指令操作涉及的寄存器
I Format
使用立即数的指令,Load指令系列
实际数最多允许12bits(3位16进制数),sign extend to 32bits
width:决定Load数据的宽度(word byte half word)
S Format
store指令
保持rs1 rs2在相同位置 把immediate的高位和低位不连续储存
SB Format
PC储存当前指令的地址
指令为word大小,且为字对齐
利用immediate跳转 表示当前指令和需要跳到的指令间隔的word(指令)数
事实上 RISCV支持16bit(半字)指令,则跳转范围减小,且有风险跳转到指令之间
但有助于减小space for instructions
immediate实际上不需要知道bit0,由于是半字对齐,bit0一定是0,所以可以用来保存bit12,相当于encode 13bits
U Format
I指令中立即数只有12位,U指令负责立即数的高20位
lui reg imm
- 设置reg寄存器的高20位,低12位清零
- 配合addi完成32位的设置
lui x10, immHigh addi x10, immLow
Corner Case:如果低12位是1开头,由于sign extension的特性,需要lui upperbits+1
AUIPC
- add upper immediate value to PC and place result in dest
- used for PC-relative addressing