使用Fermat素数测试的乘法模逆Assembly MIPS

问题描述

接收两个整数ap并打印x使得ax ≡ 1 (mod p)
p是质数,a不是p的倍数

代码在MARS中可以正常工作,但是在QTSpim中,它抱怨过大(immediate value 825265 out of range),并在p和素数时指出错误。为什么两者之间有这种区别?

enter image description here

    .data
message1: .asciiz "Invali Input\n"
message2: .asciiz "inverse = "
message3: .asciiz "The module is not a prime\n"
finalLine: .asciiz "\n"
    .text
main:
    li $v0,5
    syscall
    move $t8,$v0
    
    li $v0,5
    syscall
    move $t9,$v0
    beq $t8,2,verifyMult
    ble $t8,1,invalidInput
    ble $t9,invalidInput
    
    j pr

verifyMult:
    div $t9,$t8
    mfhi $s1
    beq $s1,invalidInput
    j modInverse
main3:  
    li $v0,4
    la $a0,message2
    syscall
    
    li $v0,1
    move $a0,$t4
    syscall
    
    li $v0,finalLine
    syscall
    
    li $v0,10
    syscall

invalidInput:
    li $v0,message1
    syscall 
    
    li $v0,10
    syscall
    
invalidMod:
    li $v0,message3
    syscall 
    
    li $v0,10
    syscall
modInverse:
    move $t0,$t8
    move $t1,$t9
    
    addi $t2,$t0,0 
    addi $t3,$zero,0
    addi $t4,1
    while:
        ble $t1,exit  
        div $t1,$t0
        mflo $t5
        addi $t6,0
        mfhi $t0
        
        addi $t1,$t6,0
        addi $t6,$t3,0
        
        mult $t5,$t3
        mflo $s0
        
        sub $t3,$t4,$s0
        addi $t4,0
        j while 
        
    exit:
        blt $t4,makePositive
        j main3
        
    makePositive: 
        add $t4,$t2
        j main3

pr: 
      add  $s5,$t8,$zero  
      
      andi $t1,$s5,1
      beq $t1,invalidMod 
      
      xor $t0,$t0
      addiu $t0,561
      beq $s5,1105
      beq $s5,1729
      beq $s5,2465
      beq $s5,invalidMod
      
       xor $t0,2821
      beq $s5,invalidMod
      
      xor $t0,6601
      beq $s5,8911
      beq $s5,10585
      beq $s5,invalidMod
      
      addiu $t2,$t2,41041
      beq $s5,invalidMod 
      
      addiu $t3,825265
      beq $s5,invalidMod 
      
      addiu $t4,321197185 
      beq $s5,invalidMod 
      
      move $s1,$s5
      xor $t2,$t2

      xor $t3,$t3
     
      xor $t4,$t4
      addiu $t4,2 
     
     
loop_exponent:
     andi $t1,1      
     beq $t1,even_exponent
    
     subiu $s5,1
     
     sll $t2,1   
     addiu $t2,1   

     j next_iteration   

even_exponent:
    sll $t2,1
    srl $s5,1
    
next_iteration:
     addiu $t3,1      
     bne $s5,loop_exponent      
     

     sll $t2,1
     addiu $t3,1  
    
     xor $t5,$t5,$t5
     addiu $t5,3
     
     xor $t6,$t6
     addiu $t6,3
     
loop_compute_mod:
     andi $t1,even
     
     multu $t5,$t6
     mflo $t5
     divu $t5,$s1

     mfhi $t5
     j next_exponent_bit
even:
    multu $t5,$t5
    mflo $t5
    divu $t5,$s1

    mfhi $t5
 
 next_exponent_bit:

    subiu $t3,1
    srl $t2,1
    bgtz $t3,loop_compute_mod     
     
     divu $t6,$s1
     mfhi $t6
     
     beq $t5,verifyMult
     j invalidMod         
      

 

解决方法

MARS允许将每条指令视为伪指令,通过在另一个寄存器中构造值来处理较大的立即数。

QtSpim更像传统的MIPS汇编程序,仅将一些指令(例如li)作为伪指令而不是addiu对待。

825265不适合16位带符号立即数。 41041-SPIM也不应该对此抱怨。