MIPS64乘法器模拟实验(计系3实验二)

一、 实验目标:

  1. 实际运用WinMIPS64进行实验,以期更了解WinMIPS64的操作;
  2. 更加深入地了解MIPS程序的语法;
  3. 深入地了解在计算机中乘法的实现以及加法与乘法之间的关系。

二、实验内容

按照下面的实验步骤及说明,完成相关操作记录实验过程的截图:

首先,我们使用加法操作设计一个不检测溢出的乘法操作;完成后,我们对此进行优化,以期获得一个可以对溢出进行检测的乘法操作。(100分)

三、实验环境

       硬件:桌面PC

       软件:Windows,WinMIPS64仿真器

四、实验步骤及说明

       本次试验分为两个部分:第一部分、用加法器设计一个不考虑溢出的乘法器;第二部分、用加法器设计一个考虑溢出的乘法器(编程熟练的同学,也可以用除法器、浮点加法器等替代)。

1、忽略溢出的乘法器

首先,我们得了解乘法器如何由加法器设计得到,此处,我们以32位乘法为例。

总共分为4步:

  1. 测试乘数最低位是否为1,是则给乘积加上被乘数,将结果写入乘积寄存器;
  2. 被乘数寄存器左移1位;
  3. 乘数寄存器右移一位;
  4. 判断是否循环了32次,如果是,则结束,否则返回步骤1。

运行显示运行结果的例子如下,由于我们这里展示的是忽略了溢出的乘法,所以结果有两种:1、小于32位;2、大于32位。

第一种情况截图:

第二种情况截图:

根据上面的程序代码和截图,我们可以很清楚的看出,当结果小于32位时,结果正常;当结果大于32位时,结果只截取了低32位的结果,而高32位的结果直接忽略掉了。

2、溢出提示的乘法器

       上述的程序,用加法实现了32位乘法,但是,其中,对溢出情况没有进行考虑是其中的弊端。这里,我们来完善上述的乘法器,使得该乘法器会在结果溢出时候提示。

       其实,这个小优化是十分简单的,只需要对64位的寄存器中的高32位进行检测即可。当高32位为0时,说明结果没有溢出,否则,结果溢出。

       上述代码运行结果也有两个,一个是没有溢出的情况下的结果,一个是溢出了的情况下的结果。

首先,我们看没有溢出的情况结果:

结果正确,其次,我们看溢出的情况结果如何:

可以看到,当结果溢出时,程序会给出提示“warning:result overflow”。

4 结束语

       本实验介绍了通过加法器来设计乘法器的原理,并且在编写该实验程序的时候,我们更加了解了:1、计算机乘法器工作原理的内容;2、进一步熟练MIPS的编程方法;3、WinMIPS64的使用方法。当然,如果想要更加深入的学习,我们也可以课外继续编写对除法的模拟。

五、实验结果

代码一:

代码二:

请输入数1

请输入数2

输出结果:

溢出情况:

防溢出:

具体代码:

.data
CONTROL: .word 0x10000;     # 控制寄存器的地址
DATA:    .word 0x10008;     # 数据寄存器的地址

mes1: .asciiz "输入 num1:\n";  # 提示用户输入num1的消息
mes2: .asciiz "输入 num2:\n";  # 提示用户输入num2的消息
mes3: .asciiz "答案是:\n";    # 输出答案的消息

.text
# 首先输出 mes1:
    lwu r8, DATA(r0)       ; 无用指令,加载DATA地址
    lwu r9, CONTROL(r0)    ; 无用指令,加载CONTROL地址

    daddi r8, r0, 8        ; DATA地址
    daddi r9, r0, 0        ; CONTROL地址

    lwu r8, (r8)           ; 加载数据
    lwu r9, (r9)           ; 加载控制寄存器

    daddi r11, r0, 4       ; 为输出 mes1 做准备
    daddi r1, r0, mes1     ; 获取mes1的地址
    sd r1, (r8)            ; 保存mes1
    sd r11, (r9)           ; 调用系统输出

    daddi r1, r0, 8         ; 为输入数据做准备
    sd r1, 0(r9)            ; 获取被乘数
    ld r2, 0(r8)
    daddi r10, r2, 0        ; 将被乘数存储在r10中

    daddi r11, r0, 4        ; 为输出 mes2 做准备
    daddi r1, r0, mes2      ; 获取mes2的地址
    sd r1, (r8)             ; 保存mes2
    sd r11, (r9)            ; 调用系统输出

    daddi r1, r0, 8         ; 为输入数据做准备
    sd r1, 0(r9)            ; 获取乘数
    ld r2, 0(r8)
    daddi r11, r2, 0        ; 将乘数存储在r11中

