2015-10-11 1 views
-1

J'ai écrit un code d'assemblage pour additionner cinq nombres. La valeur finale est ensuite stockée dans la mémoire.Impression d'une valeur de mémoire à l'écran dans l'assemblage

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 

J'ai suivi l'exemple à partir de cette topic, mais il ne fonctionne pas dans EMU8086

+0

Vous devez d'abord convertir 'sum' en une chaîne ASCII. Regardez [cet exemple] (http://stackoverflow.com/a/23682807/3512216) – rkhb

+0

Voulez-vous afficher une valeur 32 bits? – rkhb

+0

J'ai mis à jour le post. Bien qu'il y ait quelques similitudes entre ma question et l'exemple, mais le mien est seulement un extrait qui est meilleur à suivre – mahmood

Répondre

3

This example vous montre comment convertir une valeur de mot dans AX à une chaîne et l'affiche. Vous voulez convertir une valeur DWORD en chaîne. Dans votre cas, vous pouvez utiliser l'avantage de DIV divisant un DWORD dans les registres DX: AX. Dans l'exemple DX est mis à 0, donc la première idée est de supprimer la ligne xor dx, dx. Mais vous avez besoin de DX juste pour la première fois, alors vous devez l'effacer, car il détient le reste après le DIV. L'astuce consiste à effectuer l'autorisation après la div à la place avant elle. Donc, il sera utilisé pour la première fois et effacé pour chaque répétition.

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 

Il y aura un problème avec DIV, si le résultat ne rentre pas dans le registre AX. Ensuite, vous obtenez une erreur de débordement.

+0

Une raison de préférer 'inc cl' (2 octets) à' inc cx' (1 octet)? –

+1

@mahmood S'il vous plaît noter que cette solution exellent est en fait un cas particulier où le dividende ne doit pas être supérieur à 655359. Avec vos 5 numéros (somme = 147879), il ne sera pas un problème, mais ne l'utilisez pas comme un général solution pour convertir un nombre de dword en texte. –

+0

@ user3144770: Vous avez raison. J'ai édité la réponse. – rkhb