Loops 汇编GCD编码无限循环

Loops 汇编GCD编码无限循环,loops,assembly,masm,irvine32,greatest-common-divisor,Loops,Assembly,Masm,Irvine32,Greatest Common Divisor,我试图制作一个汇编程序来查找GCD,输入两个整数,然后打印出GCD。代码汇编良好,但在提交两个整数后,程序陷入无限循环: ;Title - GCD INCLUDE Irvine32.inc .data strA BYTE "Enter an integer A: ",0 strB BYTE "Enter an integer B: ",0 temp DWORD ? finalStr BYTE "GCD of the two integers is: ",0 .code main

我试图制作一个汇编程序来查找GCD,输入两个整数,然后打印出GCD。代码汇编良好,但在提交两个整数后,程序陷入无限循环:

;Title - GCD

INCLUDE Irvine32.inc


.data

strA BYTE "Enter an integer A: ",0
strB BYTE "Enter an integer B: ",0
temp DWORD ?
finalStr BYTE "GCD of the two integers is: ",0



.code

main PROC

call Clrscr

mainLoop:
mov edx,OFFSET strA
call WriteString
call ReadInt
mov temp, eax
call Crlf

mov edx, OFFSET strB
call WriteString
call ReadInt        
mov ebx, eax
mov eax, temp
call Crlf

call GCD

mov edx, OFFSET finalStr
call WriteString
call WriteInt

call WaitMsg

jmp mainLoop

main ENDP

;-----------------------------------------------
abs PROC
; Computes the absolute value of a number.
; Receives: eax = the number
; Returns:  eax = absolute value of the number
;-----------------------------------------------
   cmp eax, 0                    ; see if we have a negative number
   jge done
   neg eax

done:
   ret
abs ENDP

;-----------------------------------------------
gcd PROC
; Finds Greatest Common Divisor of two integers
; Recieves: eax= int A , ebx = int B
; Returns eax = GCD
;-----------------------------------------------
call abs        ;takes absolute value of both registers
mov temp, eax
mov eax, ebx
call abs
mov eax, temp

cmp eax, ebx    ; making sure we divide the bigger number by the smaller
jz DONE     ; if numbers are equal, GCD is eax either way
jc SWITCH   ;swaps if ebx is larger then eax

mov edx, 0

SWITCH:         ;swaps values so eax is larger then ebx
mov temp, eax
mov eax, ebx
mov ebx, temp
mov edx, 0
jmp L1

L1:     ;divides until remainder is 0, then eax is GCD
div ebx
cmp edx, 0
jz DONE
mov eax, edx
jmp L1


DONE:
gcd ENDP

END main
我怎样才能摆脱这个循环?

我直接看到一个问题:

call abs        ;takes absolute value of both registers
mov  temp, eax
mov  eax, ebx
call abs
mov  eax, temp
abs
-ed
ebx
值移回
ebx
时没有任何内容,它应该是:

call abs        ;takes absolute value of both registers
mov  temp, eax
mov  eax, ebx
call abs
mov  ebx, eax
mov  eax, temp

另一个问题虽然与您的问题没有直接关系,但是
x86
体系结构长期以来一直有一条
xchg
指令,它将极大地清理您的代码,特别是
temp
的使用


想想这个顺序:

cmp eax, ebx    ; making sure we divide the bigger number by the smaller
jz DONE     ; if numbers are equal, GCD is eax either way
jc SWITCH   ;swaps if ebx is larger then eax

mov edx, 0

SWITCH:         ;swaps values so eax is larger then ebx
您会发现无论哪个值更大,
开关:
处的代码都将运行

您可以通过更改以下内容来解决此问题:

jc   SWITCH   ; swaps if ebx is larger then eax

mov  edx, 0
进入:


除此之外,我将建议您在头脑中实际运行该代码,以了解其工作原理,但更重要的是,如何像机器一样思考,从而成为一名更好的开发人员

从下表开始:

[temp]   eax      ebx      edx      <stack>
-------- -------- -------- -------- --------
?        ?        ?        ?        ?,
[temp]eax ebx edx
-------- -------- -------- -------- --------
?        ?        ?        ?        ?,
然后依次执行每一行,在数据更改时填充列

最终,您将了解问题的来源,并且您也将理解为什么有时候只有这种方式进行调试的老家伙在这方面做得更好:-)


我会给你一个线索。请特别关注
edx
,了解它是如何变化的,以及它可能会如何影响某些其他指令,如
div
,这可能取决于它是否为零。

谢谢!然而,我仍然被困在这个循环中。是的,@George,我仍然在研究:-)是的,我只是在发布后不久注意到,所以我在“mov-edx,0”行下面添加了“jmp-L1”,所以它跳过了切换,但我仍然得到了loop@George:见我最后的评论。请参阅代码。是代码:-)PROC
gcd
不会返回。在
DONE:
gcd ENDP
之间插入
ret
。不要忘记每次在
div
之前清除
EDX
。欧几里德算法的实现是错误的。
[temp]   eax      ebx      edx      <stack>
-------- -------- -------- -------- --------
?        ?        ?        ?        ?,