忽略溢出的乘法器
首先,我们得了解乘法器如何由加法器设计得到,此处,我们以32位乘法为例。
总共分为4步:
1. 测试乘数最低位是否为1,是则给乘积加上被乘数,将结果写入乘积寄存器;
2. 被乘数寄存器左移1位;
3. 乘数寄存器右移一位;
4. 判断是否循环了32次,如果是,则结束,否则返回步骤1。
流程图如图1所示
图1
首先初始化一些数据,包括要输出的两个字符串提示信息和两个内容映射地址,如图2所示。
图2
然后写代码输出这两个字符串,其中输出pleas enter two numbers的代码如图3所示。
图3
然后需要获取被乘数和乘数,将CONTROL的值改为8,获取整数输入,如图4所示。
图4
然后开始乘法计算过程,如图5所示,测试乘数最低位是否为1,是则给乘积加上被乘数,将结果写入乘积寄存器,否则跳到下一步,下一步是被乘数寄存器左移1位,乘数寄存器右移一位,最后判断是否循环了32次,如果是,则结束,否则返回第一步。
图5
最后把CONTROL改为2,输出乘积结果,如图6所示。
图6
运行显示运行结果的例子如下,由于我们这里展示的是忽略了溢出的乘法,所以结果有两种:1、小于32位;2、大于32位。
第一种情况截图如图7所示:
图7
第二种情况截图如图8所示:
图8
根据上面的程序代码和截图,我们可以很清楚的看出,当结果小于32位时,结果正常;当结果大于32位时,结果只截取了低32位的结果,而高32位的结果直接忽略掉了。
代码语言:javascript复制 .data
CONTROL: .word32 0x10000
DATA: .word32 0x10008
cue1: .asciiz "please enter two numbers:n"
cue2: .asciiz "results:n"
.text
daddi r1,r0,cue1 # please enter two numbers
lw r2,DATA(r0)
sd r1,0(r2)
daddi r1,r0,4
lw r2,CONTROL(r0)
sd r1,0(r2)
daddi r1,r0,8 # r3=a
lw r2,CONTROL(r0)
sd r1,0(r2)
lw r2,DATA(r0)
lw r3,0(r2)
daddi r1,r0,8 # r4=b
lw r2,CONTROL(r0)
sd r1,0(r2)
lw r2,DATA(r0)
lw r4,0(r2)
dadd r5,r0,r0 # r5=0 for r5=a*b
daddi r1,r0,32
loop: andi r2,r4,1 # r4[-1]
beq r2,r0,zero # r4[-1]==1?
dadd r5,r5,r3
zero: dsll r3,r3,1
dsra r4,r4,1
daddi r1,r1,-1
bne r1,r0,loop
daddi r1,r0,cue2 # results
lw r2,DATA(r0)
sd r1,0(r2)
daddi r1,r0,4
lw r2,CONTROL(r0)
sd r1,0(r2)
lw r2,DATA(r0) # output a*b
sd r5,0(r2)
daddi r1,r0,2
lw r2,CONTROL(r0)
sd r1,0(r2)
halt
溢出提示的乘法器
上述的程序,用加法实现了32位乘法,但是,其中,对溢出情况没有进行考虑是其中的弊端。这里,我们来完善上述的乘法器,使得该乘法器会在结果溢出时候提示。
其实,这个小优化是十分简单的,只需要对64位的寄存器中的高32位进行检测即可。当高32位为0时,说明结果没有溢出,否则,结果溢出。
首先在数据里加上一条提示字符串,如图9所示。
图9
将乘积寄存器进行算术右移32位取其高32,如图10所示,因不能一次移32位,所以分两次移位,然后判断是否为0,如果高32位为0说明没有溢出,如果不为0则说明已经溢出了,则输出提示字符串。
图10
上述代码运行结果也有两个,一个是没有溢出的情况下的结果,一个是溢出了的情况下的结果。
首先,我们看没有溢出的情况结果,如图11所示:
图11
结果正确,其次,我们看溢出的情况结果如何,如图12所示:
图12
可以看到,当结果溢出时,程序会给出提示“warning:result overflow”。
代码语言:javascript复制 .data
CONTROL: .word32 0x10000
DATA: .word32 0x10008
cue1: .asciiz "please enter two numbers:n"
cue2: .asciiz "results:n"
cue3: .asciiz "warning: result overflown"
.text
daddi r1,r0,cue1 # please enter two numbers
lw r2,DATA(r0)
sd r1,0(r2)
daddi r1,r0,4
lw r2,CONTROL(r0)
sd r1,0(r2)
daddi r1,r0,8 # r3=a
lw r2,CONTROL(r0)
sd r1,0(r2)
lw r2,DATA(r0)
lw r3,0(r2)
daddi r1,r0,8 # r4=b
lw r2,CONTROL(r0)
sd r1,0(r2)
lw r2,DATA(r0)
lw r4,0(r2)
dadd r5,r0,r0 # r5=0 for r5=a*b
daddi r1,r0,32
loop: andi r2,r4,1 # r4[-1]
beq r2,r0,zero # r4[-1]==1?
dadd r5,r5,r3
zero: dsll r3,r3,1
dsra r4,r4,1
daddi r1,r1,-1
bne r1,r0,loop
daddi r1,r0,cue2 # results
lw r2,DATA(r0)
sd r1,0(r2)
daddi r1,r0,4
lw r2,CONTROL(r0)
sd r1,0(r2)
lw r2,DATA(r0) # output a*b
sd r5,0(r2)
daddi r1,r0,2
lw r2,CONTROL(r0)
sd r1,0(r2)
dsra r1,r5,16 # r1=r5[0:31]
dsra r1,r1,16
beq r1,r0,end
daddi r1,r0,cue3 # output overflow
lw r2,DATA(r0)
sd r1,0(r2)
daddi r1,r0,4
lw r2,CONTROL(r0)
sd r1,0(r2)
end: halt