导言:做完真的很烦,记录一下,方便以后查找~~
一、实验目的
1、掌握RISC-V基础指令集RV32I的指令格式和使用方法;
2、学会RISC-V汇编模拟器RARS的使用;
3、掌握用RISC-V汇编语言编写、调试和运行程序的方法。
二、实验内容
(一)安装并熟悉RISC-V汇编模拟器RARS的使用;
(二)完成以下程序的编写
1、顺序结构的编程
计算y=12a+7b-c,其中y放在寄存器a0中,a、b、c三个变量存放的寄存器不限。要求不用乘法指令。
.data
a: .word 5 # 变量a的值
b: .word 10 # 变量b的值
c: .word 30 # 变量c的值
#算的结果10进制应该是100,对应16进制应该是64,所以a0应该是64
.text
main:
lw t0, a # 加载变量a到寄存器$t0
lw t1, b # 加载变量b到寄存器$t1
lw t2, c # 加载变量c到寄存器$t2
# 计算 12a
slli t3, t0, 3 # 左移3位,相当于乘以2的3次方,即乘以8
slli t4, t0, 2 # 左移2位,相当于乘以2的2次方,即乘以4
add t4, t4, t3 # t3+t4相当于乘于12;
# 计算 7b
slli t5, t1, 3 # 左移2位,相当于乘以2的3次方,即乘以8
sub t5, t5, t1 # 减去t1相当于乘于7
# 计算 y = 12a + 7b - c
add a0, t4, t5 # 计算12a + 7b
sub a0, a0, t2 # 减去c
# 输出整数到控制台
li a7, 1 # 系统调用号 1 表示输出整数
ecall
# 结束程序
li a7, 10 # 系统调用号10表示退出程序
ecall
运行结果:
2、分支结构的编程
计算C语言表达式: if (x>=y) z=x+10; else z=y-10。其中z存放在寄存器a1中,x、y存放的寄存器不限。
.data
x: .word 5 # 假设 x 的值为5
y: .word 12 # 假设 y 的值为12
ten: .word 10
.text
main:
lw t0, x # 加载变量x到寄存器$t0
lw t1, y # 加载变量y到寄存器$t1
lw t2, ten # 加载变量ten到寄存器$t2中,这样子可以参与运算
# 判断 x >= y
bge t0, t1, bigger_than_or_equal # 如果 x >= y,则跳转到 bigger_than_or_equal
# 如果 x < y,则执行以下指令
sub a0, t1, t2 # z = y - 10
j end # 跳转到结束
bigger_than_or_equal:
add a0, t0, t2 # z = x + 10
end:
# 输出整数到控制台
li a7, 1 # 系统调用号 1 表示输出整数
ecall
# 结束程序
li a7, 10 # 系统调用号10表示退出程序
ecall
运行结果:
3、循环结构的编程
计算y=1+2+3…+88,y存放在寄存器a2中。
.text
main:
li t0, 1 # 初始化循环变量 i 为 1
li t1, 100 # 设置循环上限为 88
li a0, 0 # 初始化结果变量 y 为 0,放在寄存器a0中
loop:
add a0, a0, t0 # 将当前循环变量 i 加到结果变量 y 中
addi t0, t0, 1 # i = i + 1
blt t0, t1, loop # 如果 i < 88,继续循环
# 循环结束,a2 中存放的即为 y
# 输出整数到控制台
li a7, 1 # 系统调用号 1 表示输出整数
ecall
# 结束程序
li a7, 10 # 系统调用号10表示退出程序
ecall
运行结果:
4、系统调用
输出提示信息“请输入姓名:”,从键盘输入本人姓名的字符串;输出提示信息“请输入学号:”,输入本人学号后3位(整数形式)。程序结束后调用exit功能退出。
提示:系统调用功能的使用方式:将功能号放入a7寄存器,参数放入a0~a3等系统要求的寄存器,运行ecall指令。常用的系统调用功能有:
功能号 | 功能描述 | 输入值 | 输出值 |
1 | 输出1个整数 | a0 = 要输出的整数 | |
4 | 输出字符串 | a0 = 要输出的字符串首地址 | |
5 | 输入1个整数 | a0 = 输入的整数 | |
8 | 输入字符串 | a0 = 输入字符串放置的地址 a1 = 最大的输入字符个数 | |
10 | 退出程序exit | ||
11 | 输出ascii字符 | a0 = 要输出的字符 (只输出最低字节) |
更多的系统调用功能详见RARS系统Help中的Syscalls部分。
用法示例:
la a0,string #假设字符串首地址标号为string,放入a0
li a7,4 #a7中存放功能号4
ecall #开始系统调用,即可输出字符串到Run/IO区。
本题运行后,结果显示如下:
.data
prompt_name: .string "请输入姓名:"
prompt_id: .string "请输入学号:"
output_info: .string "已输出信息:\n" # 添加换行符
newline: .string "\n" # 换行符
.text
main:
# 输出提示信息“请输入姓名:”
la a0, prompt_name
li a7, 4 # 功能号4表示输出字符串
ecall
# 输入姓名
la a0, buffer_name
li a1, 32 # 假设名字的最大长度为32
li a7, 8 # 功能号8表示输入字符串
ecall
# 输出提示信息“请输入学号:”
la a0, prompt_id
li a7, 4 # 功能号4表示输出字符串
ecall
# 输入学号
la a0, buffer_id
li a1, 8 # 输入8位数字,假设学号最大为8位
li a7, 8 # 功能号5表示输入整数
ecall
# 输出已输出信息
la a0, output_info
li a7, 4 # 功能号4表示输出字符串
ecall
# 输出姓名
la a0, buffer_name
li a7, 4 # 功能号4表示输出字符串
ecall
# 输出学号
la a0, buffer_id
li a7, 4 # 功能号1表示输出整数
ecall
# 跳到下一行
la a0, newline
li a7, 4 # 功能号4表示输出字符串
ecall
# 调用exit功能退出
li a7, 10 # 功能号10表示退出程序
ecall
.data
buffer_name: .space 32 # 用于存储姓名的缓冲区
buffer_id: .space 8 # 用于存储学号的缓冲区,假设最大8位
运行结果:
5、综合编程
利用数据结构课所学的任意一种排序方式,将数据区的10个数字按从小到大排序,并输出显示。要求程序的第一行注释里写明是采用什么排序方式,如冒泡排序。数据区为:
.data
array: .word -15,1024,12,60,19,26,-18,19,100,86
.data
array: .word -15, 1024, 12, 60, 19, 26, -18, 19, 100, 86
msg: .string "排序后的数组为:\n"
blank: .ascii " " # 空格
.text
main:
la t0, array # 存储 array 的首地址
addi t1, zero, 0 # i = 0
addi t2, t1, 11 # 数组元素个数 10,后面 i 多加了一次
addi t3, zero, 0 # j = 0
addi s1, t2, -1 # s1 = 9
loop1:
bge t1, t2, print # i >= n 打印
li t3, 0 # j
addi t1, t1, 1 # i++
loop2:
sub t4, s1, t1 # n - i - 1
blt t3, t4, branch # j <= n - i - 1
j loop1
branch:
slli a1, t3, 2 # t1 左移 2 位即乘以 4,乘 4 是因为 word 数据 4 字节
add a1, t0, a1 # 数组首地址 t0 加 a1,即走到数组的第 1 个元素 a1 = array + j * 4
lw a2, 0(a1) # 取数组元素值放入 t4 a2 = array[j]
lw a3, 4(a1) # 下一个元素 a3 = array[j+1]
bgt a2, a3, swap # 第 j 个元素 > 第 j+1 个元素则交换
addi t3, t3, 1 # j++
j loop2
swap:
sw a3, 0(a1) # array[j] = a3 即第 j+1 个元素
sw a2, 4(a1) # array[j+1] = a2
addi t3, t3, 1 # j++
j loop2
print:
la a0, msg
li a7, 4
ecall
la t0, array
li s2, 10 # 总数 n = 10
li s3, 0 # i = 0
printloop:
beq s3, s2, exit # i = 10 时退出
slli s4, s3, 2 # 4 * i
add s4, t0, s4 # array + 4i
lw a0, 0(s4)
li a7, 1
ecall
la a0, blank # 两数之间加空格
li a7, 4
ecall
addi s3, s3, 1 # i++
j printloop
exit:
li a7, 10
ecall
运行结果: