3

I've written a pretty simple code in asm x8086 and I'm facing an error. If anyone could help me with a brief explanation I would greatly appreciate it.

IDEAL
MODEL small
STACK 100h
DATASEG
; --------------------------
    array db 10h, 04h, 04h, 04h, 04h, 04h, 04h, 04h, 04h, 04h
    sum db 0
    ; --------------------------
CODESEG
start:
    mov ax, @data
    mov ds, ax
; --------------------------
    xor cx, cx
    mov al, 0
    mov bx, offset array
StartLoop:
    cmp cx, 10
    jge EndLoop
    add al, [bx]
    add [sum],al
    inc cx
    inc bx
    jmp StartLoop
EndLoop:
    mov ah, 09h
    int 21h

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

exit:
    mov ax, 4c00h
    int 21h
END start
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Dor George
  • 101
  • 1
  • 4
  • 9
  • 2
    Note that the line: add al, [bx] is actually mov al, [bx] – Dor George Nov 09 '16 at 09:09
  • I think a brief explanation is here: http://stackoverflow.com/help/how-to-ask (At the moment it's not clear what you are asking) Plus for assembly it always help to specify what is your target platform/OS to run the code, and what assembler you use to compile it (don't hesitate even to copy the command lines used, sometimes even that may help to resolve problems). – Ped7g Nov 09 '16 at 10:49
  • I mean, there are few people who will take a look on your source, and have the same environment, so they can just copy/paste it, compile and see your problem live. Most of people here will use their knowledge and experience to do a "dry run" in their head, and to make it easier for them, you should provide every relevant detail (just imagine yourself reading your question with zero knowledge about how your setup looks). – Ped7g Nov 09 '16 at 10:52

2 Answers2

3

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
Fifoernik
  • 9,779
  • 1
  • 21
  • 27
1

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 ...
Community
  • 1
  • 1
Ped7g
  • 16,236
  • 3
  • 26
  • 63
  • This would be simpler and more efficient if it just stored into the buffer directly and did `dec si` inside the div loop, instead of pushing onto the stack and popping in a separate loop. For printing with `int 21h`/`ah=9` you don't care where in the buffer your string starts, you just need a pointer to the start. – Peter Cordes Dec 17 '19 at 17:09