mahmood
mahmood

Reputation: 24705

printing a memory value on the screen in assembly

I wrote an assembly code to sum five numbers. The final value is then stored in the memory.

dtseg    segment
data     dw       27345,28521,29533,30105,32375
sum      dw       ?  
MSG1     DB "The sum is : $"  
dtseg    ends
;---------------------
cdseg    segment
main     proc     far
     assume   cs:cdseg,ds:dtseg,ss:stseg
     mov      ax,dtseg
     mov      ds,ax
     clc                       ; clear the carry
     mov      si,offset data   ; first location of data
     mov      cx,04            ; setting the counter
     mov      ax,0             ; clear ax
     mov      bx,ax            ; clear bx
back:add      ax,[si]          ; the first round: 0+27345
     adc      bx,0             ; if there is a carry, add that to bx
     inc      si               ; two inc because traversing words
     inc      si
     dec      cx               ; count down
     jnz      back             ; do that for other numbers
     mov      sum,ax           ; the final value
     mov      sum+2,bx         ; the carries are stored in bx

     lea      dx,MSG1          ; trying to display the result
     mov      ah,09h
     int      21h  
     mov      ah, 4cH          ; return to DOS
     int      21h
main     endp
cdseg    ends  
         end      main

I followed the example based on this topic, however it doesn't work in emu8086

Upvotes: 0

Views: 4177

Answers (1)

rkhb
rkhb

Reputation: 14399

This example shows you how to convert a WORD value in AX to a string and output it. You want to convert a DWORD value to a string. In your case you can use the advantage of DIV dividing a DWORD in the registers DX:AX. In the example DX is set to 0, so the first idea is to remove the line xor dx, dx. But you need DX just for the first time, then you must clear it, because it holds the remainder after the DIV. The trick is to perform the clearance after the div instead before it. So it will be used for the first time and cleared for every repetition.

dtseg    segment
data     dw 27345,28521,29533,30105,32375   ; Sum: 147879

sum      dw  ?, ?               ; two WORD = one DWORD
MSG1     DB "The sum is : $"
DECIMAL  db "0000000000$"       ; space for the result
dtseg    ends
;---------------------
cdseg    segment
main     proc     far
     assume   cs:cdseg,ds:dtseg,ss:stseg
     mov      ax,dtseg
     mov      ds,ax
     clc                       ; clear the carry

     mov      si,offset data   ; first location of data
     mov      cx,5             ; setting the counter
     mov      ax,0             ; clear ax
     mov      bx,ax            ; clear bx
back:add      ax,[si]          ; the first round: 0+27345
     adc      bx,0             ; if there is a carry, add that to bx
     inc      si               ; two inc because traversing words
     inc      si
     dec      cx               ; count down
     jnz      back             ; do that for other numbers

     mov      sum,ax           ; the final value
     mov      sum+2,bx         ; the carries are stored in bx

     call mem_to_dec

     lea      dx,MSG1          ; trying to display the result
     mov      ah,09h
     int      21h
     lea      dx,DECIMAL          ; trying to display the result
     mov      ah,09h
     int      21h

     mov      ah, 4cH          ; return to DOS
     int      21h
main     endp

mem_to_dec proc
    mov ax, [sum]
    mov dx, [sum+2]

    mov bx, 10                  ; divisor
    xor cx, cx                  ; CX=0 (number of digits)

    @First_Loop:
        div bx                  ; DX:AX / BX = AX remainder: DX
        push dx                 ; LIFO
        inc cx                  ; increment number of digits
        xor dx, dx              ; Clear DX for the next DIV
        test  ax, ax            ; AX = 0?
        jnz @First_Loop         ; no: once more

        mov di, OFFSET DECIMAL  ; target string DECIMAL
    @Second_Loop:
        pop ax                  ; get back pushed digit
        or ax, 00110000b        ; to ASCII
        mov byte ptr [di], al   ; save AL
        inc di                  ; DI points to next character in string DECIMAL
        loop @Second_Loop       ; until there are no digits left

        mov byte ptr [di], '$'  ; End-of-string delimiter for INT 21 / FN 09h
        ret
mem_to_dec endp

cdseg    ends
         end      main

There will be an issue with DIV, if the result don't fit into the AX register. Then you get an overflow error.

Upvotes: 3

Related Questions