Pause
Pause
Pause is a little routine that does what it say - make a pause. There are several ways to do that, and my first attempt was to use function 86h/int15h.
BIOS - WAIT (AT,PS)
AH = 86h
CX:DX = interval in microsecondsReturn:
CF clear if successful (wait interval elapsed) CF set on error or AH=83h wait already in progress AH = status (see #00496)Note: The resolution of the wait period is 977 microseconds on many systems because many BIOSes use the 1/1024 second fast interrupt from the AT real-time clock chip which is available on INT 70; because newer BIOSes may have much more precise timers available, it is not possible to use this function accurately for very short delays unless the precise behavior of the BIOS is known (or found through testing).
That didn't work on my Amstrad PPC640, so I tried with function 00/int1Ah.
TIME - GET SYSTEM TIME
AH = 00h
Return:
CX:DX = number of clock ticks since midnight AL = midnight flag, nonzero if midnight passed since time last readNotes: There are approximately 18.2 clock ticks per second, 1800B0h per 24 hrs (except on Tandy 2000, where the clock runs at 20 ticks per second). IBM and many clone BIOSes set the flag for AL rather than incrementing it, leading to loss of a day if two consecutive midnights pass without a request for the time (e.g. if the system is on but idle). Since the midnight flag is cleared, if an application calls this function after midnight before DOS does, DOS will not receive the midnight flag and will fail to advance the date. Modern releases of MS-DOS/PC DOS (5.0+???) assume that AL is a day rollover counter rather than a flag, as expected by older releases. DOS 5 - 7.10 (Windows 98 SE) provide an undocumented CONFIG.SYS SWITCHES=/T option to force the old behaviour of the day advancing code, that is using a flag instead of a counter.. DR DOS 3.31 - DR-DOS 7.03 handle AL as a flag.
It can be used this way:
;---------------------------------------------------------------
;
; PAUSE
;
; expext: cx = number of 1/18.2 seconds to pause
;
; return: nothing
;
;---------------------------------------------------------------
PROC pause
push ax ; save registers
push bx
push dx
mov ah, 00h ; get ticks
int 1Ah
mov bx, dx ; save ticks in bx
@@L1:
mov ah, 00h ; get ticks again
int 1Ah
sub dx, bx ; substract, to get num of ticks
cmp dx, cx ; since first int 1Ah, and compare
jb @@L1 ; to the num in cx
; loop while below
pop dx
pop bx
pop ax
ret
ENDP pause
There is just one little problem with this - we are running a loop, until the specified number of ticks has passed. It's a waste of CPU time.It would be smarter if we could do something in the meantime. And we can. In squares.asm I insert some code between the first and second 00h/int1Ah, so the code is executed while waiting for the time to pass.
mov ah, 00h ; get ticks
int 1ah ; return ticks in dx@@L1:
push dx ; save them
call write_vbuffer ; fill vbuffer
pop bx ; get ticks again
mov ah, 00h ; get ticks again
int 1Ah
sub dx, bx ; substract, to get num of ticks
cmp dx, cx ; since first int 1Ah, and compare
jb @@L1 ; to the num in cx
; loop while below