Domanda

Quando aggiungo due valori in assembly a 16 bit, qual è il modo migliore per stampare il risultato per console?

Al momento ho questo codice:

;;---CODE START---;;
mov ax, 1   ;put 1 into ax
add ax, 2   ; add 2 to ax current value
mov ah,2  ; 2 is the function number of output char in the DOS Services.
mov dl, ax ; DL takes the value.
int 21h    ; calls DOS Services

mov ah,4Ch   ; 4Ch is the function number for exit program in DOS Services.
int 21h      ; function 4Ch doesn't care about anything in the registers.
;;---CODE END---;;

Credo che il valore dl dovrebbe essere in codice ASCII, ma non sono sicuro come convertire il valore ascia dopo l'aggiunta in ASCII.

È stato utile?

Soluzione

Che, fondamentalmente, vogliono dividere per 10, stampare il resto (una cifra), e poi ripetere con il quoziente.

    ; assume number is in eax
    mov ecx, 10

loophere:
    mov edx, 0
    div ecx

    ; now eax <-- eax/10
    ;     edx <-- eax % 10

    ; print edx
    ; this is one digit, which we have to convert to ASCII
    ; the print routine uses edx and eax, so let's push eax
    ; onto the stack. we clear edx at the beginning of the
    ; loop anyway, so we don't care if we much around with it

    push eax

    ; convert dl to ascii
    add dl, '0'

    mov ah,2  ; 2 is the function number of output char in the DOS Services.
    int 21h    ; calls DOS Services

    ; now restore eax
    pop eax

    ; if eax is zero, we can quit

    cmp eax, 0
    jnz loophere

Come nota a margine, si dispone di un bug nel codice proprio qui:

mov ax, 1   ;put 1 into ax
add ax, 2   ; add 2 to ax current value
mov ah,2  ; 2 is the function number of output char in the DOS Services.
mov dl, ax ; DL takes the value.

Si mette in 2 ah, e poi lo metti in ax dl. Stai fondamentalmente junking ax prima di stamparlo.

Inoltre ha formato non corrisponde poiché dl è largo 8 bit e ax è a 16 bit.

Che cosa si dovrebbe fare è capovolgere le ultime due righe e fissare la mancata corrispondenza dimensione:

mov ax, 1   ;put 1 into ax
add ax, 2   ; add 2 to ax current value

mov dl, al ; DL takes the value.
mov ah,2  ; 2 is the function number of output char in the DOS Services.

Altri suggerimenti

Basta fissare l'ordine del @ Nathan Fellman s' codice

PrintNumber proc
    mov cx, 0
    mov bx, 10
@@loophere:
    mov dx, 0
    div bx                          ;divide by ten

    ; now ax <-- ax/10
    ;     dx <-- ax % 10

    ; print dx
    ; this is one digit, which we have to convert to ASCII
    ; the print routine uses dx and ax, so let's push ax
    ; onto the stack. we clear dx at the beginning of the
    ; loop anyway, so we don't care if we much around with it

    push ax
    add dl, '0'                     ;convert dl to ascii

    pop ax                          ;restore ax
    push dx                         ;digits are in reversed order, must use stack
    inc cx                          ;remember how many digits we pushed to stack
    cmp ax, 0                       ;if ax is zero, we can quit
jnz @@loophere

    ;cx is already set
    mov ah, 2                       ;2 is the function number of output char in the DOS Services.
@@loophere2:
    pop dx                          ;restore digits from last to first
    int 21h                         ;calls DOS Services
    loop @@loophere2

    ret
PrintNumber endp

L'algoritmo di base è:

divide number x by 10, giving quotient q and remainder r
emit r
if q is not zero, set x = q and repeat 

Si noti che questo produrrà le cifre nell'ordine inverso, quindi probabilmente stai andando a voler sostituire il passaggio "Emit" con qualcosa che memorizza ogni cifra, in modo da poter successivamente iterate in retromarcia nel corso degli cifre memorizzate.

Si noti inoltre che per convertire un numero binario tra 0 e 9 (decimale) per ascii, basta aggiungere il codice ASCII per '0' (che è 48) per il numero.

mov dl, ax

Questo non funzionerà come dl e ax hanno dimensioni differenti bit. Che cosa si vuole fare è creare un ciclo in cui si divide il valore a 16 bit da 10, ricorda il resto sullo stack, e poi continuare il ciclo con il risultato divisione intera. Quando si raggiunge un risultato di 0, ripulire la cifra per cifra pila, aggiungendo 48 alle cifre per trasformarli in cifre ASCII, quindi stamparli.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top