               Hooking Interrupt i Turb Pascal
                   Michae Da CIS:[70007,4645         09/23/92


Ther ar  numbe o way t hoo a interrupt I mos case 
the al resul i th sam effect The simpl diffe i ho t 
ge there.

Writin th Interrupt:

Th metho supplie b Pasca itsel i t us th Interrup ta 
o  procedur t tel th compile tha i i bein use a a 
interrup procedure 

Th Interrup doe severa things Firs i cause th procedur 
retur t b declare a  IRE instea o th norma RE tha 
woul b used Whe a interrup i called i no onl save th 
curren cod addres o th stack i als save th curren 
flag o th stack Th reasonin behin thi i s tha th 
stat o th flag wil b automaticall restore o exi fro 
th interrup call Thi i neede mainl t manag th interrup 
fla itself Wit ou th save yo coul neve kno wha th 
previou conditio o th interrup fla was.

Th othe thin th Interrup ta doe i t tel th compile t 
pus al th register o entr t th procedur an po the al 
of o exit Thi i neede becaus whe callin  Pasca 
procedure ther i n knowin wha register wil ge destroyed 
an al register MUS b restore t thei origina conditio 
befor th interrup wa called 

Finally th Interrup ta tell th compile t reloa th dat 
segmen registe a th star o th interrup procedur (afte 
pushin th registers) Thi i neede becaus i a interrup 
procedur yo don' kno wher yo cam from an th register 
ma no b wha the wer i th mai program I fact i i 
highl unlikel tha the wil b i an recognizabl condition 

Wha th Interrup ta doe NO d i reloa th stac segment 
Thi i o purpose becaus ther i n wa t kno wher i th 
progra stac yo are an i woul b disasterou t attac t 
th stac a a imprope location I i u t th programme t 
dea wit stac issues I mos simpl interrup procedures yo 
ca usuall safel ignor th stac issue 

Th stac yo wil b usin i th stac tha wa i effec a 
th tim tha th interrup occurred. Becaus o this yo mus 
us extrem cautio wit th stac i a interrupt Yo shoul 
neve us mor tha  doze o s level o th stac i a 
interrupt I yo expec tha yo wil nee more yo shoul se 
u you ow stack Ho t se u you ow stac wil b discusse 
later 


Re-entranc issues:

Extrem cautio mus b use whe writin a interrup procedure 
ther ar man restrictions Yo canno writ cod i a 
interrup procedur lik yo writ cod i  norma program 

First yo mus b awar o r-entranc issues R-entran mean 
callin som othe routin fro you interrup procedure I i 
possibl tha th procedur yo ar callin wa i operatio a 
th tim tha th interrup occurred an s i yo cal th 
routin fro th interrup procedure yo woul b r-enterin 
th operatin procedure Thi ca caus disruptio t routine 
tha don' tak r-entranc int account 

Muc o DO an th program tha ru unde i ar no r-
enterable Wha tha mean i tha yo canno generat cod tha 
call thos procedures D no cal an BIO routine (othe 
interrupts) D no cal an DO routine (In $21) D no cal 
an ru-tim librar functions 

 wil no g int designin r-entran cod i thi discussio. 
Tha i  subjec al it own Fo now jus realiz tha yo 
canno cal DO o BIO routine becaus the wer no designe 
t b r-entrant  A wit DO an th BIOS th Turb Pasca 
ru-tim librar i no r-entrant tha mean tha yo shoul 
avoi callin an Turb Pasca Run-tim calls 

Som runtim call ar buil-i t th compile code an yo 
shoul avoi the a well A a example Stac checkin mus b 
avoide becaus yo ar no usin th progra stack yo ar 
usin a unknow stack Tha wil caus seriou conflict an 
mos likel  stac error Thi jus compound th proble 
becaus whe yo ge  stac error T trie t proces it Tha 
mean  ru-tim librar cal t th erro handler an you 
progra end u diggin it' ow grave 

I checkin i th sam way S i Rang checking Anythin tha 
coul caus  runtim librar cal mus b avoided Tha mean 
tha yo shoul tur of th Stack IO an Rang checkin fo 
an cod use b th interrup procedure.

I additio t no doin IO/Range/Stac checking yo shoul no 
cal routine suc a Writel o Readl whic ar par o th 
ru-tim library Doin s i a invitatio t cras an burn 
No shoul yo overla Interrup procedures.

Yo shoul als b ver carefu wit regar t r-entranc i 
you ow code Th sam r-entranc issue tha ar i th ru-
tim librar hold fo you ow code Yo ca cal othe 
procedure fro an interrup procedure bu i yo ar callin 
procedure tha ar use b th mainlin code yo mus b 
extremely carefu o r-entranc problems I yo ar uncertai 
o th effects i i bes t no shar th code Practice saf 
coding Th sam i tru o variables don' shar variable 
unles yo full understan th effect o doin so.

Ther ar really onl tw primar issue tha tri programmer 
u whe writin interrup procedures r-entrancy an time 

Time 

Th othe critica aspec abou interrupt i time A interrup 
procedur MUS b a shor i tim a possible Yo shoul striv 
t kee th proces tim t unde 10 microseconds Preferabl 
faste i possible Tim resource o th compute ar limited 
Remembe tha ther ar othe interrupt ou ther demandin 
service an som o the expec t b service i  timel 
manner I yo hav  RS23 seria communication tas goin o 
i th backgroun sa a 960 baud an th tota interrup 
servic tim o th compute exceed on millisecond yo wil 
los dat o th seria port 

Tim i  fixe quantity yo can' chang it I somethin lik 
 seria por demand t b serviced yo mus allo i t b 
serviced o yo wil los th data 

Som interrupt ar buil int th i th system Flopp disk 
har disk keyboar an th cloc timer Thes al hav thei 
demand o th computer' time an the mus b serviced.

Ther ar man ad i board a wel tha plac thei ow demand 
o th interrupts Tw o th mos commo one ar th mous an 
RS23 (modem) Ther ar man othe one becomin popula too 
suc a Soun card an C-ROMs Al o thes mus b allowe t 
hav thei interrupt serviced.

Th 10 microsecon (uS figur i jus  rul o thum tha I'v 
develope ove tim wit m experienc i writin interrup 
drivers Yo ca g longer bu car mus b use i yo d so 
Tha doesn' mea tha th syste wil cras i yo g t 150uS 
i won't bu th longe th time th greate th chanc o 
timin relate proble occurring. 

Kee i min tha no onl ar th existin interrupt i th 
system bu othe TSR an program i th syste ma b 
attachin themselve t th interrupt too addin eve mor t 
th demand o th availabl time 

T giv yo som idea o wha t expec i  typica situation 
conside  seria por runnin a 960 bau receivin  strea o 
data 960 bau mean tha th por i receivin dat a 96 
character  second T mak thing easie fo thi discussion 
we'l roun tha u t 100 character pe second Tha mean 
tha th por i receivin 100 character pe second Th rs23 
softwar mus respon t eac characte received i i i no t 
los th receive data Yo can' sto th incomin data yo ca 
onl respon t it Tha mean tha th interrup mus respon a 
 on millisecon rate I othe words tha mean tha i yo 
don' wan t los data th tota interrup servic tim i th 
compute mus b les tha on millisecon t b abl t service th RS23 por a 960 baud.

A yo ca imagine a faste baudrates th proble become eve 
mor sever Th fastes tha th standar P por ca operat a 
i 11520 bau (although thi i  bi unreliable an th 
componen manufacture d no guarantee th operatio a tha 
sped) Th fastes reliabl spee o operatio i 5760 baud.
A 5760 baud th seria por mus b service a  rat o onc 
ever 17 microseconds Tha i no muc tim t ge anythin 
done A yo ca see i i extremel importan t pa attentio 
 th timin issue i th interrup servic routines.  

Sometime yo ma simpl hav n choic bu t writ  routin 
tha take longe tha desire t servic th interrupt I tha 
cas i i importan t tel th use s tha the wil b awar 
o th limitation o th progra an won' b surprise t 
discove tha thei syste ha suddenl becom flaky 

Th RS23 i normaly the worst case service area in the PC 
Usuall yo ca us i a  benc mar fo you cod timin 
issues 

Th nex importan tim leve i th interna syste clock Th 
bio maintain a interna cloc t kee trac o time Th cloc 
i drive fro a interrupt Th cloc perform a interrup onc 
ever 5 milliseconds. I you interrup servic routin take 
longe tha 55m t perform th compute wil begi t los 
time Yo shoul neve writ a interrup routin tha take 
longe tha 55m t perform Ther ar man thing i th 
compute tha ar tie t th cloc whic wil b disrupted 

Tha bein said i extrem cases yo ca get awa wit 
occasionall exceedin th 55m time bu th overal averag 
servic tim shoul neve excee 55mS Yo shoul stil avoi 
writin interrup routine tha tak thi lon, howeve, becaus 
th compute wil los tim becaus o th los time interrupts 
Als kee i min tha interrup servic routine o thi lengt 
i tim ar no goin t b abl t operat a th sam tim a 
a RS23 progra sinc yo won' b servicin th RS23 i  
timel manner 
     
Th othe issu t b awar o i tha you interrup servic 
routine mus b awar o itself A a example i yo writ a 
RS23 servic routine i mus b fas enoug t servic th 
seria port Failur t d s wil caus los data 


Writin Saf Lon Interrups:

Ther ar way t safel writ servic routine tha tak longe 
tha 100u t perform bu the complicat thing greatly Yo d 
thi b r-enablin th interrup syste a quickl a possibl 
i you ow servic routine Thi allow othe servic routine 
t hav acces t th compute whil your i bein processed 
Thi mean tha tim critica routine suc a RS23 ca no interrup yo interrup s the ca b serviced.

I th BIOS som routine ar implemente tha way A exampl 
i th keyboard Th keyboar interrup ca tak  lon tim t 
servic th keyboard Enoug s tha th RS23 woul no b 
service i  timel fashion Thu th keyboar interrup r-
enable th interrupt a quic a i ca s tha othe 
interrupt ca hav acces t th system Thi create othe 
problem though I i no possibl fo th keyboar interrup t 
interrup itself I fact thi proble ha bee th sourc o 
problem o th PC Fas typist hav cause th keyboar 
interrup t b entere multipl time resultin i  syste 
crash Th STACKS=n, statemen i CONFIG.SY attempt t dea 
wit th problem bu i i no  perfec solution Anytim a 
interrup ca interrup itself th possibilit exist o  stac  
cras a th servic run ou o memory 

I additio t th servic issue th interrup mus b awar o 
r-entranc issue i i allow itsel t b r-interrupted 
Ideall th solutio woul b t no allo th r-interrup t 
occu b servicin th interrup i  fashio tha woul ensur 
tha i woul b service bfor th nex interrupt Thi i no 
alway possible I tha case th thre option ar t (1 Mas 
th interrup t preven i fro happening  (2 Ignor th extr 
interrupt an dea wit th fallou later  o (3 Attemp t 
servic th extr interrup i som fashion Excep i  fe 
specia cases attemptin t servic th extr interrup ca lea 
t seriou problems Wha d yo d i th interrupte interrupt 
get interrupted etc.. Thi i on o th commo probles o 
dealin wit interrupts Tim i  fixe quantity yo can' 
chang it s th syste desig mus tak int accoun th 
servic tim an allo fo al task t b service withi th 
allowe tim period 

Als kee i min tha i yo d allo th interrup t b r-
interrupted yo mus no dea wit th r-entranc proble o 
share cod an variables Becaus o this mos peopl simpl 
mas ou thei ow interrup t preven i fro interruptin the 
again Yo ca mas you ow interrup whil allowin othe 
interrupt t occu i th system I yo ar hookin int 
someon else' interrupt suc a th cloc servic interrupt 
yo shoul b extremel carefu abou this Th cloc servic 
interrup stil need t b service a  55m rate an maskin 
th interrup longe tha 55m wil caus th interrup t b 
los an thu th interna clo wil los time. 


Creatin You Ow Stack:

Normall yo shoul kee th cod use i a interrup a smal 
an a simpl a possible I howeve yo fin tha yo nee t 
mak us o  stac mor tha  doze o s level deep yo mus 
creat you ow stac o yo wil b subjec t th wrat o th 
compute Gods Resultin i  cras an bur a th mos 
inopportun time 

I i no tha har t creat you ow stack Firs yo mus 
decid ho muc stac yo wil need Microsof use t sa tha 
51 byte wa neede t servic DO an BIO functions Tha ha 
bee creepin u ove th years Thes day 102 byte i 
considere  safe are t b in yo shoul ad 100 byte o 
stac spac t you o interna requirement i yo allo othe 
interrupt t interrup you servic routine 

I yo d no allo an othe interrupt t occu insid you 
interrupt the yo don' nee t worr abou th stac 
requirement o outsid code Yo onl nee t worr abou you 
ow stac requirements 

Onc yo decid ho muc stac yo need yo mus decid wher 
yo wil pu i i memory Th proble wit th interrup stac 
i tha i mus b  fixe are o memory Yo neve kno whe 
th interrup wil happen s th memor mus b ther read an 
waitin fo th interrup t happen Also hea allocatio i  
ru-tim function s yo canno cal i insid th interrup 
procedure Tha mean tha yo mus allocat th stac a fixe 
memor tha neve change location Th easies wa t d thi i 
t pu i i th dat segmen a  globa variable.

B havin i i th dat segment i i predefine an i i 
alway ther waitin fo you 

Her i a example:

     va MyStack:array[0..1000 o word;
         OldStack:pointer;  
     procedur MyInt Interrupt;
     begin
       asm
         mo wor pt [OldStack+2],s  {sav th curren stack}
         mo wor pt [OlStack],ss
         mo ss,SE @Mystac           {se u ou ow stack}
         mo sp,OFFSE @MyStack+200    not tha th stac} 
       end;                             start a en o array} 

       {...you cod here...}

       as   
         mo sp,wor pt [OldStack]    {restor origina stack}
         mo ss,wor pt [OldStack+2]   
       end;
     end;


Not tha i yo r-enable interrupt yo mus disabl th 
interrupt befor changin th stac pointer Thi i critical 
Failur t d s wil caus th compute t cras an bur a th 
stac ma b pointin t th wron plac i memor i th 
interrup happen i th middl o th chang over.


Anothe are t plac th stac i t pu i o th heap Thi i 
simila t havin i i th dat segment excep tha yo woul 
hav  pointe i th dat segmen pointin t th arra o th 
hea an yo woul ge th addres fro th pointe rathe tha 
gettin th offse o th array Yo mus howeve allocat th 
stac o th hea befor yo allo th interrupt t happen i 
mus sta i effec a lon a th interrupt routin i i 
effect Th advantag i tha yo ca recove th memor use i 
yo n longe nee th interrup servic routine 


Her i a example:

     typ StackArra  array[0..1000 o word;
     va MyStack:^StackArray;
         OldStack:pointer;  
     begin
       new(MyStack);
     end;

     procedur MyInt Interrupt;
     begin
       asm
         mo wor pt [OldStack+2],s   {sav th curren stack}
         mo wor pt [OlStack],ss
         mo ss,wor pt [Mystac]      {se u ou ow stack}
         mo sp,wor pt [MyStack+2     not tha th stac} 
         ad sp,2000                     start a en o array} 
       end;                             

       {...you cod here...}

       as   
         mo sp,wor pt [OldStack]    {restor origina stack}
         mo ss,wor pt [OldStack+2]   
       end;
     end;



 Mor Efficient Interrupt:

Whil ther i n question tha th Interrup directiv availabl 
i Turb Pasca make writin a Interrupt servic routine 
easier i doe cos  bi i overhea o th stac an i cod 
generated Whe al yo wan t d is incremen  variabl an 
ge out i ca b  bi wasteful  mor efficient wa t writ 
th servic routin woul b t d i entirel i assembler Wit 
th adven o th buil i assemble availabl i versio 6. o 
Turb Pascal thi become eve easier I fact wit that ther 
become les o  reaso t us th Interrup directiv eve i 
mor comple interrup servic routines.


 Simpl IS:

Th followin i  simpl uni tha ca b include i you 
program whic provide  tic counte tha i simila t th 
GetTickCoun functio i Windows I provide  counte whic 
tell yo ho lon th progra ha bee runnin i milliseconds 
Onc ever cloc tic th counte get 5 adde t it 

{---------------------------------------------------------------}
 Thi Uni wil trac i millisecond ho lon th progra ha  
 runnin sinc i wa turne o (simila t th Window        } 
 GetTickCoun functio) Th resolutio i 55mӮ Tha is 55m }
 i adde t th coun o eac syste cloc tick              }
{---------------------------------------------------------------}

{$R-,S-,I-,O-}
uni Ticker;
interface

cons TickCoun  longin  0;

implementation
use dos;

var Old1Cvec:pointer    {storag fo previous $1 in vector}
var ExitSave : pointer  storag fo previous exi procedur}

