Author Topic: 16-bit Timer tick function  (Read 12648 times)

Offline mik3ca

  • Jr. Member
  • *
  • Posts: 30
16-bit Timer tick function
« on: January 26, 2021, 09:03:30 PM »
I'm rewriting parts of my code from Qbasic to assembler because I'm making a server that gives me the best speed for CPU.

Anyways, I'm having trouble with the timer function.

I'm using interrupt 1Ah with AH=0 to receive clock ticks. Info for that is here: http://www.ctyme.com/intr/rb-2271.htm

For this code, ES:DI is the segment and offset to a predefined structure in QuickBasic that's passed in through "Call absolute".

For those that don't care about QuickBasic, don't worry because the code I'm showing has everything commented

Code: [Select]

;These are offsets to individual elements in the QuickBasic struct
func equ 0h
errc equ 2h
tmo equ 4h
debug equ 6h


;Function begins
atimer:
  xor AX,AX ;Set AH+AL to 0
  mov [ES:DI+tmo],AX ;Set member tmo of struct to 0.
  int 1Ah ;Call timer tick interrupt
  cmp AL,0h ;do clock read again if 12am marker set
  je noclk2
    xor AX,AX ;Set AH+AL to 0 for second call
    int 1Ah ;Call timer tick interrupt since midnight passed
  noclk2:
;We will store timer value as EAX instead of the returned CX:DX
  xor EAX,EAX  ;Set EAX to 0
  mov AX,CX ;Set lower 16-bits to CX
  shl EAX,16 ;make those 16-bits as high 16-bits
  mov AX,DX ;Set lower 16-bits to DX
  mov EBX,[CS:myclock] ;Load old clock value as EBX
  mov [CS:myclock],EAX ;Save new clock value
  mov DX,[CS:myclockinit] ;Load initialized value to DX
  cmp DX,0h ;See if function was called before
  je tosmlc
  sub EAX,EBX ;this clock function was called so subtract timer values
  jc tosmlc ;if value is under 0 then 1 second didnt pass
    cmp EAX,19 ;See if we got 19 ticks (18.2 ticks a sec)
    jl tosmlc
    inc word[ES:DI+tmo] ;we have so we set tmo member of struct to 1
  tosmlc:
  mov DX,1h ;Set clock function to 1 so next time we call it we can check for timeout
  mov [CS:myclockinit],DX
jmp endit ;do ending and return to Qbasic

myclock dd 0 ;This stores the last time value read from the interrupt
myclockinit dw 0 ;If non-zero, it means function was executed at least once


Now the odd thing is that when I run the code the first time, the timeout value is correct and things work as expected. However when I run it the second time, I receive this error:

Code: [Select]
DOS memory-arena error

Then QuickBasic crashed and I'm returned to DOS with the DOS prompt appearing right after the error message (with no space after the word error) and no blinking cursor after the prompt.

So I'm wondering what I may be doing wrong.

Could it be that my math is incorrect?

Could it be that the interrupt function I'm using is not functional? Maybe I discovered a bug with DOSBOX that I'm not aware of? I'm using DOSBOX 0.74 for testing.

Could it be that the source of interrupt information I refer to is not correct?

What would be a fast and working method to calculate a 1-second timeout?

I ask here because I notice when I use some quickbasic functions, they are slower than their assembler counterparts.

Offline fredericopissarra

  • Full Member
  • **
  • Posts: 373
  • Country: br
Re: 16-bit Timer tick function
« Reply #1 on: January 27, 2021, 04:17:58 PM »
Why not capture interrupt 0x1C instead?