Reputation: 19
EDIT: the code now runs,thanks for the assistance. it may not be pretty but it works
I have to write a program that finds the GCD of two numbers, the prompt reads like this. "You are to write a program containing a function which will evaluate the Greatest Common Divisor function using Euclid’s algorithm, defined as follows:
GCD(a,0) = a
GCD(a,b) = GCD(b, a mod b) for b > 0
Your function is to compute GCD(a,b) recursively and return the value in ax. Input to the function should be accomplished by pushing the values of a and b on the stack.
Your main program will:
print a program description on the screen display a prompt on the screen accept values for a and b from the keyboard (Use the DEC_IN procedure you wrote previously.) pass the values of a and b to the function print out the value of GCD(a,b) with an appropriate prompt (Use the DEC_OUT procedure you wrote previously.) Ask the user if he wishes to repeat the process." I believe I have accomplished most of the objectives but when run my program just freezes after entering the second integer. any help would be greatly appreciated here is my code:
; program to calculate gcd of two inputs
org 100h
section .data
prompt0: db "This is a program to caculate the GCD of two inputs $"
prompt1: db "Please enter integer X: $"
prompt2: db "Please enter integer Y: $"
prompt3: db "The GCD is: $"
intX dw 0
intY dw 0
gcd dw 0
section .text
mov ah,9 ; print prompt
mov dx,prompt0
int 21h
mov ah,9 ; print prompt
mov dx,prompt1
int 21h
call dec_in ; read value into bx
mov [intX], bx
mov ah,9 ; print prompt
mov dx,prompt2
int 21h
call dec_in ; read value into bx
mov [intY], bx
call calc_GCD
mov bx, [gcd]
mov ah,9 ; print output label
mov dx,prompt3
int 21h
call dec_out ; display the value in bx (gcd)
dec_in:
; save registers
push ax
push dx
xor bx,bx ; bx holds accumulated input
mov ah,1 ; read char fcn
int 21h ; read it into al
while1:
cmp al,0Dh ; char = CR?
je finis ; if so, we are done
push ax ; save the character read
mov ax,10 ; set up for multiply
mul bx ; dx:ax <- bx * 10
mov bx,ax ; put 16-bit result back in bx (assume no overflow)
pop ax ; restore the char read
and ax,000Fh ; convert character '0'-'9' to value 0-9
add bx,ax ; add value to accumulated input
mov ah,1 ; read char fcn
int 21h ; read next char into al
jmp while1 ; loop until done
finis:
; restore registers
pop dx
pop ax
ret
dec_out:
; save registers we will be using
push ax
push bx
push cx
push dx
xor cx,cx ; cx counts digits, initially zero
rept:
mov ax,bx ; set up to divide by by 10
xor dx,dx ; must have a 32 bit (unsigned) dividend
mov bx,10 ; divisor will be in bx
div bx ; quotient will be in ax, remainder in dx
push dx ; push remainder on stack
inc cx ; we generated another digit, so count it
mov bx,ax ; the quotient goes back in bx
cmp ax,0 ; clever way to test if quotient is zero
jne rept ; if not, generate next digit
mov ah,2 ; display character function
for2: ; loop cx times
pop dx ; pop digit to print
or dl,30h ; convert the digit to print to ASCII code
int 21h ; display the character
loop for2 ; and keep going until all digits displayed
; restore registers
pop dx
pop cx
pop bx
pop ax
ret
calc_GCD:
mov ax, [intY]
cmp ax, 0
jne chk_swap ; check if swap is needed
mov ax, [intX]
mov [gcd], ax ; move result into gcd
ret
chk_swap:
mov ax, [intX] ;store
mov bx, [intY]
cmp ax, bx
jl swap
jnl loop
swap:
mov ax, [intX]
mov bx, [intY]
;temp
mov cx, [intY]
; intY = intX
; intX = temp
mov bx, ax
mov ax, cx
mov [intX], ax
mov [intY], bx
jmp loop
loop:
mov dx, [intX]
shr dx, 16
mov ax, [intX]
mov bx, [intY]
div bx
mov di, [intX]
mov si, [intY]
mov di, si
mov [intX], di
mov [intY], dx
jmp calc_GCD
Upvotes: 1
Views: 10963
Reputation: 28921
There's no need to swap for GCD. If the divisor is greater than the dividend, the quotient is zero and the remainder is the dividend, so the first step of GCD will do the swap automatically if it's needed.
There's no need to keep storing the intermediate results into intX and intY. Just use registers to calculate the GCD until you get a remainder of 0, then the previous remainder is the GCD.
; ;ax, bx contain the two numbers
gcd0: xor dx,dx ;divide
div bx
mov ax,bx ;ax = new dividend = old divisor
mov bx,dx ;bx = new remainder
test bx,bx ;loop if remainder != 0
jnz gcd0
; ;ax = gcd
maximum number of loops is Fibonacci numbers: 46368, 28657, gcd = 1
Upvotes: 2