使用移位进行除法的问题

Posted

技术标签:

【中文标题】使用移位进行除法的问题【英文标题】:Trouble with division using shifting 【发布时间】:2013-03-26 01:03:40 【问题描述】:

我在使用 MIPS 实现除法算法时遇到了一些麻烦,我假设它与我移动和设置最低有效位的方式有关,但我不完全确定。

算法如下:

1) 余数寄存器减去除数寄存器,将结果放入余数寄存器。

2a) 如果余数 >= 0,则将商寄存器左移,将新的最右边位设置为 1

2b) 如果余数

3) 将除数寄存器右移一位

4) 重复 n+1 次。由于我们正在进行无符号 8 位除法,我会假设这意味着 9 次重复

编辑:为了简单起见,我只设置了 $t0 = 12 和 $t1 = 5。但是对于商,我得到 63,余数得到 0


    .data
    quotient_a:     .asciiz "Quotient (a/b): "
    remainder_a:        .asciiz "Remainder (a/b):"
    quotient_b:     .asciiz "Quotient (b/a): "
    remainder_b:        .asciiz "Remainder (b/a):"
    error:          .asciiz "Sorry, divide-by-zero not allowed"
    new_line:       .asciiz "\n"


    .text
main:
    li $s0, 8   #8 bit

    li $t0, 12
    li $t1, 5

    ## Quotient  A message
    la $a0, quotient_a      # load the addr of display_sum into $a0.
    li $v0, 4           # 4 is the print_string syscall.
    syscall             # do the syscall.

    ##Computer the Quotient and remainder
    ## $t0 = a     $t1 = b
    ## $t0 = dividend       $t1 = divisor
    li $t2, 0       ##Quotient
    li $t3, 0       ##Remainder
    li $t9, 0       ##i
    li $s0, 9       ##count

loop:
    sub $t3, $t3, $t1
    blt $t3, 0, less_than
    ## >= 0
    sll $t2, $t2, 1
    addi $t2, $t2, 1
    j cont

less_than:
    add $t3, $t3, $t1
    sll $t2, $t2, 1

cont:   
    srl $t1, $t1, 1 
    addi $t9, $t9, 1
    bne $t9, $s0, loop



    ## print the quotient 
    move $a0, $t2
    li $v0, 1           # load syscall print_int into $v0.
    syscall             # make the syscall.

    ## new line
    la $a0, new_line        # load the addr of new_line into $a0.
    li $v0, 4           # 4 is the print_string syscall.
    syscall 

    ## Remainder A message
    la $a0, remainder_a         # load the addr of display_sum into $a0.
    li $v0, 4           # 4 is the print_string syscall.
    syscall             # do the syscall.

    ## print the remainder 
    move $a0, $t3
    li $v0, 1           # load syscall print_int into $v0.
    syscall             # make the syscall.

    #Exit Program
    li $v0, 10          # syscall code 10 is for exit.
    syscall             # make the syscall.

【问题讨论】:

【参考方案1】:

算法的描述对我来说有点不对劲。这就是 C 中有效的 8 位除法算法的样子:

unsigned char Q,R;
unsigned char N=12,D=5;
int i;

Q = 0;
R = 0;
for (i = 0; i < 8; i++) 
    R <<= 1;
    R |= (N & 0x80) >> 7;
    N <<= 1;
    Q <<= 1;
    if (R >= D) 
        R -= D;
        Q |= 1;
    

将其转录成 MIPS 程序集应该不会太困难。

【讨论】:

(N & 0x80) 指的是什么?在我正确执行之后我会向右移动 7 吗? 这是与1&lt;&lt;7 的按位与(即0x80)。是的,你会在 AND 之后立即移动它。 R |= (N &amp; 0x80) &gt;&gt; 7; 所做的是将 N 的第 7 位复制到 R 的第 0 位。

以上是关于使用移位进行除法的问题的主要内容,如果未能解决你的问题,请参考以下文章

请问怎样用加法-移位实现定点乘除法?

单片机 怎么用位移的方法实现乘除法

使用移位操作代替乘除运算

除以 9 而不使用除法或乘法运算符

C++的大数除法最快速度的算法

关于fpga的除法