Istnieje 4-bajtowy licznik w segmencie 0 przesunięcie 46Ch (lub alternatywnie w seg 40h, offs 6Ch) jest utrzymywany i aktualizowany przez system BIOS komputera. Zwiększa się o 18,2 razy na sekundę. Licząc 18 zmian w najniższym bajt lub słowo z tego licznika jest prawdopodobnie najprostszym sposobem czeka się około jednej sekundy:
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
Aby wydrukować liczb dziesiętnych potrzebne do konwersji liczb binarnych na przecinku, dostać poszczególne cyfry i wydrukować je . Dzielicie liczbę przez 10 i zbierajcie resztki. np
123:
123/10: iloraz 12, reszta 3
12/10: iloraz 1, reszta 2
1/10: iloraz 0, reszta 1
poprzez dzielenie przez 10 otrzymasz poszczególne cyfry w reszcie w odwrotnej kolejności: 3,2,1. Następnie drukujesz je za pomocą funkcji DOS int 21h 2 (załaduj 2 do AH
, załaduj kod ASCII postaci do DL
, wykonaj int 21h
).
Alternatywnym wariantem, całkowicie odpowiadającym Twojemu problemowi, byłoby użycie instrukcji DAA
w celu zwiększenia liczby bezpośrednio w systemie dziesiętnym bez jakiejkolwiek konwersji.
Oto jak to wszystko może być wykonane:
; 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,"$"
Jeśli nie lubią zer lub ostatni 1-sekundowe opóźnienie, można je pominąć warunkowo.
Pobierz instrukcje procesora Intel i/lub AMD x86, które opisują działanie każdej instrukcji. Przeczytaj je. Pobierz także Ralf Brown's Interrupt List
, który opisuje każdą funkcję BIOS i DOS. Musisz znać niektóre z nich, aby wykonać I/O. Istnieją również HelpPC
i TechHelp
, które wygodnie opisują wiele rzeczy z BIOS-u i DOS, takich jak BIOS Data Area
, gdzie wspomniany wcześniej licznik żyje.
Czy robisz to na komputerze? –
@PavanManjunath Tak, robię to na PC. Windows 7, 32 bity. –
W części dotyczącej opóźnienia można sprawdzić ostatni wpis w wątku [this] (http://www.physicsforums.com/showthread.php?t=150424). Zakłada się, że zegar wynosi 100 MHz. Ale musisz wypróbować dokładną wartość na swoim komputerze za pomocą prób i błędów. [This] (http://www.programmersheaven.com/mb/x86_asm/272272/272273/re-sleep-function-/?S=B10000) link powinien również pomóc w uzyskaniu opóźnienia w prawo –