问题描述
我正在创建一个程序,该程序应在启动五秒钟后打印来自处理程序的Hello".首先,我通过名为create_interrupt
的proc创建了中断4ah.此中断导致int_handler
,它打印字符串"Hello from handler".然后proc"alarm"获得当前时间,将其增加5秒钟,并通过int 1ah的func 06h设置警报.
I'm creating a program, that should print "Hello from handler" five seconds after start. At first I created interrupt 4ah by proc called create_interrupt
.This interrupt causes int_handler
, that prints string "Hello from handler".Then proc "alarm" get curent time, add 5 second to it and set alarm by func 06h of int 1ah.
此警报应在启动5秒后致电int 4ah,但它不起作用,我也不知道为什么.如果我手动"调用4ah,只需添加"int 4ah"就可以了,这意味着中断已创建并且可以正常工作.但是我需要通过警报调用此中断.
This alarm should call int 4ah after 5 seconds from start, but it doesn't works and I don't know why. If I call 4ah "by hand", just by adding "int 4ah" it works, it means that interruption created and works correctly. But I need to call this interrupt by alarm.
SSEG segment stack
db 256 dup(0)
SSEG ends
DSEG segment
mess db 'Hello',0dh,0ah,'$'
mess2 db 'Hello from handler!',0dh,0ah,'$'
mess3 db 'Ассемблер это жопа, я уже устал''$'
DSEG ends
CSEG segment
assume cs:CSEG,ds:DSEG,ss:SSEG
begin:
mov ax, DSEG
mov ds,ax
mov ah,09h
mov dx,offset mess
int 21h
;call far ptr int_handler
call far ptr create_interrupt
;int 4ah
call far ptr alarm
mov ah,01h
int 21h
mov ah,4ch
int 21h
create_interrupt proc far
push 0
pop es
;pushf
;cli
mov word ptr es:[4ah*4],offset int_handler
mov word ptr es:[4ah*4+2],seg int_handler
;sei
iret
create_interrupt endp
alarm proc far
;pushf
mov ah,02h ;get current time
int 1ah
mov ah,06h
;mov ch,ch ;hour
;mov cl,cl ;min
;mov dh,dh ;sec
;mov dl,dl ;mlsec
add dh,05h ;add 5 to seconds
int 1ah ;ah=06h, so this int sets alarm
;mov ah,01h
;int 21h
iret
alarm endp
int_handler proc far
mov ax,DSEG ;
mov ds,ax ;in ds addres of Data segment
mov ah,09h
mov dx,offset mess2
int 21h
iret
int_handler endp
CSEG ends
end begin
推荐答案
DOSBox不提供对实时时钟的访问.
int 1Ah AH=06h
(BIOS.SetSystemAlarm)和int 21h AH=2Dh
(DOS.SetSystemTime)之类的功能无法正常运行!
为什么是这样?嗯,DOSBox是一个针对玩(现有)DOS游戏的模拟器.通常,游戏不设置(实时)时钟或使用实时时钟警报.游戏宁可处理各种延迟.这就解释了为什么DOSBox不支持这种功能.
尽管我们必须接受开发人员的选择,但如果他们向我们提供了记录错误的返回代码以表示错误,那就太好了.
DOSBox does not give access to the Real Time Clock.
Functions like int 1Ah AH=06h
(BIOS.SetSystemAlarm) and int 21h AH=2Dh
(DOS.SetSystemTime) don't operate correctly!
Why is this? Well, DOSBox is an emulator that targets playing (existing) DOS games.Typically games don't set the (real time) clock or use a real time clock alarm. Games rather deal with delays of all kinds. That explains why DOSBox does not support this kind of functionality.
Although we have to accept the developer's choice, it would have been nice if they had provided us with the documented return codes that signal an error.
-
int 1Ah AH=06h
(BIOS.SetSystemAlarm)最好返回CF=1
-
int 21h AH=2Dh
(DOS.SetSystemTime)最好返回AL=FFh
int 1Ah AH=06h
(BIOS.SetSystemAlarm) had better returnedCF=1
int 21h AH=2Dh
(DOS.SetSystemTime) had better returnedAL=FFh
为了创建一个打印"Hello from handler!"的程序,我们可以成功使用1Ch中断. 5秒的延迟将转换为91个计时器滴答,因为每秒大约有18.2个滴答.使用此1Ch中断时,链接到原始(上一个)处理程序非常重要,这样其他进程仍可以管理其业务.
In order to create a program that prints "Hello from handler!", we can succesfully use the 1Ch interrupt. A delay of 5 seconds would translate to 91 timer ticks because there're about 18.2 ticks in every second. When using this 1Ch interrupt it's very important to chain to the original (previous) handler so other processes can still manage their business.
以下是此任务的我的版本:
Below is my version of this task:
; 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,'$'
Michael Petch已完成.
Michael Petch made this valuable comment about DOS re-entrancy or the lack thereof.
我已经在DOSBox下测试了上面的程序,没有任何问题,因为引用了我的程序员手册,
I've tested the above program under DOSBox with no problems at all because, quoting from my programmer's manual,
上面的程序除了等待键盘输入外什么也不做,所以很好.在更复杂的程序中,可以同时检查InDOS标志并拦截int 28h
.
然而,一个简单的解决方案仍然是避免完全使用DOS,并使用例如来输出消息. BIOS.Teletype:
The above program does nothing but waiting for keyboard input so this is fine. In a more elaborate program one could both check the InDOS flag and intercept int 28h
.
However a simple solution remains to avoid using DOS altogether and output the message using e.g. 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
这篇关于如何使计时器工作?启动后5秒致电int 4ah的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!