I need help with using SHR to divide by 2. My code seems to add the results together rather than display them individually. Even numbered values enter code label D2 and should continue to divide by 2 if they are even. Here's the code.
TITLE Message (prog.asm)
;*********************************************************************
;
;
;
;
; Program Description:
;
;*********************************************************************
INCLUDE Irvine16.inc
.DATA
openMsg DB 'Program 2', 0dh, 0ah
DB 'Title: Hailstone ', 0dh, 0ah
DB 'File: progl.asm', 0dh, 0ah
DB 'Date ', 0dh, 0ah
DB 'Author: ', 0dh, 0ah, 0
start BYTE 'Enter a seed (1 to 130): ', 0
range BYTE 'The seed is out of range', 0
again BYTE 'Would you like to generate another sequence? (Y/N)', 0
theEnd BYTE 'The End', 0
multiply BYTE 'multiply by 3 and add 1',0
divide BYTE 'DIVIDE', 0
answer BYTE 'Y', 0
seed BYTE 0, 0
captMsg DB 'Hailstone Program', 0dh, 0ah, 0ah, 0
.CODE
main PROC
mov ax, @data ; start
mov ds, ax ;put start of data segment into ds
mov dx, OFFSET openMsg ;point to opening message
call WriteString ;use library routine to display message
mov dx, OFFSET captMsg ;point to capture message
call WriteString ;use library routine to display message
L2: mov dx, OFFSET start ;ask user to input the seed
call WriteString ;display the question on the screen
call ReadHex ;read the seed input
mov seed, al ;stored value in seed variable
cmp seed, 1 ;see if seed = 1
je TE ;end the program
cmp seed, 0 ;see if input is <= 0
jbe Ran ;display 'Out of Range' and ask for another seed
cmp seed, 131 ;see if input is >= 131
jae Ran ;display 'Out of Range' and ask for another seed
and al, 1 ;determine if the input value is even or odd
jz D2 ;if input value is even then jump to D2
jnz M3 ;if input value is odd then jump to M3
Ran: call Crlf ;line break
mov dx, OFFSET range ;call the range value
call WriteString ;display 'Out of range' message
call Crlf ;line break
jmp L2 ;jump to prompt for a new seed
D2: mov al, seed ;move the seed value into the lower half of ax
shr al, 1 ;shift al once to divide by 2
mov seed, al ;move al back to the seed variable
call Crlf ;line break
mov dx, OFFSET seed ;call the seed value
call WriteDec ;write the seed value to the screen
call Crlf ;line break
test seed, 1 ;
jz D2 ;
cmp seed, 1 ;compare the seed to 1
je TE ;jump to the end if seed = 1
call Crlf ;line break
mov dx, OFFSET again ;call the again string question
call WriteString ;ask if they would like to do it again
call ReadChar ;read the users input
mov bl, al ;move the input into the lower half of bx
cmp bl, answer ;compare the answer give to 'Y'
call Crlf ;line break
call Crlf ;line break
je L2 ;if answer and bl are = then jump to L2 to start again
je TE ;if answer is not = to bl then jump to the end
M3: call Crlf ;
mov dx, OFFSET multiply ;
call WriteString ;
jmp TE ;
TE: call Crlf ;
mov dx, OFFSET theEnd ;
call WriteString ;
call Crlf ;calls a new line
exit ;exit the program
main ENDP ;assembler directive for end of the main
END main ;assembler directive for end of the
I don't think your problem is with the SHR instruction; it will correctly divide the value in AL by two, and as long as the value is even, no remainder will be lost.
Some problems I see:
This sequence would depend on Crlf preserving the flags (not likely), and the second JE can never execute. You are not otherwise using the value in BL, so it would be more efficient to just compare AL directly.
mov bl, al ;move the input into the lower half of bx
cmp bl, answer ;compare the answer give to 'Y'
call Crlf ;line break
call Crlf ;line break
je L2 ;if answer and bl are = then jump to L2 to start again
je TE ;if answer is not = to bl then jump to the end
And an inefficiency:
You are not otherwise using the value in AL, so it would be more efficient to just shift the variable directly.
D2: mov al, seed ;move the seed value into the lower half of ax
shr al, 1 ;shift al once to divide by 2
mov seed, al ;move al back to the seed variable
This would be a great problem to solve using your debugger, even if it's just DEBUG. You can trace through your code while looking at your listing. (You might have to turn the listing on.) You'd immediately see that the code doesn't send you where you think it should.