Assembly 如何使定时器工作?启动后5秒呼叫int 4ah
我正在创建一个程序,它应该在启动五秒钟后打印“Hello from handler”。首先,我通过名为Assembly 如何使定时器工作?启动后5秒呼叫int 4ah,assembly,dos,x86-16,tasm,dosbox,Assembly,Dos,X86 16,Tasm,Dosbox,我正在创建一个程序,它应该在启动五秒钟后打印“Hello from handler”。首先,我通过名为create\u interrupt的proc创建了中断4ah。 此中断导致int\u handler,它打印字符串“Hello from handler”。 然后处理“报警”获取当前时间,加上5秒,并通过int 1ah的func 06h设置报警 这个警报应该在启动5秒后调用int 4ah,但它不工作,我不知道为什么。如果我称4ah为“手动”,只需添加“int4ah”即可工作,这意味着中断创建并
create\u interrupt
的proc创建了中断4ah。
此中断导致int\u handler
,它打印字符串“Hello from handler”。
然后处理“报警”获取当前时间,加上5秒,并通过int 1ah的func 06h设置报警
这个警报应该在启动5秒后调用int 4ah,但它不工作,我不知道为什么。如果我称4ah为“手动”,只需添加“int4ah”即可工作,这意味着中断创建并正确工作。但我需要通过警报来调用这个中断
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=06h
(BIOS.SetSystemAlarm)和int 21h AH=2Dh
(DOS.SetSystemTime)这样的函数不能正常工作为什么会这样?DOSBox是一个模拟器,目标是玩(现有的)DOS游戏。 通常,游戏不设置(实时)时钟或使用实时时钟闹钟。游戏处理的是各种各样的延迟。这就解释了为什么DOSBox不支持这种功能。
尽管我们不得不接受开发人员的选择,但如果他们向我们提供了记录在案的返回代码来表示错误,那就太好了
(BIOS.SetSystemAlarm)最好返回int 1Ah AH=06h
CF=1
(DOS.SetSystemTime)最好返回int 21h AH=2Dh
AL=FFh
; 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)谈到了DOS的重新进入或缺乏
我在DOSBox下测试了上述程序,没有任何问题,因为引用我的程序员手册
当DOS等待键盘输入时,它在循环中空闲,读取输入的字符。只要DOS在此等待,即使InDOS标志另有指示,也可以保存以使用文件处理和其他功能
上面的程序除了等待键盘输入外什么也不做,所以这是可以的。在一个更复杂的程序中,可以同时检查InDOS标志和拦截int28h
但是,一个简单的解决方案仍然是避免完全使用DOS,并使用BIOS等输出消息。电传打字机:
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
这是DOS程序吗?请标记操作系统。程序中有很多问题(例如,IRET太多,DOS中断不可重入,5秒非常短),但主要问题是:Int1A/Fn06h在DosBox中不工作。也许警报在其他地方被使用。可能值得注意的是,因为DOS不是可重入的,而且没有检查INDOS标志,INT21H/AH= 9H可以在DOS中间中断定时器做其他工作时将DOS拧紧。当然BIOS也不被认为是可重入的。PS:我是upvote。至于Int 28h(空闲处理程序),问题是DOSBox在空闲时实际上不会调用中断。我最近在评论另一个问题时发现了这一点(我尝试了一些从未被调用的int28h测试代码)。我不得不去看DOSBox代码来确认它。@MichaelPetch多少次我渴望DOSBox更多的是一个实际DOS的模拟器,而不是一个游戏环境!BOCHS是否忠实地模仿PC?我想是的。如果你想用BOCHS,有什么理由不直接用BOCHS吗?