Hi,
I'm transitioning to assembly, starting with processor 8086.
The attached code is Masm 5 compatible and is a step up from Hello World, which linked and ran okay.
An endless loop exists, giving credence to this note.
Any comments or suggestions to resolve it would be appreciated, thanks!
.model small
.stack 100h
.data
name_prompt db 'Enter your first name: $'
user_input db 11, 0 ; Buffer for user's name (up to 10 characters + 1 null terminator)
range_prompt db 'Enter the range of numbers (e.g., 0 to 10): $'
range_input db 5, 0 ; Buffer for user's range input (up to 4 characters + 1 null terminator)
lower_bound dw 0 ; Lower bound of the range
upper_bound dw 0 ; Upper bound of the range
operand1 dw 0 ; First operand for flash card
operand2 dw 0 ; Second operand for flash card
correct_answer dw 0 ; Correct answer for flash card
user_answer db 0 ; User's answer for flash card
correct_count db 0 ; Counter for correct answers
flash_card_prompt db 'Flash Card: $'
correct_msg db 'Correct!', 0Dh, 0Ah, '$'
incorrect_msg db 'Incorrect!', 0Dh, 0Ah, '$'
result_prompt db 'Number of Correct Answers: $'
hello_msg db 'Hello World',0Dh, 0Ah, '$'
debug_msg db 'Debug: ', 0
debug_end_msg db 'Debug: End of Execution', 0
.code
print_number proc
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
; Display a number
mov bx, 10 ; Set divisor to 10
print_digit:
xor dx, dx ; Clear any previous remainder
div bx ; Divide AX by 10, result in AX, remainder in DX
push dx ; Push the remainder onto the stack
inc dl ; Convert the remainder to ASCII
add dl, '0'
mov ah, 02h ; DOS print character function
int 21h ; Call DOS interrupt
pop dx ; Pop the remainder from the stack
cmp ax, 0 ; Check if quotient is zero
jnz print_digit ; If not, continue the loop
ret
print_number endp
generate_random_number proc
; Seed the random number generator
mov ah, 2Ch ; DOS get system time function
int 21h ; Call DOS interrupt
xor ah, ah ; Clear AH
mov cx, dx ; Use CX as the seed for the random number generator
; Generate a random number in the range [lower_bound, upper_bound]
mov ax, cx ; Use AX to store the random number
sub ax, [lower_bound]
inc ax
; Move the upper_bound value into a register (BX)
mov bx, [upper_bound]
xor dx, dx
div bx ; Divide AX by BX, result in AX, remainder in DX
add ax, [lower_bound]
ret
generate_random_number endp
clear_keyboard_buffer proc
; Clear the keyboard buffer
mov ah, 0Ch ; DOS flush keyboard buffer function
int 21h ; Call DOS interrupt
ret
clear_keyboard_buffer endp
main proc
mov ax, @data
mov ds, ax
mov es, ax
mov ss, ax
; Display prompt for user's name
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
mov ah, 09h ; DOS print string function
mov dx, offset name_prompt ; Offset of the message
int 21h ; Call DOS interrupt
; Read user's first name
mov ah, 0Ah ; DOS buffered input function
lea dx, user_input ; DX points to the buffer for input
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
int 21h ; Call DOS interrupt
; Clear the keyboard buffer
call clear_keyboard_buffer
; Display prompt for the range of numbers
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
mov ah, 09h ; DOS print string function
mov dx, offset range_prompt ; Offset of the message
int 21h ; Call DOS interrupt
; Read lower bound of the range
mov ah, 0Ah ; DOS buffered input function
lea dx, range_input ; DX points to the buffer for input
int 21h ; Call DOS interrupt
; Convert ASCII input to integer (lower bound)
mov al, [range_input + 2] ; ASCII character
sub al, '0' ; Convert ASCII to integer
mov bl, 10 ; Multiplier for tens place
mul bl ; Multiply AL by BL, result in AX
mov [lower_bound], ax ; Store the result
; Debug print for lower bound
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
mov ah, 09h ; DOS print string function
mov dx, offset range_prompt ; Prompt for debug print
int 21h ; Call DOS interrupt
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
mov ax, [lower_bound] ; Load lower_bound into AX
call print_number ; Display the lower bound
mov ah, 09h ; DOS print string function
mov dx, offset debug_msg ; Debug message
int 21h ; Call DOS interrupt
; Read upper bound of the range
mov ah, 0Ah ; DOS buffered input function
lea dx, range_input ; DX points to the buffer for input
int 21h ; Call DOS interrupt
; Convert ASCII input to integer (upper bound)
mov al, [range_input + 3] ; ASCII character for tens place
sub al, '0'
mov bl, 10
mul bl ; Multiply AL by BL, result in AX
mov bh, 0 ; Clear BH
mov bl, [range_input + 2] ; ASCII character for units place
sub bl, '0' ; Convert ASCII to integer
add ax, bx ; Add to result (upper bound)
mov [upper_bound], ax ; Store the result
; Debug print for upper bound
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
mov ah, 09h ; DOS print string function
mov dx, offset range_prompt ; Prompt for debug print
int 21h ; Call DOS interrupt
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
mov ax, [upper_bound] ; Load upper_bound into AX
call print_number ; Display the upper bound
mov ah, 09h ; DOS print string function
mov dx, offset debug_msg ; Debug message
int 21h ; Call DOS interrupt
; Preserve dx before calling generate_random_number
push dx
; Generate random numbers in the specified range
call generate_random_number ; Call the generate_random_number procedure
mov [operand1], ax
call generate_random_number ; Call the generate_random_number procedure
mov [operand2], ax
; Restore dx after generate_random_number
pop dx
; Generate and display flash cards
mov cx, 10 ; Number of flash cards
flash_cards_loop:
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
; Add debug print to check loop iteration
mov ah, 09h ; DOS print string function
mov dx, offset debug_msg
int 21h ; Call DOS interrupt
mov ax, cx
call print_number ; Display loop iteration number
; Generate random numbers in the specified range
call generate_random_number ; Call the generate_random_number procedure
mov [operand1], ax
call generate_random_number ; Call the generate_random_number procedure
mov [operand2], ax
; Display flash card
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
mov ah, 09h ; DOS print string function
mov dx, offset flash_card_prompt
int 21h ; Call DOS interrupt
; Display the first operand
mov ax, [operand1]
call print_number ; Display the operand
; Display operator (+ or -)
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
mov ah, 02h ; DOS print character function
mov dl, '+'
int 21h ; Call DOS interrupt
; Display the second operand
mov ax, [operand2]
call print_number ; Display the operand
; Display equals sign
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
mov ah, 02h ; DOS print character function
mov dl, '='
int 21h ; Call DOS interrupt
; Display the second operand
mov ax, [operand2]
call print_number;Display operand A2102 SYMBOL NOT DEFINED
; Display equals sign
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
mov ah, 02h ; DOS print character function
mov dl, '='
int 21h ; Call DOS interrupt
; Read user's answer
mov ah, 01h ; DOS input character function
int 21h ; Call DOS interrupt
sub al, '0' ; Convert ASCII to integer
mov bh, 0 ; Clear BH
mov bX, [correct_answer];Load correct_answer into BL A2048 OP.MUST BE SAME SIZE
; Calculate the correct answer
add bl, bh ; Clear high bits of BL
cmp al, bl ; Compare AL with BL
je correct_answer_handler ; Jump if equal
; Display incorrect message
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
mov ah, 09h ; DOS print string function
mov dx, offset incorrect_msg
int 21h ; Call DOS interrupt
jmp next_flash_card ; Jump to the next flash card
correct_answer_handler:
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
; Add debug print to check correct answer handling
mov ah, 09h ; DOS print string function
mov dx, offset debug_msg
int 21h ; Call DOS interrupt
mov dx, [correct_answer]
call print_number ; Display correct answer
; Display correct message
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
mov ah, 09h ; DOS print string function
mov dx, offset correct_msg
int 21h ; Call DOS interrupt
; Increment correct answer count
mov al, [correct_count] ; Load the byte value into AL
inc al ; Increment AL
mov [correct_count], al ; Store the result back in memory
next_flash_card:
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
; Add debug print to check loop termination
mov ah, 09h ; DOS print string function
mov dx, offset debug_msg
int 21h ; Call DOS interrupt
; Move to the next flash card
dec cx ; Decrement the loop counter
jnz flash_cards_loop ; Jump if not zero
; Display the number of correct answers
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
mov ah, 09h ; DOS print string function
mov dx, offset result_prompt
int 21h ; Call DOS interrupt
; Display the number of correct answers
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
mov ah, 02h ; DOS print character function
mov dl, [correct_count]
add dl, '0'
int 21h ; Call DOS interrupt
; Exit program
mov ah, 4Ch ; DOS exit function
int 21h ; Call DOS interrupt
main endp
END main
.text
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
mov ah, 09h ; DOS print string function
mov dx, offset hello_msg
int 21h ; Call DOS interrupt
mov ah, 09h ; DOS print string function
; Set DS to point to the data segment
mov ax, @data
mov ds, ax
mov dx, offset debug_end_msg ; Debug message
int 21h ; Call DOS interrupt
mov ah, 4Ch ; DOS exit function
int 21h ; Call DOS interrupt