我在MASM X8086-32bit程序集中编写一个8位整数newton raphson函数,我想我陷入了无限循环。我必须用于类的编辑器不会为无限循环发送错误。
无论如何我不确定我的问题在哪里。几周前我刚刚开始使用MASM,并且对于无限循环有点失去任何帮助。我的初始x值定义为1。
函数是y = 1/2(x + n / x)===> x / 2 + n / 2x其中n是有问题的数字。和x是初始化的值,然后是前面的迭代y值。
mov ah, 09h
lea dx, prompt ;Prompt User
int 21h
mov ah, 01h
int 21h ;User input
sub al, 30h
mov bh, al
mov bl, x ;Loading for loop
mov al, x
iteration:
mul bl; al*bl = al
mov dl, al ; storing x^2
add al, 01h ; (x+1)^2
mul al
cmp bh, dl
jge doneCheck ; bh - dl ====> n- x^2 => 0
doneCheck:
cmp bh, al; bh-al = ? ====>n - (x+1)^2 == -int
jl done
mov al, 02h; loading 2 in ah
mul bl ; bl*al = 2(bl) = 2x = al
shr bl, 1 ; x/2 = bl
mov cl, al ; storing 2x in cl
mov ah, 0 ; clearing ah
mov ch, 0; clearing ch
mov al, bh ; moving n into ax for division prep
div cx ; ax/cl ====> n/2x ===> p =ah and q = al
add bl, ah ;so this is finally 1/2(x+(n/x)) === (x/2+n/2x) y the new value y is now stored in bl for next loop
mov al, bl ; for next loop
jmp iteration
done:
mov dl, bl; print square root
mov ah, 02h
int 21h
答案 0 :(得分:4)
此:
shl bl, 1 ; x/2 = bl
不应该是?:
shr bl,1
- 更新:
关于你的问题:
BH = Number to find sqrt. When x^2 == BH then x is the sqrt(n)
AL and BL = y value of the last iteration
你做了:
mul bl ; AL*BH => AX
cmp bh, al ; BH == AL? or with names: n == x^2 ?
为什么无限循环?:
当您使用AH=01h+int 21h进行输入时,您只能阅读一个字符,并且您在AL中获得ascii code。
假设用户输入的数字是“A”,它被翻译成数字 65 。绝不是,任何整数都会给你x ^ 2 = 65,所以循环将永远循环。
我建议您使用此条件作为循环中断。结果将是近似值(四舍五入到较低的数字):
(n >= x^2) && (n < (x+1)^2)
请记住,你正在使用8位工作,所以最高的解决方案是:y = 15.看看这个:
1^2 = 1
2^2 = 4
3^2 = 9
4^2 = 16
5^2 = 25
6^2 = 36
7^2 = 49
8^2 = 64
...
15^2 = 225
这些是唯一数字,您可以使用代码(不含我的提案)来计算sqrt。
所以你只能按下以下键作为输入:
$ = number 36
1 = number 49
@ = number 64
Q = number 81
d = number 100
y = number 121
这些之间的任何按键都会使你的代码陷入无限循环。
输出的提示:在打印之前将BL添加到BL,使其变为ASCII数字:)
- 更新2:
从您的代码中我发现了这个错误:
add al, 01h ; (x+1)^2 ; AL = x^2, therefore you are doing (x^2)+1
mul al
这里执行流程将始终执行所有行:
cmp bh, dl
jge doneCheck ; bh >= dl? ====> n >= x^2 ?
doneCheck:
cmp bh, al; bh-al = ? ====>n - (x+1)^2 == -int
jl done
我想它应该是这样的:
cmp bh, dl ; n vs x^2
jb notSolution ; BH < DL? ====> if n < x^2 continue with next NR step
cmp bh, al ; here, n >= x^2
jb done ; BH < AL ? ====> if n < (x+1)^2 we found a solution
notSolution: ; n is not in [ x^2 , (x+1)^2 )
我使用jb
代替jl
,因为我只假设数字是正确的。 jl
会将129视为负数,也许我们会遇到麻烦。
- 更新3:
从Peter Cordes'回答,我没有注意到的详细信息(我看过div cl
):
div cx; ax / cl ====&gt; n / 2x ===&gt; p =啊和q = al。如果您使用div cl
,那将是正确的
答案 1 :(得分:2)
我不确定你是否正确地理解MUL和DIV各有一个操作数double the width of the other two。
您对这些问题的评论是错误的:
mul bl; al*bl = al
:不,AX = AL*BL
。div cx ; ax/cl ====> n/2x ===> p =ah and q = al
。如果您使用div cl
,那将是正确的,但DIV r / m16将DX:AX视为32位被除数,并以AX =商,DX =余数生成结果。查找MUL和DIV in the manual。
我强烈建议您在调试器中单步执行代码。和/或在调试器进入无限循环后在调试器中停止,并在观察寄存器时从那里单步执行。
x86标记wiki的底部有一些关于使用GDB调试asm的提示。 (例如,使用layout reg
)。由于您使用的是MASM,因此您可能正在使用内置调试器的Visual Studio。
使用什么调试器并不重要,但它是开发asm的必备工具。