Risc-V学习日记06
Day12
算术运算指令(Arithmetic Instructions)
ADD
语法:ADD RD,RS1,RS2
例子:add x5,x6,x7 x5=x6+x7
opcode(7):01-100|11(OP)//查表page130
"R-type"
rs2,rs1,rd[用于存放寄存器参数]
rd(register destination)存放结果
rs(register source)源数据
一个寄存器占5个bit
funct3:000//查表page130
funct7:0000000//查表page130
0000000|RS2|RS1|000|RD|01-100|11
7+6=13
0x007302B3转化为二进制
0000-0000-0111-0011-0000-0010-1011-0011
000000000111-00110-000-00101-0110011
OP:
01-100-11
00000000011100110000-00101
RD:
00110
00000000011100110-000
funct3
000
000000000111-00110
rs1
01100
0000000-00111
rs2
00111
funct7:0000000
SUB减法
语法:SUB RD,RS1,RS2
例子:sub x5,x6,x7 x5=x6-x7
rule.mk
debug:
@echo "Press Ctrl-C and then input 'quit' to exit GDB and QEMU"
@echo "-------------------------------------------------------"
@${QEMU} ${QFLAGS} -kernel ${EXEC}.elf -s -S &
QEMU=qemu-system-riscv32//模拟器模拟riscv32
QFLAGS=-nographic -smp 1 -machine virt -bios none
nographic:不起图形界面
smp:用一个hart
virt:使用的设备类型为virt
-s:使用远程调试模式,运行了一个gdbserver与gdb通信
-S:使程序中断
&:把qemu放在后台
@${GDB} ${EXEC}.elf -q -x ${GDBINIT}
-q:清理
-x:启动脚本{GDBINIT}
{GDBINIT}
避免每次手动去链接服务器
exercise:{{
.text # Define beginning of text section
.global _start # Define entry _start
_start:
li x6, 1 # x6 = 1
li x7, 2 # x7 = 2
add x5, x6, x7 # x5 = x6 + x7
stop:
j stop # Infinite loop to stop execution
#死循环
.end # End of file
}
不能直接从windows拖文件进虚拟机会搞乱makefile文件格式
git clone https://gitee.com/unicornx/riscv-operating-system-mooc.git
make
make hex
13 03 10 00|93 03 20 00|b3 02 73 00|6f 00 00 00
b3 02 73 00为add——————>0x007302B3 //小端序
make code
//makerun Ctrl-a 再按x强制停止qemu
//makedebug Ctrl-c 输入quit
make debug
si单步执行 (step Instructions)
回车自动执行上步指令
}
无符号数,有符号数:
有符号数在计算机中的表示:二进制补码(twoscomplement)
例如,十进制的-3用8位二进制补码表示是:
绝对值的二进制表示为3:0000 0011
按位取反:1111 1100
加1:1111 1101
符号扩展(Sign extension)v.s. 零扩展(Zeroextension)
符号扩展
例如,考虑一个8位的有符号整数:11010110。如果我们要将其符号扩展为16位,那么,由于最高位是1(表示负数),在高位填充1,得到:1111111111010110
零扩展
例如,考虑一个8位的无符号整数:01010110。如果我们要将其零扩展为16位,那么在高位填充零,得到:0000000001010110
exercise_5_1
0x00001000 in ?? ()
=> 0x00001000: 97 02 00 00 auipc t0,0x0
1: /z $x5 = 0x00000000
2: /z $x6 = 0x00000000
3: /z $x7 = 0x00000000
97 02 00 00 0x00-00-02-97
0x0 -> 0000
0x0 -> 0000
0x0 -> 0000
0x2 -> 0010
0x9 -> 1001
0x7 -> 0111
0000-0000-0000-0000-0000-0010-1001-0111
"U-type"
0000000000000000000000101-0010111
001-01-11
OP:001-01-11[STORE-FP]
imm(立即数):0000000000000000000000101
AUIPC
qemu默认起始地址为0x80000000
Add Upper Immediate to PC
AUIPC指令用于将一个符号扩展的立即数与PC(程序计数器)的上位部分相加,然后将结果存储到目标寄存器中。它主要用于计算全局地址
1.将PC(程序计数器)的上位部分(前20位)拷贝到目标寄存器的位置。
2.将符号扩展的立即数(左移12位)与上一步得到的值相加。
3.将相加的结果存储到目标寄存器中。
AUIPC指令在处理全局地址时非常有用,因为它可以将一个相对较大的立即数与当前PC的上位部分相加,从而实现较大范围的跳转和地址计算。
此时x5 = 0x80000000??目前还未解释
Breakpoint 1, _start () at test.s:12
12 li x6, -1 # x6 = -1
=> 0x80000000 <_start+0>: 13 03 f0 ff li t1,-1
1: /z $x5 = 0x80000000 #(由于AUIPC指令加载了PC + 0x1000的值,因此初始PC为0x80000000。)
2: /z $x6 = 0x00000000
3: /z $x7 = 0x00000000
13 03 f0 ff 0xff-f0-03-13
0 -> 0000
1 -> 0001
3 -> 0011
f -> 1111
1111-1111-1111-0000-0000-0011-0001-0011
OP:0010011
rd=0011-0
1111-1111-1111-0000-0-000
funct3=000
所以为ADDI
rs1=00000
111111111111-00000-000-00110-0010011
ADDI它是"Add Immediate"的缩写。ADDI指令用于将一个立即数与一个源寄存器的值相加,并将结果存储到目标寄存器中
ADDI指令的执行过程如下:
1.从rs1寄存器中取出源操作数的值。00000
2.将立即数imm与源操作数相加。111111111111+00000=111111111111
首先,查看二进制数"111111111111"的最高位,它是1,所以是一个负数。
取反:将"111111111111"中的0变1,1变0得到"000000000000"。
加1:在取反的结果上加1,得到"000000000001"
3.将相加的结果存储到目标寄存器rd中。rd=-1
(gdb) si
13 li x7, -2 # x7 = -2
=> 0x80000004 <_start+4>: 93 03 e0 ff li t2,-2
1: /z $x5 = 0x80000000
2: /z $x6 = 0xffffffff
3: /z $x7 = 0x00000000
(gdb)
14 sub x5, x6, x7 # x5 = x6 - x7
=> 0x80000008 <_start+8>: b3 02 73 40 sub t0,t1,t2
1: /z $x5 = 0x80000000
2: /z $x6 = 0xffffffff
3: /z $x7 = 0xfffffffe
(gdb)
stop () at test.s:17
17 j stop # Infinite loop to stop execution
=> 0x8000000c <stop+0>: 6f 00 00 00 j 0x8000000c <stop>
1: /z $x5 = 0x00000001
2: /z $x6 = 0xffffffff
3: /z $x7 = 0xfffffffe
Risc-V学习日记06
于 2023-08-03 14:45:56 首次发布