WinMIPS64乘法器模擬(帶符號運算)
阿新 • • 發佈:2018-12-17
本方法為模擬乘法器的實現,對應的是《計算機組成與設計:硬體/軟體介面》第123頁中的圖3-5的實現
正常的乘法是將乘數和積分在2個暫存器中存放的,但可以進行改進:將乘數和積存放在同一個暫存器中,在計算過程中聯合右移,使得剛空出的位馬上被重新利用,這樣的話,就可以節省一個暫存器,並減少對應的暫存器的操作,提高乘法速度。
因為模擬的是32位的乘法,而軟體中的暫存器是64位的,所以被乘數放於$s1的低32位中,乘數和積聯合放在$s2中
程式碼:
.data CONTROL: .word32 0x10000 DATA: .word32 0x10008 .text lwu $t8,DATA($zero) lwu $t9,CONTROL($zero) daddi $s2,$zero,0 ;將積和乘數的聯合暫存器置0 daddi $t1,$zero,8 ;t1置為8,準備用於放到CONTROL裡 sw $t1,0($t9) ;將8放到CONTROL中,開始輸入被乘數 lw $s3,0($t8) ;將被乘數放到s3中 slt $s5,$s3,$zero ;判斷被乘數是否為正,如果為正,s5為0,如果為負,s5為1 beq $s5,$zero,g2 ;依據s5,如果s5為0,表示被乘數為正數,則不做處理 dsub $s3,$zero,$s3 ;依據s5,如果s5為1,表示被乘數為負數,那麼就用0減去被乘數把被乘數變成正數 g2: daddi $s1,$s3,0 ;把被乘數存到s1中用於乘法迴圈的運算 sw $t1,0($t9) ;將8放到CONTROL中,開始輸入被乘數 lw $s3,0($t8) ;將乘數存在s3中 slt $s4,$s3,$zero ;判斷乘數是否為正,如果為正,s4為0,如果為負,s4為1 beq $s4,$zero,g1 ;依據s4,如果s4為0,表示乘數為正數,則不做處理 dsub $s3,$zero,$s3 ;依據s4,如果s4為1,即表示乘數為負數,那麼就用0減去乘數把乘數變成正數 g1: daddi $s2,$s3,0 ;把乘數存到s2中用於乘法迴圈的運算 ;乘法迴圈開始,先做以下準備 daddi $t1,$zero,0 ;t1初始化為0,用來計算迴圈次數 daddi $t7,$zero,1 ;將$t7置為1,方便後面判斷是否是1 daddi $t8,$zero,32 ;將t8置為32,方便判斷是否跳出迴圈 loop: and $t2,$t7,$s2 ;取乘數的最高位 bne $t2,$t7,ad ;判斷最高位是否是1,如果是,則讓積+被乘數 dsll $t2,$s1,16 ;將s1左移16位 dsll $t2,$t2,16 ;再將s1左移16位 dadd $s2,$s2,$t2 ;將移位後的值加到s2中 ad: dsrl $s2,$s2,1 ;右移聯合暫存器s2 daddi $t1,$t1,1 ;次數加1 bne $t1,$t8,loop ;如果次數不等於32,則繼續迴圈 output: xor $s6,$s4,$s5 ;s4和s5代表的是乘數和被乘數的符號位,取他們的異或存在s6中 beq $s6,$zero,out ;如果符號位異或結果是0,則直接輸出 dsub $s2,$zero,$s2 ;如果是1,則用0減去資料再輸出 out: lwu $t8,DATA($zero) lwu $t9,CONTROL($zero) daddi $t2,$zero,8 ;因為模擬器本身的問題,我們需要自己預判一下輸出的數是正是負,然後輸入一個任意的符號和結果一樣的數,才可以正常輸出 sw $t2,0($t9) sw $s2,0($t8) ;把結果放到DATA中 daddi $t2,$zero,2 sw $t2,0($t9) ;把2存到CONTROL中,把DATA中的數輸出 halt
說明:
因為模擬器本身有問題:輸入的數是正數,那麼只能輸出正數,如果輸出負數就會顯示亂碼;同樣,如果輸入的數是負數,那麼輸出的也只能是負數,如果輸出正數就會顯示亂碼。
所以在最後進行輸出的時候進行了一些處理,就是在輸出前人為地預判輸出的數的符號,然後輸入一個任意的相同符號的數就可以避開這個模擬器本身的問題,達到正確輸出了