Miscellaneous > 16 bit DOS Programming

Handle Interruptions

(1/3) > >>

Hi all!

I'm trying now to have a code run every certain period of time. I have coded microcontrollers assembly before, and you just set the interruption you want to handle at the beginning of the program, go to the interruption vector, and code your interruption handler. However, the concept of interruption seems to be different in x86 assembly. When I google for interruption handling, all I find are references to the BIOS/MSDOS interruptions (INT 10H, INT13H, INT21H, etc). But there must be a way to do what I want to do since there's an IRET instruction (return from interruption), I just can't find any example.

Here's what I tried:
        INT    21H     ;CH=HOUR, CL=MINUTE, DH=SECOND, DL=1/100 SECS
        CMP    DL, TIME
        ;DO WHATEVER

This works arbitrarily (ie. it doesn't work), the times are random, sometimes it's less than a second, sometimes it's five seconds or more...

Second thing I tried (it's worse, but it's the only thing that occurred to me since the code above doesn't work):
        ;DO WHATEVER
        MOV     AH, 86H ;WAIT
        MOV     CX, 00000011B
        MOV     DX, 11111111B
        INT     15H
What I try to do here, is run the code every iteration of the main loop, then wait for whatever amount of milliseconds. The wait time is short enough for the user to not notice the program is stopped, but long enough for the keyboard buffer to fill with garbage since the user is pressing the arrow keys to move a cursor. Therefore, sometimes, the cursor appears to "teleport" because the keyboard buffer filled with keystrokes while the program is waiting.

None of the two approaches work for me. How do I enable a time interruption and code the handler? Thanks!


To control something with arrow keys,simple use
 in Al,60h

Because I also code 32bit windows with vk codes,I have started to write. Inc file with equates for vk codes for port 60

I'm talking from memory, I can be wrong.
Exist an ivt (interruption vector table) in ms-dos where is stored code addresses to interruption.
Basically we calculate address of our interruption in that table, get and store that address in our program, ovewrite that with our code address. When an interruption is called, we check for signs, if a special key was pressed our code will run, if not we call saved address interruption code.
I forgot if flags register should be saved and restored at start and end of our code. And we need use iret as you noted.
Ms-dos have a technique called TSR (terminate and stay resident). Program will run, install or ovewrite interruption code address, and exit. So, program need be resident in memory after program exit. Start with a simple program, move a value to some register and instruction iret.
Keyword to do a search is "ms-dos TSR".
google: site:masm32.com/board/ TSR
Old saved board have these talks too: http://www.masmforum.com/board/index.php
One thing I'm remembering is about data and extra segments while coding interruption code. I have a lot of dificulty in doing that, so, I inserted data inside code segment.

jmp realcode:
old_int_16 dw 0
othervar db 0

I don't have played with timings, so, no answer.


   Here is a routine that I used to "blink" a cursor in
a graphics program.

--- Code: ---; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Mode 6 implies 200LX and no INT 15 delay routine
; so we will use something similar to MsDelay from the PAL library.
; 15 November 2000, Mods for a fixed delay, 7 August 2002

        PUSH    ES
        PUSH    AX      ; After all this is a delay routine, so save everything.
        PUSH    BX
        PUSH    CX
        PUSH    DX

; 26 August 2002, test if keystroke ready
        MOV     AH,11H  ; Check Extended Keyboard Status
        INT     16H     ; BIOS Keyboard Services
        CALL KeyStatus
        JNZ     DLR_3   ; key available, abort delay

        CMP     [StatusTime],CX
        JZ      DLR_0
        CALL StatusDate

        MOV     CX,1
        XOR     BX,BX

        PUSH    DS              ; Save DS and point to BIOS data area
        MOV     AX,SEG BIOSSEG
        MOV     DS,AX
        LES     AX,DS:[ClockTic] ; Get timer 55 ms tick count
                                ; Actually, not using high word...
        MOV     DX,AX   ; Save low word start time in DX
        ADD     CX,AX   ; Save low word start + delay = end in CX
        JNC     DLR_1
; problem...  counter overflow
        MOV     BX,CX
        MOV     CX,0FFFFH
        STI             ; 4 Sep 03
        HLT             ; 4 Sep 03
        LES     AX,DS:[ClockTic] ; Get timer 55 ms tick count
        CMP     AX,DX
        JAE     DLR_2   ; Greater than Start?
        MOV     CX,BX
        MOV     DX,0

        CMP     AX,CX
        JBE     DLR_1   ; Less than end?

        POP     DS      ; exit processing
        POP     DX
        POP     CX
        POP     BX
        POP     AX
        POP     ES

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

--- End code ---

   GTIME is the MS-DOS Get Time function.  StatusDate updates the
screen display of the current time.  Flags are not preserved as not
needed in my program.

   Looking at your INT 15H,86H code you might be looking for much
longer delays.  If so, the MS-DOS Get Time function might be more
appropriate to use.  Your posted Get Time code does not check for
overflow, which will cause problems.


Steve N.


--- Quote from: daydreamer on June 05, 2021, 09:04:25 PM ---To control something with arrow keys,simple use
 in Al,60h

Because I also code 32bit windows with vk codes,I have started to write. Inc file with equates for vk codes for port 60

--- End quote ---

This could work. Thanks!

Is there a way to interrupt the program whenever certain keys are pressed? Ie. The main loop is iterating, I press an arrow key, the program goes to a handler, does whatever, then returns t the main loop.


[0] Message Index

[#] Next page

Go to full version