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.
Stai facendo questo su un PC? –
@PavanManjunath Sì, lo sto facendo su un PC. Windows 7, 32 bit. –
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 –