RISC-V汇编语言设计实验

导言:做完真的很烦,记录一下,方便以后查找~~

一、实验目的

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

运行结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乄bluefox

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值