2012-04-02 17 views
5

Sto usando NASM 16 BITS. Sto provando a fare un semplice codice assembly che stampa i numeri da 0 a 255 con intervallo di 1 secondo tra ciascun numero. Questo è quello che ho finora:Come visualizzare un numero sullo schermo e dormire per un secondo con l'assembly DOS x86?

[bits 16] 

mov ax,cs 
mov ds,ax 
mov cx,255 
mov ax,0 

myloop: 
    ;print in screen ax value 
    ;wait 1 second 
    inc ax 

loop myloop 

Non sono sicuro di come stampare il valore di ascia nella schermata, e come attendere 1 secondo (li mise in un commento nel codice).

+0

Stai facendo questo su un PC? –

+0

@PavanManjunath Sì, lo sto facendo su un PC. Windows 7, 32 bit. –

+0

Per la parte di ritardo, è possibile controllare l'ultimo post in [questo] (http://www.physicsforums.com/showthread.php?t=150424) thread. Si presume che l'orologio sia 100 MHz. Ma è necessario capire il valore esatto sulla tua macchina attraverso tentativi ed errori. [Questo] (http://www.programmersheaven.com/mb/x86_asm/272272/272273/re-sleep-function-/?S=B10000) link dovrebbe anche aiutarti a ottenere il ritardo giusto –

risposta

6

C'è un contatore di 4 byte nell'offset del segmento 0 46Ch (o in alternativa in 40 secondi, 6 canali disattivati) gestito e aggiornato dal BIOS del PC. È incrementato di 18,2 volte al secondo. Contando 18 cambiamenti nel byte più basso o una parola di questo contatore è probabilmente il modo più semplice di aspettare fuori di circa un secondo:

mov ax, 0 
mov ds, ax 
mov cx, 18 
mov bx, [46Ch] 
WaitForAnotherChange: 
NoChange: 
mov ax, [46Ch] 
cmp ax, bx 
je NoChange 
mov bx, ax 
loop WaitForAnotherChange 

Per stampare i numeri decimali è necessario per convertire i numeri binari in decimali, ottenere singole cifre e stamparle . Dividi il numero per 10 e raccogli i resti. es:

123:
123/10: quoziente 12, restante 3
12/10: quoziente 1, restante 2
1/10: quoziente 0, resto 1

Premendo ripetutamente dividendo per 10 ottieni le singole cifre nel resto nell'ordine inverso: 3,2,1. Poi li stampi usando la funzione int 2h 21 di DOS (carica 2 in AH, carica il codice ASCII del personaggio in DL, esegui int 21h).

Una variante alternativa, abbastanza adatta al tuo problema, sarebbe quella di utilizzare l'istruzione DAA per incrementare il numero direttamente in decimale senza alcuna conversione.

Ecco come tutto può essere fatto:

; file: counter.asm 
; assemble: nasm.exe counter.asm -f bin -o counter.com 

bits 16 
org 0x100 

    mov ax, 0 ; initial number 
    mov cx, 256 ; how many numbers 

NextNumber: 
%if 1 ; change to 0 to use the DAA-based method 
    push ax 

    mov dx, 0 
    div word [ten] 
    push dx 

    mov dx, 0 
    div word [ten] 
    push dx 

    mov dx, 0 
    div word [ten] 
    push dx 

    pop dx 
    call PrintDigit 
    pop dx 
    call PrintDigit 
    pop dx 
    call PrintDigit 

    pop ax 

    call PrintNewLine 
    call Wait1s 

    inc ax 
%else 
    mov dl, ah 
    call PrintDigit 

    mov dl, al 
    shr dl, 4 
    call PrintDigit 

    mov dl, al 
    and dl, 0Fh 
    call PrintDigit 

    call PrintNewLine 
    call Wait1s 

    add al, 1 
    daa 
    adc ah, 0 
%endif 

    loop NextNumber 
    ret 

PrintDigit: 
    pusha 
    mov ah, 2 
    add dl, '0' 
    int 21h 
    popa 
    ret 

PrintNewLine: 
    pusha 
    mov dx, CRLF 
    mov ah, 9 
    int 21h 
    popa 
    ret 

Wait1s: 
    pusha 
    push ds 

    mov ax, 0 
    mov ds, ax 

    mov cx, 18 
    mov bx, [46Ch] 
WaitForAnotherChange: 
NoChange: 
    mov ax, [46Ch] 
    cmp ax, bx 
    je NoChange 
    mov bx, ax 
    loop WaitForAnotherChange 

    pop ds 
    popa 
    ret 

ten dw 10 
CRLF db 13,10,"$" 

Se non vi piacciono gli zeri iniziali o l'ultimo ritardo di 1 secondo, è possibile condizionale li salta.

Scaricare i manuali della CPU Intel e/o AMD x86 che descrivono il funzionamento di ciascuna istruzione. Leggili. Inoltre, scarica Ralf Brown's Interrupt List, che descrive ogni funzione BIOS e DOS. Hai bisogno di sapere alcuni di loro per fare I/O. Ci sono anche HelpPC e TechHelp che descrivono convenientemente molte cose BIOS e DOS come lo BIOS Data Area dove vive il contatore sopra menzionato.

+0

Questo commento è per @Alex Funziona perfettamente, grazie mille per il tuo generoso aiuto. Mi assicurerò di leggere tutto ciò che hai detto nel commento sopra. Solo una domanda, è difficile modificare il codice che hai postato per far andare indietro il processo? (Da 255 a 0). –

+0

L'ho fatto, grazie ancora per il vostro aiuto @Alex –

+0

È semplice/facile sia nei casi basati su div sia nei casi basati su daa. –

Problemi correlati