procedure TickerExit; far;
begin
  SetIntVec($1C,Old1Cvec)  {restor th previou exi procedur}
  ExitProc := ExitSave     {o exi fro th program}
end;

{Thi i th interrupt servic routine}
procedure TickerHook; far; assembler;
asm
  push d               {sav th curren registers}
  push ax
  mov ax,SEG @Data      {ge th T dat segment}
  mov ds,ax
  add word ptr [TickCount,55   {ad 5 to TicCount} 
  jnc @done
  inc word ptr [TickCount + 2  {(it'  longint)}

 @done:                                     
  pushf                 {pus flag t simulat interrup call}
  call dword ptr [Old1Cvec]   cal th previou cloc vector}
  pop ax                {restore th save regs}
  pop ds                                    
  iret                  {retur fro th interrupt}
end;

{----------}
begin
  GetIntVec($1C,Old1Cvec)    {sav curren cloc in vector}
  ExitSave := ExitProc       {sav curren exi proc}
  ExitProc := @TickerExit    {pok i ou ow exi proc}
  SetIntVec($1C,@TickerHook) {pok i o ow cloc in vector}
end.


Not tha a IRE instructio i use insid th procedur 
instea o relyin o th norma procedur return Thi i 
becaus withou th Interrup directive th compile wil 
generat  RE instruction bu a interrup servic routine mus 
alway en wit a IRE instructio s tha th origina flag 
ar pope of th stack Thu th procedur RE instructio wil 
b ignore sinc th IRE instructio i code ahea o it.

On potentia proble wit codin th wa show abov i tha th 
stac i use fo th cal t th previou interrup vecto s 
tha i ca b serviced Normall thi i no  problem bu i 
stac spac i precious o i yo expec t chai t  lo o 
littl routine lik this i ma b  problem On wa t solv 
th proble i t dispos o everythin of th stac befor 
linking t th previou servic vector 

T d tha require storin th lin addres i th cod segmen 
rathe tha usin  variabl i th dat segment W d thi 
becaus withou th availabilit o th dat segment w canno 
acces th dat segmen pointer S w transfe i t th loca 
cod segmen befor disposin o th dat segment 


{Thi i a alternat interrupt servic routine}
procedure TickerHook; far; assembler;
asm
  push d                        {sav th curren registers}
  push ax
  mov ax,SEG @Data               {ge th T dat segment}
  mov ds,ax
  add word ptr [TickCount,55    {ad 5 to TicCount} 
  jnc @done
  inc word ptr [TickCount + 2   {(it'  longint)}

 @done:
  lds ax,[Old1Cvec              {ge preiou cl in vector}
  mov word ptr @Local,a         {sav i t  cod se var}
  mov word ptr @Local+2,ds
  pop a                         {restor registers} 
  pop ds
  jmp Dword ptr cs:[@Local      {g proces preious vector} 
 @Local: DD                     {loca cod segmen variable}     
end;


Ther i anothe simple wa t d thi tha relie o creatin 
anothe assemble procedur tha contain nothin mor tha  
cod segmen variable Th proble wit tha thoug i tha i i 
dependent upo al th procedure i th uni bein i th sam 
cod segment Tha ma no hol fo futur implementation o i othe version o Pascal I definitely won' wor i 
environments suc a Window whic disallo writin t th cod 
segment 

{Thi i a exampl cod se va interrupt servic routine}
procedur TickerVar far assembler;
asm
  D 0
end;
procedure TickerHook; far; assembler;
asm
  push d                        {sav th curren registers}
  push ax
  mov ax,SEG @Data               {ge th T dat segment}
  mov ds,ax
  add word ptr [TickCount,55    {ad 5 to TicCount} 
  jnc @done
  inc word ptr [TickCount + 2   {(it'  longint)}

 @done:
  pop a                         {restor registers} 
  pop ds
  jmp Dword ptr cs:[@TickerVar  {g proces preious vector} 
end;

begin
  GetIntVec($1C,Old1Cvec)    {sav curren cloc in vector}
  asm
    le ax,[Old1Cvec               {ge pre cloc vector}
    mo wor pt cs:[TickerVar],a  {pok it addres int}
    mo wor pt cs:[TickerVar],e  {cod se var}
  end;
  ExitSave := ExitProc       {sav curren exi proc}
  ExitProc := @TickerExit    {pok i ou ow exi proc}
  SetIntVec($1C,@TickerHook) {pok i o ow cloc in vector}
end.


<eof>
