Board index » delphi » I can't figure out what I am doing wrong...

I can't figure out what I am doing wrong...

I've poured over this code so many times that I think that I have it
memorized and I still don't see what it is that I'm doing wrong.
Perhaps some of you could enlighten me . . .

This code started life a some C code that I found out there somewhere.
I am in need of a higher resolution clock tick than the default 55
milliseconds so I am attempting to reprogram the 8253.  This code does
work as far as getting my ISR installed and having it chain to the
original ISR that it replaces as well as getting the resolution that I
was after.  I have examined the code that the compiler generates,
re-written the code in mixed pascal/asm, pure asm, etc.  Clearly there
is something that I am overlooking but I don't know what it is.  Your
help is GREATLY appreciated and I thank you in advance for any help that
you may be able to extend.

The problem occures upon program termination and yes I do call
RestoreBIOS_ISR_08 prior to terminating.  On my NT workstation there are
no errors reported but on the actual devices that this code is required
to run on: AMD 286 and 486 CPUs, the problems are always there.

I will gladly provide the remainder of the unit code and test app code
if anyone wants to see it but I suspect that the error is in this
portion.

var
   HighResTicks   : longint;
   HighResClockOn : boolean;
   BIOS_ISR_08    : pointer;

{===============================================================================

   The following routines increase the clock rate to around 1165
interrupts
   per second, for a granularity of close to 858 microseconds between
clock
   pulses, rather than the 55 milliseconds between normal PC clock
pulses
   (18.2 times/second).

===============================================================================}

{$F+,S-,W-}
procedure  HighRes_ISR;  interrupt;
const  CallCntr : byte = 0;
begin
 { Increment the ticks counter }
   if HighResTicks < $7FFFFFFF then  Inc( HighResTicks )
   else                              HighResTicks := 0;
 { If this is the 64th call, then call handler }
   { Otherwise, clear the interrupt controller   }
   if CallCntr < 64 then begin
      Inc( CallCntr );
      { Send the Clear Interrupt signal }
      Port[ $20 ] := $20;
   end else begin
      CallCntr := 0;
      asm  call dword ptr [ BIOS_ISR_08 ]  end;
   end;
end;
{$F-,S+}

{==============================================================================}

procedure  RestoreBIOS_ISR_08;
begin
   if not HighResClockOn then  exit;
   asm  cli  end;
   SetIntVec( $08, BIOS_ISR_08 );
   { Reinstate the clock rate to 18.2 Hz }
   Port[ $43 ] := $36;  { Set up for count to be sent         }
   Port[ $40 ] := $00;  { LSB = 00  \_together make 65536 (0) }
   Port[ $40 ] := $00;  { MSB = 00  /                         }
   asm  sti  end;
   HighResClockOn := false;
end;

{==============================================================================}

function  InitHighResClock : integer;
begin
   InitHighResClock := -1;
   if HighResClockOn then  exit;
   asm  cli  end;
   GetIntVec( $08,       BIOS_ISR_08   );
   SetIntVec( $08, Addr( HighRes_ISR ) );
 { Increase the clock rate }
   Port[ $43 ] := $36;  { Set up for count to be sent   }
   Port[ $40 ] := $00;  { LSB = 00 \_together make 1024 }
   Port[ $40 ] := $04;  { MSB = 00 /                    }
   asm  sti  end;
   HighResClockOn   := true;
   InitHighResClock := 0;
end;

{==============================================================================}

-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----==  Over 80,000 Newsgroups - 16 Different Servers! =-----

 

Re:I can't figure out what I am doing wrong...


Quote
"Robert Milligan" <robe...@harvestmaster.com> wrote in message

news:39F61428.CFBAE1D8@harvestmaster.com...

Quote
> I've poured over this code so many times that I think that I have it
> memorized and I still don't see what it is that I'm doing wrong.
> Perhaps some of you could enlighten me . . .

dunno, really, but I noticed that you don't reset the timer speed to
18.2 Hz until after you reset the interrupt vector. Now, it's all
wrapped up in a cli...sti. but could SetIntVec be doing an implicit
sti somewhere?

Just a guess

FP

Re:I can't figure out what I am doing wrong...


Quote
Frank Peelo wrote:
> dunno, really, but I noticed that you don't reset the timer speed to
> 18.2 Hz until after you reset the interrupt vector. Now, it's all
> wrapped up in a cli...sti. but could SetIntVec be doing an implicit
> sti somewhere?

