News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Handle Interruptions

Started by popcalent, June 05, 2021, 06:29:01 AM

Previous topic - Next topic

popcalent

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:
 
        MOV    AH, 2CH ;GET SYSTEM TIME
        INT    21H     ;CH=HOUR, CL=MINUTE, DH=SECOND, DL=1/100 SECS
        CMP    DL, TIME
        JB     NO_INTERRUPTION
INTERRUPTION:
        ;DO WHATEVER
NO_INTERRUPTION:

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!



daydreamer

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


my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

mineiro

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.

main:
jmp realcode:
old_int_16 dw 0
othervar db 0
realcode:

I don't have played with timings, so, no answer.
I'd rather be this ambulant metamorphosis than to have that old opinion about everything

FORTRANS

Hi,

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

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; 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

DELAYER:
        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
IF DEBUG3
        MOV     AH,11H  ; Check Extended Keyboard Status
        INT     16H     ; BIOS Keyboard Services
ELSE
        CALL KeyStatus
ENDIF
        JNZ     DLR_3   ; key available, abort delay

        SCALL GTIME
        CMP     [StatusTime],CX
        JZ      DLR_0
        CALL StatusDate
DLR_0:

        MOV     CX,1
        XOR     BX,BX

        PUSH    DS              ; Save DS and point to BIOS data area
        MOV     AX,SEG BIOSSEG
        MOV     DS,AX
        ASSUME  DS:BIOSSEG
        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
DLR_1:
        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

DLR_2:
        CMP     AX,CX
        JBE     DLR_1   ; Less than end?

        POP     DS      ; exit processing
        ASSUME  DS:DATASG
DLR_3:
        POP     DX
        POP     CX
        POP     BX
        POP     AX
        POP     ES

        RET
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


   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.

Regards,

Steve N.

popcalent

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

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.

popcalent

Thanks, mineiro and FORTRANS. I'll check later, and get back to you.  :thumbsup:

daydreamer

Quote from: popcalent on June 05, 2021, 10:18:41 PM
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

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.
nonzero call keyboard handler,otherwise continue in outerloop
or just following switch/case with VK_LEFT ,VK_RIGHT,VK_UP,VK_DOWN
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

popcalent

Quote from: FORTRANS on June 05, 2021, 10:07:10 PM
Here is a routine that I used to "blink" a cursor in a graphics program.

Hi,

I assume Keystatus does MOV AH, 01h and INT16h, while GTIME does MOV AH, 2Ch and INT21h. What does StatusDate do? What are StatusTime and ClockTic, what do you init them to?

Also, should I check for key available right after DLR_1 label just in case a key is pressed during the delay?


Quote from: FORTRANS on June 05, 2021, 10:07:10 PM
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.

Well, 00111111 11111111 should be approximately one second (not the number I posted before), but I agree that the code causes problems.

Thanks!

daydreamer

If you doing sprite animation, reading from one port gets when vga vertical retrace is going on is alternative way to time code to synchronise to frame. Rate

my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

popcalent

Quote from: daydreamer on June 06, 2021, 04:18:10 AM
If you doing sprite animation, reading from one port gets when vga vertical retrace is going on is alternative way to time code to synchronise to frame. Rate

Yes, I thought I should track the vertical retrace to avoid sprite blinking, but I'm not there yet... I've done it in Borland C before, but I have no idea how to do it in ASM.

FORTRANS

Hi,

Quote from: popcalent on June 06, 2021, 12:00:54 AM
Hi,

I assume Keystatus does MOV AH, 01h and INT16h, while GTIME does MOV AH, 2Ch and INT21h.

   Mostly right.  GTIME is an EQUate of 2CH used by the SCALL macro
to call the DOS INT 21H.  Saves me from remembering that Get Time
uses 2CH.  KeyStatus also has a test for a redirected keyboard.

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
; Return non-zero if key available
; 22 April 2003, SRN
KeyStatus:
        CMP     [REDIRECT],0    ; 0 = Check keyboard
        JNZ     KS_1

        MOV     AH,11H  ; Check Extended Keyboard Status
        INT     16H     ; BIOS Keyboard Services
KS_1:
        RET
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -



QuoteWhat does StatusDate do? What are StatusTime and ClockTic, what do you init them to?

   StatusDate updates the program's status line at the bottom
of the screen with time and date.  StatusTime is a word in the
data segment to save the returned time.  Tested to skip an update
if it has not changed.  ClockTic is a word to store the current 55ms
tic count.  Initialized with current values when in use.

QuoteAlso, should I check for key available right after DLR_1 label just in case a key is pressed during the delay?

   I don't.  Both the delay routine is called often enough that it
shouldn't matter, and I check key status elsewhere as well.

Regards,

Steve

popcalent

#11
Thanks FORTRANS.

I ended up using a 16-bit counter that increments in every iteration of the main loop. When it reaches a certain number, the code calls a function that does what needs to be done periodically. I coded a basic Pacman game that can be played with the NES controller connected to the parallel port. The ghost (there's only one), makes a move whenever the counter reaches the number. When I move Pacman, the code makes a small pause, otherwise it would move too fast and it would be impossible to do anything other than going from one end of the screen to the other. The problem is that, because of the small pause, if I press a direction button, and don't release it, the ghost won't move because the counter will increment only by one between each pause. Solution: when Pacman makes one move, the ghost makes another move and resets the counter. If Pacman doesn't move, the ghost waits for the counter. On a 286 at 8 Mhz it works fine.

Now, my next goal... and I'm not sure if this can be done... or if it can be easily done...
I want to code a program that stays resident and translates what it reads on the parallel port to keystrokes. So, prior to playing a game, you execute the program and tell it to which keys you want to translate the NES buttons. For instance, you tell the program that when you press the arrow keys on the NES controller, the program makes it so the game thinks you pressed the arrow keys. Other games use Q,A,O,P instead of the arrow keys, or Space vs. Enter to fire.

You would execute the program and it would ask: "What key to go up?", and if you press Q, every time you press UP on the NES controller it'd be the same as pressing Q. Then the program asks the same for down, left, right, and fire. If you want to change the keys, you execute the program again.

I'll start working on this soon, I'll report my progress in this forum.

 

daydreamer

You mean some tsr that stays high up in memory,that takes care of input thru interrupt, loaded with autoexec.bat?
Interesting pacman game  :thumbsup:

But I prefer poll vertical retrace for periodic calls,because it's advantage of know when to call draw sprites/tiles without flicker

my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding