MIPS——有符号乘法

在无符号乘法基础上改进的有符号乘法。如有错误请指正。(debug弄死我了)

init:
    li $v0 5                    #输入被乘数$a0
    syscall
    addu $a0 $v0 $0
    li $v0 5                    #输入乘数$a1
    syscall
    addu $a1 $v0 $0
    li $v1 0                    #$v1存储积的高32位
    li $v0 0                    #$v0存储积的低32位
    li $t2 0                    #$t2记录执行次数
    andi $t1 $a0 0x80000000     #判断被乘数是否为负数 若为负数则进行符号扩展
    beq  $t1 0   posi           
                                #$s0存储被乘数的高32位
    li $s0 0xffffffff           #符号扩展        
    j  mull
    
 posi:
    li $s0 0   
    
mull:
    andi $t1 $a1 1          #判断乘数的最后一位是否为1
    beq  $t1 0   shift      #最后一位不是1 进入移位部分
    addu $v1 $v1 $s0        #积的高32位=积的高32位+被乘数的高32位
    addu $v0 $v0 $a0        #积的低32位=积的低32位+被乘数的低32位
    sltu $t1 $v0 $a0        #判断低32位相加时是否溢出 若溢出则和必定小于乘数
    beq  $t1 $0  shift      #没有溢出 进入移位部分
    addiu $v1 $v1 1         #发生溢出 积的高32位加1
    
shift:
    srl  $a1 $a1 1          #乘数右移一位
    sll  $s0 $s0 1          #先将被乘数的高32位左移一位
    andi $t1 $a0 0x80000000 #判断被乘数的低32位最高位是否为1
    sll  $a0 $a0 1          #被乘数的低32位左移一位
    beq  $t1 0   ad         #被乘数的低32位最高位不是1 进入自增部分 
    addiu $s0 $s0 1         #被乘数的低32位最高位是1 高32位加1
    
ad:
    addi $t2 $t2 1          #执行次数加1
    slti $t1 $t2 31         #判断是否已经执行31次
    beq  $t1 1   mull       #还未执行31次 进入下一次循环
    
check:                      #若乘数一开始为负数 既符号位为1 那么最后还要加上被乘数的补码
    beq  $a1 0  print1      #乘数为正数 直接进入打印部分
    nor  $s0 $s0 $s0        #被乘数的高32位取反
    nor  $a0 $a0 $a0        #被乘数的低32位取反
    addiu $a0 $a0 1         #取反再加1得到补码
    sltiu $t0 $a0 1         #判断溢出
    add  $s0 $s0 $t0        #高32位加上溢出位
    addu $v1 $s0 $v1        #积的高32位=积的高32位+被乘数的高32位
    addu $v0 $v0 $a0        #积的低32位=积的低32位+被乘数的低32位
    sltu $t1 $v0 $a0        #判断低32位相加时是否溢出 若溢出则和必定小于乘数
    beq  $t1 $0  print1     #没有溢出 进入打印部分
    addiu $v1 $v1 1         #发生溢出 积的高32位加1
    
print1:
    move $s0 $v0            #先将积的低32位转移
    move $a0 $v1            #将积的高32位放到$a0
    beq  $a0 0 print2       #如果积的高32位为0或-1 进入低32位输出部分
    beq  $a0 0xffffffff print2
    li   $v0 1              #打印积的高32位
    syscall
    
print2:
    move $a0 $s0            #将积的低32位放到$a0
    li   $v0 1              #打印积的低32位
    syscall
    
exit:
    li   $v0 10             #退出程序
    syscall
    
    
    
    
    

 

posted @ 2020-11-03 23:50  yanying  阅读(1050)  评论(0编辑  收藏  举报