# 循环:对于每一位乘数,如果乘数最低位为1,则进行加法操作
    daddi r12, r0, 0        ; r12用于存储乘法结果
    daddi r13, r0, 0        ; 初始化循环变量i

 loop:
    slti r15, r13, 32       ; 检查i是否小于32
    beq r15, r0, exit_loop  ; 如果i >= 32,则退出循环

    andi r14, r11, 1        ; 获取乘数的最低位
    beq r14, r0, out_add    ; 如果最低位为0,跳过加法

    # 进行乘法加法
    dadd r12, r12, r10

 out_add:
    dsll r10, r10, 1        ; 被乘数左移1位
    dsrl r11, r11, 1        ; 乘数右移1位
    daddi r13, r13, 1       ; i自增
    j loop

 exit_loop:
    
    daddi r11, r0, 4        ; 为输出 mes3 做准备
    daddi r1, r0, mes3      ; 获取mes3的地址
    sd r1, (r8)             ; 保存mes3
    sd r11, (r9)            ; 调用系统输出

    daddi r11, r0, 2        ; 为输出整数做准备
    daddi r1, r12, 0        ; 获取乘法结果
    sd r1, (r8)             ; 保存
    sd r11, (r9)            ; 调用系统输出

    halt



二:
.data

CONTROL: .word 0x10000;     # 控制寄存器的地址
DATA:    .word 0x10008;     # 数据寄存器的地址

mes1: .asciiz "请输入 num1:\n";  # 提示用户输入num1的消息
mes2: .asciiz "请输入 num2:\n";  # 提示用户输入num2的消息
mes3: .asciiz "答案是:\n";      # 输出答案的消息
mes4: .asciiz "结果溢出了。";     # 输出溢出消息

.text
# 首先输出 mes1:
    lwu r8, DATA(r0)       ; 无用指令,加载DATA地址
    lwu r9, CONTROL(r0)    ; 无用指令,加载CONTROL地址

    daddi r8, r0, 8        ; DATA地址
    daddi r9, r0, 0        ; CONTROL地址

    lwu r8, (r8)           ; 加载数据
    lwu r9, (r9)           ; 加载控制寄存器

    daddi r11, r0, 4       ; 为输出 mes1 做准备
    daddi r1, r0, mes1     ; 获取mes1的地址
    sd r1, (r8)            ; 保存mes1
    sd r11, (r9)           ; 调用系统输出

    daddi r1, r0, 8         ; 为输入数据做准备
    sd r1, 0(r9)            ; 获取被乘数
    ld r2, 0(r8)
    daddi r10, r2, 0        ; 将被乘数存储在r10中

    daddi r11, r0, 4        ; 为输出 mes2 做准备
    daddi r1, r0, mes2      ; 获取mes2的地址
    sd r1, (r8)             ; 保存mes2
    sd r11, (r9)            ; 调用系统输出

    daddi r1, r0, 8         ; 为输入数据做准备
    sd r1, 0(r9)            ; 获取乘数
    ld r2, 0(r8)
    daddi r11, r2, 0        ; 将乘数存储在r11中

# 循环:对于每一位乘数,如果乘数最低位为1,则进行加法操作
    daddi r12, r0, 0        ; r12用于存储乘法结果
    daddi r13, r0, 0        ; 初始化循环变量i

 loop:
    slti r15, r13, 32       ; 检查i是否小于32
    beq r15, r0, exit_loop  ; 如果i >= 32,则退出循环

    andi r14, r11, 1        ; 获取乘数的最低位
    beq r14, r0, out_add    ; 如果最低位为0,跳过加法

    # 进行乘法加法
    dadd r12, r12, r10

 out_add:
    dsll r10, r10, 1        ; 被乘数左移1位
    dsrl r11, r11, 1        ; 乘数右移1位
    daddi r13, r13, 1       ; i自增
    j loop

 exit_loop:
    
    daddi r11, r0, 4        ; 为输出 mes3 做准备
    daddi r1, r0, mes3      ; 获取mes3的地址
    sd r1, (r8)             ; 保存mes3
    sd r11, (r9)            ; 调用系统输出

    daddi r11, r0, 2        ; 为输出整数做准备
    daddi r1, r12, 0        ; 获取乘法结果
    sd r1, (r8)             ; 保存

    sd r11, (r9)            ; 调用系统输出

    # 右移32次
    daddi r13, r0, 0        ; 重新初始化i
 loop2:
    slti r15, r13, 32       ; 检查i是否小于32
    beq r15, r0, exit_loop2  ; 如果i >= 32,则退出循环
    dsrl r12, r12, 1        ; 右移1位
    daddi r13, r13, 1       ; i自增
    j loop2

 exit_loop2:
        
    # 判断是否溢出
    beq r12, r0, out_print  ; 当r12的高位不为零时打印溢出消息

    # 打印
 out_print:
    daddi r11, r0, 4        ; 为输出 mes4 做准备
    daddi r1, r0, mes4      ; 获取mes4的地址
    sd r1, (r8)             ; 保存mes4
    sd r11, (r9)            ; 调用系统输出

 halt

六、实验总结与体会

此次实验让我对mips有了更深的了解,但winmips64软件r8r9老是出问题不知道是什么原因。

  • 12
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值