Nanosecond delaysMarch 30 2006 at 5:06 AM
|David (no login)|
The pentium processor has a so called "time stamp counter" this is a 64 bit clock that is incremented at the same rate as the processor speed. It can be accessed using a short ASM routine from Qbasic.
Read time stamp counter (RDTSC) is invoked by the ASM code 0F31 and the 64 bits go into EDX:EAX. Below is a simple routine that will cause output to the LPT3 port for 7865 clock ticks. I have not taken into account the possibility that the bits might "roll over" in the same way timer does at midnight. I think the chances of a 32 bit timer rolling over in a short delay are fairly slim.
It is interesting that you can have access to 32 bit arithmatic from Qbasic (there are also 16 and 8 bit variables - dx and al - mixed in there)
I'm not too good at ASM I would hope that somebody (Michael ? JT ?) could improve on this program. I have fastidiously avoided messing with the stack as I don't like having to re-boot after every trial run.
'QBASIC PROGRAM HERE
CALL ABSOLUTE(I2) 'calling ASM routine
'loading ASM routine
H1$ = "BABC03B008EE0F316689C36681C3"
H2$ = "0F316639D87CF9BABC03B000EECA0000"
ic = 7865 ' change this for different delays
A$ = HEX$(ic)
IF LEN(A$) = 1 THEN A$ = "000" + A$
IF LEN(A$) = 2 THEN A$ = "00" + A$
IF LEN(A$) = 3 THEN A$ = "0" + A$
B$ = RIGHT$(A$, 2) + LEFT$(A$, 2) + "0000"
ASM$ = ""
H$ = H1$ + B$ + H2$
FOR A = 1 TO LEN(H$) STEP 2
ASM$ = ASM$ + CHR$(VAL("&h" + MID$(H$, A, 2)))
i1 = VARSEG(ASM$)
I2 = SADD(ASM$)
here is the assembler that is loaded
00000000 BABC03 mov dx,0x3bc 'prepare LPT(&H3bc) for output
00000003 B008 mov al,0x8 'load 8 for LPT output
00000005 EE out dx,al 'output the 8 to &H3BC
00000011 0F31 rdtsc 'read pentium clock
00000013 6689C3 mov ebx,eax 'move output to ebx
00000016 6681C3B91E0000 add ebx,0x1eb9'add delay (ic) to ebx
0000001D 0F31 rdtsc 'read clock again
0000001F 6639D8 cmp eax,ebx 'compare clock with ebx
00000022 7CF9 jl 0x1d 'keep looping until eax>ebx
0000002F BABC03 mov dx,0x3bc 'prepare LPT3 for output
00000032 B000 mov al,0x0 'load zero for output
00000034 EE out dx,al 'ouput zero to lpt3
00000035 CA0000 retf 0x0 'put things back and end
so this sends 00001000 to &H3BC waits ic(=7865 in this case) pentium clock ticks then outputs 00000000 to &h3BC. One clock tick = 1/(processor frequency) so at 100MHz clock tick is 10 nanoseconds!
*Unfortunately it's CPU speed dependant
|April 21 2006, 1:52 PM |