如何修复此代码以执行“使用减法划分”

问题描述 投票:1回答:1

我的程序应该通过使用减法执行除法。但是,我得到了无意义的结果作为输出。有人可以帮助我处理我的程序和循环吗?谢谢。

div proc
pushad

mov ecx,firstInt
mov ebx,0
subtracting:
    sub ebx,secondInt
loop subtracting
mov divResult,ebx
popad
ret
divt endp
assembly division subtraction masm32
1个回答
2
投票

只要没有借用,你就继续减法。如果借款发生,你有计数:

    mov     ecx, firstInt
    mov     ebx, -1
subtracting:
    inc     ebx
    sub     ecx, secondInt
    jnb     subtracting
    mov     divResult, ebx

编辑

上面的代码仍然缺少的是检查分频器是否为零。如果我们允许零分频器,代码将永远运行,因为减零将永远不会产生借用!

这个简单的解决方案可以完成工作,但对于大商而言,速度慢得令人无法接受。这需要一个更好的解决方案,当然不要背叛“使用减法划分”的任务,即“不要使用div(或任何类似的指令)”。

为了模仿div指令:

divide:
    mov     eax, firstInt
    xor     edx, edx
    div     secondInt       ; -> EDX is remainder, EAX is quotient

我们可以写:

simple:
    mov     edx, firstInt
    mov     eax, -1
.A: inc     eax
    sub     edx, secondInt
    jnb     .A
    add     edx, secondInt  ; -> EDX is remainder, EAX is quotient

这个简单解决方案的问题在于我们可以多次减去少量数字。如果我们能找到一次减去更多的方法怎么办? 如果我们减去除法器的二进制倍数(* 1,* 2,* 4,* 8,* 16,...),我们可以。这将是产生商的这些因素的总和。

要计算,例如503 / 20我们会减去以下内容:

503 - (20 * 16) = 183
183 - (20 *  8) =  23
 23 - (20 *  1) =   3 <-- is remainder
            --
            25 <-- is quotient

在代码中:

complex:
    mov     edx, firstInt
    xor     eax, eax
    jmp     .C
.A: rol     ecx, 1
    shl     ebx, 1
    jc      .B
    cmp     ebx, edx
    jbe     .A
.B: rcr     ebx, 1
    add     eax, ecx
    sub     edx, ebx
.C: mov     ebx, secondInt
    mov     ecx, 80000000h
    cmp     edx, ebx
    jnb     .A
; -> EDX is remainder, EAX is quotient

为了说明开发更好的解决方案的重要性,我花了几个时间来划分:

                       simple      complex    divide
                   --------------  --------  --------
4294967295 /   1   8087730.0 µsec  3.0 µsec  0.3 µsec
2147483648 /  10    405994.0 µsec  1.3 µsec  0.1 µsec
     47623 / 320         0.4 µsec  0.2 µsec  0.1 µsec
  • 4294967295 / 1是最糟糕的案件
  • 2147483648 / 10用于开始显示数字2147483648
  • 47623 / 320用于将320x200 256色视频模式偏移地址47623转换为(x,y)坐标
© www.soinside.com 2019 - 2024. All rights reserved.