Good question.  I'll have to take a look at that one.

Thanks

-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----==  Over 80,000 Newsgroups - 16 Different Servers! =-----

Re:I can't figure out what I am doing wrong...


On Tue, 24 Oct 2000 16:58:48 -0600, Robert Milligan

Quote
<robe...@harvestmaster.com> wrote:
>I've poured over this code so many times that I think that I have it
>memorized and I still don't see what it is that I'm doing wrong.
>Perhaps some of you could enlighten me . . .

[snip]

Quote

>var
>   HighResTicks   : longint;
>   HighResClockOn : boolean;
>   BIOS_ISR_08    : pointer;

>{===============================================================================

>   The following routines increase the clock rate to around 1165
>interrupts
>   per second, for a granularity of close to 858 microseconds between
>clock
>   pulses, rather than the 55 milliseconds between normal PC clock
>pulses
>   (18.2 times/second).

>===============================================================================}

>{$F+,S-,W-}
>procedure  HighRes_ISR;  interrupt;
>const  CallCntr : byte = 0;
>begin
> { Increment the ticks counter }
>   if HighResTicks < $7FFFFFFF then  Inc( HighResTicks )
>   else                              HighResTicks := 0;
> { If this is the 64th call, then call handler }
>   { Otherwise, clear the interrupt controller   }
>   if CallCntr < 64 then begin
>      Inc( CallCntr );
>      { Send the Clear Interrupt signal }
>      Port[ $20 ] := $20;
>   end else begin
>      CallCntr := 0;
>      asm  call dword ptr [ BIOS_ISR_08 ]  end;
>   end;
>end;
>{$F-,S+}

>{==============================================================================}

>procedure  RestoreBIOS_ISR_08;
>begin
>   if not HighResClockOn then  exit;
>   asm  cli  end;
>   SetIntVec( $08, BIOS_ISR_08 );
>   { Reinstate the clock rate to 18.2 Hz }
>   Port[ $43 ] := $36;  { Set up for count to be sent         }
>   Port[ $40 ] := $00;  { LSB = 00  \_together make 65536 (0) }
>   Port[ $40 ] := $00;  { MSB = 00  /                         }
>   asm  sti  end;
>   HighResClockOn := false;
>end;

>{==============================================================================}

>function  InitHighResClock : integer;
>begin
>   InitHighResClock := -1;
>   if HighResClockOn then  exit;
>   asm  cli  end;
>   GetIntVec( $08,       BIOS_ISR_08   );
>   SetIntVec( $08, Addr( HighRes_ISR ) );
> { Increase the clock rate }
>   Port[ $43 ] := $36;  { Set up for count to be sent   }
>   Port[ $40 ] := $00;  { LSB = 00 \_together make 1024 }
>   Port[ $40 ] := $04;  { MSB = 00 /                    }
>   asm  sti  end;
>   HighResClockOn   := true;
>   InitHighResClock := 0;
>end;

>{==============================================================================}

1. The way you chain to the old int 08h vector is wrong. You should do a
PUSHF before calling the old interrupt:

asm  pushf; call dword ptr [ BIOS_ISR_08 ]  end;

This must be done because an interrupt handler assumes that the flags
have been pushed on the stack first, before the return address is
pushed. The IRET instruction in the old handler not only pops the return
address, but also the flags, causing a stack corruption in your program.
Incidentally, is this why you disabled stack checking for your interrupt
handler only?

2. If you only need HighResTicks inside your interrupt handler then you
should make this an initialized constant inside your handler, just like
CallCntr.

3. The compiler directive $W has no effect when compiling for real or
protected mode, and it pretty useless now when compiling for Windows.
$W+ was only needed to provide compatibility with Windows 3.0 running in
real mode (not Windows 3.0 running in standard mode or enhanced mode).
Besides, $W- is the compiler default. Remove it.

Haye van den Oever

Re:I can't figure out what I am doing wrong...


Haye van den Oever wrote:

Quote
> 1. The way you chain to the old int 08h vector is wrong. You should do a
> PUSHF before calling the old interrupt:

> asm  pushf; call dword ptr [ BIOS_ISR_08 ]  end;

<snip>

Thanks.  I'm testing now and am quite confident that this will correct my error.

-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----==  Over 80,000 Newsgroups - 16 Different Servers! =-----

Other Threads