Assembly 8086 | Sum of an array, printing multi-digit numbers

Solution 1:

With the correction for the add to be replaced by mov as noted in your comment (Note that the line: add al, [bx] is actually mov al, [bx]) there's just the function call at the label EndLoop that's wrong!

You want to display the sum, and are using the DOS print function. This function 09h expects a pointer in DS:DX that you are not providing!
Even if you did, you would still have to convert the sum number in its text representation.

A quick solution here would be to content yourself and just display the result in the form of a single ASCII character. The hardcoded sum is 52 and so it is a displayable character:

EndLoop:
    mov dl, [sum]
    mov ah, 02h    ;Single character output
    int 21h

; --------------------------

exit:
    mov ax, 4c00h
    int 21h

One step further and we can display "52":

mov al,[sum]
mov ah,0
mov dl,10
div dl        ---> AL=5   AH=2
add ax,3030h  ---> AL="5" AH="2"
mov dh,ah     ;preserve AH
mov dl,al
mov ah,02h
int 21h
mov dl,dh     ;restore
int 21h

Solution 2:

I don't see any error at all, the code will sum the array, display some random sh*t, and exit.

You probably want to display result of sum?

int 21h, ah=9 will display '$' terminated string from memory pointed to by dx.

So you need two things, convert the number in [sum] to string terminated by'$' at end, and then set dx to the converted string ahead of that int 21h.

You may try to extract number2string procedure from here: https://stackoverflow.com/a/29826819/4271923

I would personally change it to take the address of target buffer in si as another call argument (ie. just remove the mov si,offset str from the procedure body). Like this:

PROC number2string
  ; arguments:
  ;  ax = unsigned number to convert
  ;  si = pointer to string buffer (must have 6+ bytes)
  ; modifies: ax, bx, cx, dx, si
    mov  bx, 10  ; radix 10 (decimal number formatting)
    xor  cx, cx  ; counter of extracted digits set to zero
number2string_divide_by_radix:
  ; calculate single digit
    xor  dx, dx  ; dx = 0 (dx:ax = 32b number to divide)
    div  bx      ; divide dx:ax by radix, remainder will be in dx
  ; store the remainder in stack
    push dx
    inc  cx
  ; loop till number is zero
    test ax, ax
    jnz  number2string_divide_by_radix
  ; now convert stored digits in stack into string
number2string_write_string:
    pop  dx
    add  dl, '0' ; convert 0-9 value into '0'-'9' ASCII character encoding
  ; store character at end of string
    mov  [si], dl
    inc  si
  ; loop till all digits are written
    dec  cx
    jnz  number2string_write_string
  ; store '$' terminator at end
    mov  BYTE PTR [si],'$'
    ret
ENDP

Then to call this at your EndLoop you need to add into data segment numberStr DB 8 DUP (0) to have some memory buffer allocated for string and add into code:

    ; load sum as 16b unsigned value into ax
      xor  ax,ax      ; ax = 0
      mov  al,[sum]   ; ax = sum (16b zero extended)
    ; convert it to string
      mov  si,OFFSET numberStr
      call number2string
    ; display the '$' terminated string
      mov  dx,OFFSET numberStr
      mov  ah,9
      int  21h
    ; ... exit ...