Newtons Raphson 迭代问题
Posted
技术标签:
【中文标题】Newtons Raphson 迭代问题【英文标题】:Newtons Raphson Iteration issues 【发布时间】:2016-10-30 18:03:28 【问题描述】:我正在 MASM X8086-32 位程序集中编写一个 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
【问题讨论】:
【参考方案1】:这个:
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
两者之间的任何按键都会使您的代码进入无限循环。
关于输出的提示:在打印之前将 48 添加到 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 ====> n/2x ===> p =ah 和 q = al。如果你使用了 div cl
那就对了
【讨论】:
谢谢。改变了,因为你的权利,但没有修复无限循环。 我进一步查看了您的代码,发现它为什么会永远循环 :) 更新了答案 所以我更新了条件语句,但仍然出现无限循环,或者我的用户输入未正确存储。我从接受的字符中减去了 30h? 也许我应该尝试将我的 y 值推入堆栈,然后在下一个循环中检索最后一个?这样我就不会通过尝试在下一次迭代之前将正确的值存储在寄存器中来使函数复杂化?【参考方案2】:我不确定您是否正确理解 MUL 和 DIV 各有一个操作数 double the width of the other two。
你在这些线上的 cmets 是错误的:
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=quotient, DX=remainder 的结果。
查找 MUL 和 DIV in the manual。
我强烈建议您在调试器中单步执行您的代码。和/或在进入无限循环后在调试器中停止它,并在观察寄存器时从那里单步执行。
x86 标签 wiki 底部有一些使用 GDB 调试 asm 的技巧。 (例如使用layout reg
)。由于您使用的是 MASM,因此您可能使用的是内置调试器的 Visual Studio。
使用什么调试器并不重要,但它是开发 asm 的必备工具。
【讨论】:
哦。我第一次读到关于 asm 的调试器。我一个都没用过! xD 哦,天哪! xD。是的,它是必不可少的工具。我希望我很久以前就想到了……以上是关于Newtons Raphson 迭代问题的主要内容,如果未能解决你的问题,请参考以下文章