Reputation: 24705
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
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