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!
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.
main:
jmp realcode:
old_int_16 dw 0
othervar db 0
realcode:
I don't have played with timings, so, no answer.
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.
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.
Thanks, mineiro and FORTRANS. I'll check later, and get back to you. :thumbsup:
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
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!
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
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.
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
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.
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