本文介绍了如何使计时器工作?启动后5秒致电int 4ah的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个程序,该程序应在启动五秒钟后打印来自处理程序的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 returned CF=1
  • int 21h AH=2Dh (DOS.SetSystemTime) had better returned AL=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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-29 18:06
查看更多