DOSBox не предоставляет доступ к часам реального времени.
Такие функции, как int 1Ah AH=06h
(BIOS.SetSystemAlarm) и int 21h AH=2Dh
(DOS.SetSystemTime) работают неправильно!
Почемуэтот?Что ж, DOSBox - это эмулятор, предназначенный для игр (существующих) DOS.Обычно игры не устанавливают часы реального времени или не используют будильник часов реального времени.Игры скорее имеют дело с задержками всех видов.Это объясняет, почему DOSBox не поддерживает такую функциональность.
Хотя мы должны принять выбор разработчика, было бы неплохо, если бы они предоставили нам документированные коды возврата, которые сигнализируют об ошибке.
int 1Ah AH=06h
(BIOS.SetSystemAlarm) вернулось лучше CF=1
int 21h AH=2Dh
(DOS.SetSystemTime) лучше вернулось AL=FFh
К счастью, отметка таймераработает нормально.
Чтобы создать программу, которая печатает «Hello from handler!», мы можем успешно использовать прерывание 1Ch.Задержка в 5 секунд приведет к 91 такту таймера, потому что каждую секунду происходит около 18,2 такта.При использовании этого прерывания 1Ch очень важно подключиться к исходному (предыдущему) обработчику, чтобы другие процессы все еще могли управлять своим бизнесом.
Ниже моя версия этой задачи:
; Create .COM program. We'll have CS=DS=ES=SS.
org 256
; Show we're alive.
mov dx, Msg
mov ah, 09h
int 21h
; Hook the 1Ch interrupt.
xor ax, ax
mov es, ax
cli
mov ax, MyInt1C
xchg ax, [es:001Ch*4]
mov [Int1C+1], ax ; Patch the 'jmpf' instruction (offset)
mov ax, cs
xchg ax, [es:001Ch*4+2]
mov [Int1C+3], ax ; Patch the 'jmpf' instruction (segment)
sti
; Wait for a key. Bulk of the program happens in the DOS kernel!
mov ah, 01h
int 21h
; Restore the 1Ch interrupt.
cli
mov ax, [Int1C+1]
mov [es:001Ch*4], ax
mov ax, [Int1C+3]
mov [es:001Ch*4+2], ax
sti
; Terminate.
mov ax, 4C00h
int 21h
; -----------------------------------
MyInt1C:
cmp word [cs:TimeOut], 0 ; Zero disables this functionality
je Int1C
dec word [cs:TimeOut]
jnz Int1C ; Time not yet elapsed
push ds
push dx
push ax
push cs
pop ds
mov dx, Msg_
mov ah, 09h
int 21h
pop ax
pop dx
pop ds
Int1C:
jmpf 0:0 ; Chain to the original handler
; -----------------------------------
TimeOut dw 273 ; 15 seconds x 18.2 = 273 ticks
Msg db 'Sep says to wait 15 seconds...',13,10,'$'
Msg_ db '15 seconds have elapsed. Press any key.',13,10,'$'
Майкл Петч сделал этот ценный комментарий о повторном входе в DOS или его отсутствии.
Я тестировал вышеупомянутую программу в DOSBox без проблем, потому что, цитируя руководство моего программиста,
Когда DOS ожидает ввода с клавиатуры, он бездействует в цикле, читая символы по мере их поступленияin. Пока DOS ожидает в этот момент, можно использовать обработку файлов и другие функции, хотя флаг InDOS указывает иное.
Вышеупомянутая программа ничего не делает, кроме ожидания клавиатурывход, так что все в порядке.В более сложной программе можно как проверить флаг InDOS, так и перехватить int 28h
.
Однако остается простое решение - вообще не использовать DOS и выводить сообщение, например, с помощью BIOS.Teletype:
MyInt1C:
cmp word [cs:TimeOut], 0 ; Zero disables this functionality
je Int1C
dec word [cs:TimeOut]
jnz Int1C ; Time not yet elapsed
push ax
push bx
push si
mov bx, 0007h
mov si, Msg_
cld
jmps .b
.a: mov ah, 0Eh
int 10h
.b: lods byte [cs:si]
test al, al
jnz .a
pop si
pop bx
pop ax
Int1C:
jmpf 0:0 ; Chain to the original handler
; -----------------------------------
TimeOut dw 273 ; 15 seconds x 18.2 = 273 ticks
Msg db 'Sep says to wait 15 seconds...',13,10,'$'
Msg_ db '15 seconds have elapsed. Press any key.',13,10,0