Ответ 1
Там 4-байтовый счетчик в сегменте 0 смещения 46Ch (или, альтернативно, через 40h, offs 6Ch), поддерживаемый и обновляемый BIOS компьютера. Он увеличился на 18,2 раза в секунду. Подсчет 18 изменений в младшем байте или слове этого счетчика, вероятно, является самым простым способом ожидания примерно через секунду:
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
Чтобы напечатать десятичные числа, вам нужно преобразовать двоичные числа в десятичные числа, получить отдельные цифры и распечатать их. Вы делите число на 10 и собираете остатки. например:.
123:
123/10: коэффициент 12, остаток 3
12/10: коэффициент 1, остаток 2
1/10: коэффициент 0, остаток 1
Повторяя деление на 10, вы получаете отдельные цифры в остатках в обратном порядке: 3,2,1. Затем вы печатаете их с помощью функции DOS int 21h 2 (загрузка 2 в AH
, загрузите код символа ASCII в DL
, выполните int 21h
).
Альтернативным вариантом, вполне подходящим для вашей проблемы, было бы использовать инструкцию DAA
для увеличения числа непосредственно в десятичной форме без какого-либо преобразования.
Вот как все это можно сделать:
; 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,"$"
Если вам не нравятся начальные нули или последняя 1-секундная задержка, вы можете условно пропустить их.
Загрузите руководства Intel и/или AMD x86, в которых описывается, как работают каждая команда. Читай их. Также загрузите Ralf Brown Interrupt List
, в котором описываются все функции BIOS и DOS. Вы должны знать некоторые из них, чтобы делать I/O. Существуют также HelpPC
и TechHelp
, которые удобно описывают многие функции BIOS и DOS, такие как BIOS Data Area
, где живет вышеупомянутый счетчик.