如何修复此代码以执行 "Division by using Subtracting"
How to fix this code in order to perform "Division by using Subtracting"
我的程序应该使用减法来执行除法。但是,我得到无意义的结果作为输出。有人可以帮助我完成我的程序和内部循环吗?
谢谢。
div proc
pushad
mov ecx,firstInt
mov ebx,0
subtracting:
sub ebx,secondInt
loop subtracting
mov divResult,ebx
popad
ret
divt endp
只要没有借位,你就可以继续减法。如果发生借用,您有计数:
mov ecx, firstInt
mov ebx, -1
subtracting:
inc ebx
sub ecx, secondInt
jnb subtracting
mov divResult, ebx
编辑
上面的代码仍然缺少的是检查除数是否为零。如果我们允许使用零分隔符,代码将永远 运行 因为减去零永远不会产生借位!
这个简单的解决方案可以完成工作,但对于大商来说速度慢得令人无法接受。这需要一个更好的解决方案,当然不会背叛 "Division by using subtracting" aka "Don't use div
(or any similar instruction)".
的任务
为了模仿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)坐标
我的程序应该使用减法来执行除法。但是,我得到无意义的结果作为输出。有人可以帮助我完成我的程序和内部循环吗? 谢谢。
div proc
pushad
mov ecx,firstInt
mov ebx,0
subtracting:
sub ebx,secondInt
loop subtracting
mov divResult,ebx
popad
ret
divt endp
只要没有借位,你就可以继续减法。如果发生借用,您有计数:
mov ecx, firstInt
mov ebx, -1
subtracting:
inc ebx
sub ecx, secondInt
jnb subtracting
mov divResult, ebx
编辑
上面的代码仍然缺少的是检查除数是否为零。如果我们允许使用零分隔符,代码将永远 运行 因为减去零永远不会产生借位!
这个简单的解决方案可以完成工作,但对于大商来说速度慢得令人无法接受。这需要一个更好的解决方案,当然不会背叛 "Division by using subtracting" aka "Don't use div
(or any similar instruction)".
为了模仿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
用于开始显示号码214748364847623 / 320
用于将一个320x200的256色视频模式偏移地址47623转换成(x,y)坐标