牛顿Raphson迭代问题

时间:2016-10-30 18:03:29

标签: function loops assembly infinite-loop masm

我在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

2 个答案:

答案 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

我强烈建议您在调试器中单步执行代码。和/或在调试器进入无限循环后在调试器中停止,并在观察寄存器时从那里单步执行。

标记wiki的底部有一些关于使用GDB调试asm的提示。 (例如,使用layout reg)。由于您使用的是MASM,因此您可能正在使用内置调试器的Visual Studio。

使用什么调试器并不重要,但它是开发asm的必备工具。