arraysassemblyx86-16number-formattingemu8086

Array sum assembly Language code, new prompt line is moving leftward, answer is not printing and but prints former register value


I'm trying to write a simple assembly language code. It runs but is having slight issues.
The code is meant to accept five values and to store in an array, therefore it prompts the user five times. Whenever it prompts the user in a newline the printed prompts is shifted leftward to the previous line. In the end the last lines are cut out from view. Also the code is not printing my answer right, instead it prints the previous value in the register. Also the resulting value in the register is not correlating

TITLE ArraySumInput X (ArraySumInput.asm)
; A program calculating the sum of an array with user input
; Yemi 
; 8th December, 2023

org 100h
.DATA
array_size DW 5
array DW 5 DUP ?
sum DW ?

prompt_msg DB " Enter an integer: $" 
ans_msg DB "Answer is "
newline_msg DB 13, 10, "$" ; Newline characters for formatting

.CODE
main PROC
    ; Accept input for the array elements
    mov cx, array_size ; Set the loop counter to the array size
    lea si, array       ; Load the address of the array into si

input_loop:  
    mov ah, 09          ; DOS function to print a string
    lea dx, newline_msg   ; Load the address of the newline characters
    int 21h             ; DOS interrupt to invoke the function
    
    mov ah, 09          ; DOS function to print a string
    lea dx, prompt_msg  ; Load the address of the prompt message
    int 21h             ; DOS interrupt to invoke the function

    mov ah, 0Ah         ; DOS function to input a string
    lea dx, [si]        ; Load the address where the input will be stored
    int 21h             ; DOS interrupt to invoke the function

    ; Convert the input to a number
    mov ax, [si+2]      ; Move the ASCII digits to ax
    sub ax, '0'         ; Convert ASCII to integer
    mov [si], ax        ; Store the integer in the array element

    add si, 2           ; Move to the next element in the array (assuming 16-bit integers)
    loop input_loop     ; Repeat until cx (loop counter) is zero

    ; Calculate the sum of the array
    mov cx, array_size  ; Reset the loop counter
    lea si, array       ; Reset the address of the array into si

    ; Initialize sum to zero
    mov sum, 0

sum_loop:
    mov ax, [si]       ; Load the current array element to ax
    add sum, ax         ; Add the current array element to the sum
    add si, 2           ; Move to the next element in the array (assuming 16-bit integers)
    loop sum_loop       ; Repeat until cx (loop counter) is zero
    
    ; Print a newline
    mov ah, 09          ; DOS function to print a string
    lea dx, newline_msg ; Load the address of the newline characters
    int 21h             ; DOS interrupt to invoke the function

    ; Print the prompt message
    mov ah, 09          ; DOS function to print a string
    lea dx, ans_msg      ; Load the address of the answer message
    int 21h             ; DOS interrupt to invoke the function
    
    mov ah, 09          ; DOS function to print a string
    lea dx, sum         ; Load the address of the sum variable
    int 21h             ; DOS interrupt to invoke the function 
    
main ENDP
END main
ret

I have tried adding a code to print new line and also made the code add the value at the memory address pointed by SI to the sum but they're not working.
I am using an emu8086 emulator on an X64 architecture.


Solution

  • mov ah, 0Ah   ; DOS function to input a string
    lea dx, [si]  ; Load the address where the input will be stored
    int 21h       ; DOS interrupt to invoke the function
    

    You don't pass the DOS.BufferedInput function 0Ah the correct input structure. Full info about this in How buffered input works.
    Add next to your `.DATA. section:

    sum DW ?
    buf DB 3,0,0,0,0
    

    and invoke DOS in the following manner:

    mov  bx, buf
    mov  dx, bx
    mov  ah, 0Ah
    int  21h
    cmp  byte [bx+1], 2
    jne  input_loop
    
    ; Convert the input to a number
    mov ax, [si+2]      ; Move the ASCII digits to ax
    sub ax, '0'         ; Convert ASCII to integer
    mov [si], ax        ; Store the integer in the array element
    

    Trusting the user has input two decimal digits, this code only converts one of them into its value [0,9], moreover this code does not even start to combine the digits into the full number that they represent [0,99].

    mov  ax, [bx + 2]   ; Load the 2 decimal characters
    sub  ax, '00'       ; Convert both together (SWAR-style)
    xchg al, ah         ; Remember x86 is little-endian
    aad                 ; -> AX = AH * 10 + AL
    mov  [si], ax       ; Store in the array
    
    mov ah, 09          ; DOS function to print a string
    lea dx, sum         ; Load the address of the sum variable
    int 21h             ; DOS interrupt to invoke the function 
    

    The DOS.PrintString function 09h only prints strings of text characters (and a few control codes like 10 and 13). Read all about it in Displaying characters with DOS or BIOS. Since at sum is stored a binary number [0,495], you first need to convert it into a string of characters. In Displaying numbers with DOS you'll find everything there is to know about this conversion.


    Tip 1: You can easily do the summing within the input_loop. Then you don't need a separate loop for that. Add a line like:

    mov  [si], ax       ; Store in the array
    add  sum, ax
    

    Tip 2: You can improve displaying the result.

    ans_msg DB "Answer is "
    newline_msg DB 13, 10, "$"
    

    In ans_msg that final space character tells me that you really would like to see the result on the same line. Because there is no $ character, the newline_msg that follows gets appended. Better write:

    ans_msg     DB "Answer is $"
    newline_msg DB 13, 10, "$"