o6i7ij
  Revenim asupra tehnicilor de scriere a unui program TSR cu citeva exemple.
  Deoarece sistemul de operare DOS nu are facilitati de multitasking, se recurge deseori la folosirea unor programe rezidente(TSR-Terminate and Stay
  Resident) pentru a compensa aceasta lipsa. Pastrarea mai multor programe in memorie in acelasi timp ofera unele avantaje, care rezulta dintr-o eventuala conlucrare a acestora. Fara cunoasterea tehnicilor de realizare, implementarea lor nu poate avea loc.
 Crearea programelor TSR
 In cadrul sistemului DOS, in mod obisnuit programele se incarca in memorie si se lanseaza in executie cu ajutorul intreruperii INT 21h, cu subfunctia 4BH.
  Dupa terminarea executiei ele apeleaza intreruperea INT 20h, sauINT 21h cu subfunctia 4CH (eventual subfunctia 00H), redind controlul procesului parinte si eliberand zona ocupata. Pentru a se pastra in memorie la terminarea executiei, programele trebuie sa urmeze alta cale. Pot folosi ori intreruperea
  INT 27H (Terminate and Stay Resident), ori intreruperea INT 21H, cu subfunctia
  31H(Keep Process). Ultima este mai des folosita datorita faptului ca ofera posibilitatea pastrarii in memorie numai a acelei parti din program care contine codul de actiune, partea care contine codul de instalare putindu-se elibera din memorie. Aceasta se datoreaza faptului ca se apeleaza INT 21H, cu subfunctia 49H, care permite o realocare a zonei ocupate de program cu o dimensiune mai mica. La utilizarea intreruperii INT 27H, toata zona folosita 
  de program ramine ocupata. Ambele intreruperi restaureaza valoarea vectorilor de intrerupere pastrati in PSP (INT 22H : adresa unde se realizeaza saltul dupa terminarea executiei programului, INT 23H : adresa rutinei de tratare CTRL-C,
  INT 24H adresa rutinei de tratare eroare critica), dupa care transfera controlul procesului parinte. Evenimentele ce se petrec in sistem nu afecteaza programul rezident instalat. Trebuie sa tinem insa cont de faptul ca, daca programul rezident este instalat cu ajutorul unui alt program, programul nefiind rezident dupa terminarea executiei acestuia, sistemul elibereaza zona lui si astfel apare un gol in memorie ducind la fragmentarea acesteia.
 
 Activarea programelor TSR
 Pentru a activa programe rezidente exista mai multe posibilitati. Toate acestea se bazeaza, in general, pe declansarea unui eveniment exterior programului in curs de executie, care poate sa transfere controlul la programul rezident. Cele mai folosite metode de activare vor fi descrise in continuare, insotite de explicatiile necesare acolo unde e cazul.
*****Activarea periodica cu ajutorul Timerului****************************
 Prin redirectarea intreruperii INT 08H, se poate ajunge la o activare periodica a programului rezident. Aceasta intrerupere este provocata hard in mod periodic de catre timer-ul calculatorului de circa 18.42 de ori pe secunda. PC-urile, de regula, folosesc mai multe timere, dar folosirea lor necesita cunostinte suplimentare despre sistem si este destul de incomoda.
  Scopul lor in general este masurarea timpului in sistem. Pentru apelarea programului rezident se poate folosi si intreruperea INT 1CH, care este apelata de fiecare data de intreruperea INT 08H. Intial intreruperea INT 1CH contine o simpla instructiune de revenire, IRET. Codul nou asociat acestei intreruperi va trebui sa contina : la inceput instructiuni pentru salvarea registrilor microprocesorului, iar inainte de IRET instructiuni pentru restaurarea registrilor.
*****Activarea cu ajutorul intreruperilor de tastatura**********************
 La apasarea unei taste, este provocata o intreruperea hard INT 09H.
  Vectorul de intrerupere indica de obicei spre zona ocupata de rutinele BIOS in ROM sau spre zona ocupata de IO.SYS. Programul rezident poate redirecta aceasta intrerupere, avind posibilitatea sa conunice direct cu controllerul tastaturii prin porturile 60H-6FH. Daca in anumite situatii, intreruperea nou instalata INT 09H, nu va apela intreruperea veche INT 09H, trebuie sa semnaleze controllerului de intreruperi terminarea intreruperii. Pina nu se 
  face  acest lucru, toate intreruperile hard sunt inhibate. Semnalarea explicita a 
   terminarii intreruperii este caracteristica tuturor intreruperilor hard.
  Intreruperea INT 09H depune codul corespunzator tastelor apasate (in afara  de Ctrl+Alt+Del si, eventual alte combinatii) intr-un buffer circular.
  Adresa de inceput actuala a bufferului este memorata la adresa 0000:041AH iar adresa de sfirsit la adresa 0000:041BH in zona de date folosita de BIOS.
  Octetii de la adresele 0000:0417H, 0000:0418H, 0000:0419H sint folositi pentru a retine starea curenta a tastelor CTRL, ALT, SHIFT si alte informatii.
  Continutul lor arata in felul urmator :
  0000:0417H : bitul 7=1:insert activ; bitul 6=1:CapsLock activ; bitul 5=1:NumLock activ; bitul 4=1:ScrollLock activ; bitul 3=1:Alt apasat; bitul 2=1:Ctrl apasat; bitul 1=1:Shift sting apasat; bitul 0=1:Shift drept apasat;
  0000:0418H : bitul 7=1:Insert apasat; bitul 6=1:CapsLock apasat; bitul 5=1:NumLock apasat; bitul 4=1:ScrollLock apasat; bitul 3=1:Pause activ.
  Se folosesc numai la tastaturi cu 101-102 taste: bitul 2=1:SysReq apasat; bitul 1=1:Alt sting apasat; bitul 0=1:Ctrl drept apasat;
  0000:0419H:Se foloseste pentru retinerea temporara a codului introdus de la 
   partea numerica a tastaturii pina cind se elibereaza tasta Alt, eveniment dupa care valoarea retinuta se inlocuieste cu 0, iar codul ASCII se depune in bufferul de tastatura.
  Codurile depuse in buffer se pot examina si elimina de acolo cu ajutorul intreruperii INT 16H. Daca redirectam aceasta intrerupere in loc de intreruperea
  INT 09H, avem posibilitatea activarii programului rezident numai cind programul in curs de executie asteapta apasarea unei taste sau testeaza daca a fost apasata o tasta. O alta posibilitate ar fi redirectarea intreruperii INT 1BH apelata 
  la  apasarea tastelor CTRL-BREAK sau CTRL-C de catre rutina de intrerupere INT 09H.
  Cu ajutorul acestor combinatii de taste poate fi intrerupt un program in mod 
   obisnuit si se poate reda controlul sistemului de operare.
*****Activare cu ajutorul intreruperii INT-10H*****************************
Programele utilizator afiseaza date pe ecran in mod obisnuit cu ajutorul  intreruperii INT 10H. Prin redirectarea intreruperii poate fi filtrata data 
   ce ar urma sa fie afisata de catre programul rezident, dupa care se poate apela vechea intrerupere INT 10H, care realizeaza afisarea. Programele utilizator care scriu direct pe ecran nu pot fi intrerupte pe aceasta cale.
******Activare cu ajutorul unei intreruperi soft oarecare******************
Exista mai multe posibilitati de activare. Se pot redirecta intreruperile soft folosite de CON sau LPT sau se poate extinde intreruperea INT 21H. Acest lucru ar insemna implementarea si integrarea unor noi subfuctii la cele existente.
  Inainte de apelul propriu-zis al noii subfunctii se atribuie valori  corespunzatoare in anumiti registri, dupa care intreruperea va deosebi noua 
   subfunctie de cele anterioare si va executa codul corespunzator noii subfunctii.
  Intreruperea INT 28H este activata de catre DOS pe cale soft la orice apel de 
   scriere CON, si poate folosi la fel pentru activarea programului TSR. Aceasta intrerupere are avantajul de a fi capabila sa apeleze orice functie DOS a  intreruperii INT 21H, in afara subfunctiilor 01H-0CH. O posibilitate interesanta 
   ar fi folosirea intreruperii multiplexate INT 2FH. Aceasta intrerupere ofera de fapt, un standard pentru scrierea programelor rezidente. Noul program rezident se insereaza in lantul de programe rezidente. Fiecare program rezident are un numar de multiplexare cu ajutorul caruia poate fi referit.
*******Activare cu ajutorul unei instructiuni CALL sau JMP****************
In acest caz se stabileste de la inceput adresa de memorie la care se va depune adresa programului rezident instalat. Printr-un apel indirect, folosind aceasta adresa se va putea activa codul programului. Pentru retinerea adresei s-ar putea 
   folosi octetii nefolositi din zona 0000:04F0H-0000:04FFH. 
 Verificarea instalarii programelor TSR
Daca un program TSR este instalat deja in memorie nu are nici un senns sa-l 
  mai  instalam inca o data si, de aceea, trebuie sa putem sa ne dam seama daca este 
  sau  nu instalat. Acest lucru poate fi aflat pe de o parte prin parcurgerea listei 
   de MCB (MEMORY CONTROL BLOCK), cautind numele programului rezident, la un MCB al carui proprietar nu este programul curent, pe de alta parte s-ar putea folosi 
   intreruperea multiplexata INT 2FH. Inainte de apel, registrul AH trebuie sa 
   contina codul de identificare a programului rezident iar AL valoarea 00H.
  La intoarcere daca AL=00H programul nu este instalat, daca AL=01H programul 
  nu poate fi instalat, iar daca AL=FFH programul este instalat. Desigur, intreruperea
  INT 2FH trebuie sa fie redirectata in prealabil de catre programul TSR, iar 
  codul  de identificare trebuie sa difere de codul de identificare al altor programe 
  TSR care folosesc intreruperea INT 2FH (daca verificarea instalarii programului 
   rezident este facuta de catre o noua instanta a programului putem folosi,  eventual, faptul ca datele asemenea din instanta instalata se afla la acelasi 
   deplasament ca si in instanta care se ruleaza). Daca programul rezident se  activeaza pe cale soft cu ajutorul unei intreruperi nefolosite de sistem
  (de exemplu intreruperea INT 33H pe un sistem fara mouse), se poate testa valoarea vectorului de intreruperi (de exemplu: valoarea 55FF:FF55H semnaleaza program TSR neinstalat;la fel daca octetul adresat contine o instructiune IRET aceasta semnaleaza program TSR neinstalat). Daca intreruperea este folosita 
  si  de sistem se poate implementa o subfunctie, cu care se poate afla daca programul rezident a fost sau nu instalat. Ultima metoda pe care o propunem ar fi folosirea 
  zonei zonei ICA (Interapplication Communication Area ) situata intre adresele 
  0000:04FOH-0000:04FFH din zona de date BIOS. Aceasta zona nu este folosita de catre BIOS. Un program rezident isi poate lasa la instalare, semnatura in zona.
  Daca sunt mai multe programe rezidente care vor sa foloseasca aceasta zona, 
  pot sa apara probleme. Mentionam ca aceasta zona poate fi folosita si pentru schimbarea datelor intre programe.  
 Comunicarea cu programele TSR
  
  Pentru comunicarea cu programele TSR se poate folosi intreruperea INT 21H de exemplu (trebuie redirectata). Datele scurte se transmit in registri; pentru date mai voluminoase se transmite adresa zonei care contine datele in doi  registri (segment:offset).
 Problema nereentrantei DOS
 Sistemul de operare DOS nu are o posibilitate de a afla numarul de octeti disponibili pe stiva folosita de programele utilizator; programele utilizator, 
  nu  cunosc necesarul de stiva al unui apel sistem. De aceea, pentru mai multa  siguranta , fiecare folosesc stive proprii, la adrese fixe de memorie in  zona lui de program. La fiecare apel de intrerupere DOS se executa un  schimb de stive intre stiva sistem si stiva program, in urmatorul mod :
 MOV AX,CS 
  CLI 
  MOV CS:USER_SS,SS
  MOV CS:USER_SP,SP
  MOV SS,AX
  MOV SP,SYSTEM_PSP
  STI
La revenire se efectueaza operatia inversa si se restaureaza stiva program
  Sistemul DOS foloseste 3 stive :
  Stiva 1: este folosita de INT 25H, INT 26H, INT 21H, sub functia 00H respectiv subfunctiile de la ODH in sus
  Stiva 2: este folosita de INT 21H cu subfunctiile 01H-0CH
  Stiva 3: este folosita intern de functiile sistem pentru apeluri recursive 
  Daca in cursul tratarii unei intreruperi sistem se activeaza un program TSR care, la rindul lui apeleaza o intrerupere DOS care foloseste aceeasi stiva 
   ca si intreruperea care a fost suspendata de programul TSR, datele intreruperii 
  
  DOS suspendate vor fi deteriorate, iar sistemul se va bloca cu siguranta.
  De aceea se spune ca sistemul DOS nu este reentrant.
  Aceasta imposibilitate de a apela in anumite momente intreruperi DOS de catre programele rezidente necesita sa se cerceteze daca sistemul este in cursul  tratarii unei intreruperi DOS sau nu.
  Exista o variabila a carei adresa se poate afla cu ajutorul intreruperii DOS
  INT 21H, cu subfunctia 34H care, in perechea de registre ES:BX, furnizeaza  acesta adresa (IN_DOS). Ea trebuie sa fie salvata la inceputul instalarii, caci 
  
  DOS nu este reentrant. Valoarea acestei variabile se mareste cu 1 inaintea fiecarui apel DOS, si se scade cu 1 dupa terminarea apelului. Daca valoarea este 0, atunci nu exista nici o intrerupere DOS suspendata si se poate activa 
   programul TSR; altfel programul TSR isi amina activarea. O posibilitate  de a activa programe rezidente in timp ce interpretorul de comenzi COMMAND.COM este activ se poate realiza cu ajutorul intreruperii DOS INT 28H (incepind cu
  DOS 5.00) si cu ajutorul INT 2FH, cu subfunctia in AH=1680.
  Aceasta este apelata periodic de catre sistem atunci cind sistemul asteapta apasarea unei taste. Continind initial doar un simplu IRET, nu apare pericolul reentrantei. In afara de problema reentrantei sistemului mai trebuie sa tinem seama si de alte considerente. Activarea unui program TSR nu trebuie sa se efectueze in timpul tratarii unei erori critice (DOS_CRITICAL_ERROR).
  DOS foloseste o variabila separata pentru semnalarea faptului ca sistemul este in cursul tratarii unei erori critice (in cazul acesta valoarea variabilei este diferita de 0). Adresa acestei variabilei se poate obtine cu intreruperea INT 
  5DH, cu subfunctia 06H. Rezultatul se obtine in perechea de registre ES:BX. Nu este reentranta nici intreruperea hard a discului, INT 13H.
  O metoda de rezolvare a problemei reentrantei sistemului ar putea sa fie  redirectarea de catre programul rezident a tuturor intreruperilor DOS si  activarea in prealabil a programului rezident inaintea apelarii vechii intreruperi DOS (la fel se poate redirecta si intreruperea INT 13H).
  O alta metoda care se poate incerca ar fi salvarea unei zone din stivele  sistem.
  Problema reentrantei are si un aspect mai putin relevant, dar la fel de  periculos. Rutina rezidenta poate fi intrerupta de ea insasi, de mai multe ori.
  Daca se permite acest lucru, atunci este indicat ca rutina sa aiba prevazuta 
  o  stiva separata pentru apeluri recursive. Acest lucru este asemanator  modului in care sistemul DOS trateaza inreruperile hard care, necunoscind  starea stivelor programelor intrerupte, pot folosi stive separate fixate  cu directiva STACKS in CONFIG.SYS.
 Setarea adresei segmentului de date
Pentru ca programele rezidente sa poata accesa variabilele din program trebuie 
   sa salveze vechiul continut al registrului DS si sa-l redirecteze spre zona 
   programului rezident .
  La un program COM se foloseste urmatoarea secvente de cod: 
  PUSH DS
  PUSH AX
  MOV AX,CS
  MOV DS,AX
  ................
  POP AX
  POP DS
  La un program EXE se foloseste urmatoarea secventa de cod:
  PUSH DS
  PUSH AX
  MOV AX,@DATA
  MOV DS,AX
  .................
  POP AX 
  POP DS 
  
  Probleme legate de PSP si DTA
 Daca programul rezident efectueaza operatii cu discul,datorita faptului ca 
  
  DOS foloseste un singur DTA (Disk Transfer Area), ca sa nu pericliteze integritatea datelor folosite de program (daca si acesta folosea DTA-ul) trebuie sa salveze 
   adresa DTA-ului actual si sa seteze adresa DTA-ului folosita de el. Dupa terminarea 
   executiei, inaintea redarii controlului programului intrerupt, trebuie sa restaureze adresa DTA-ului salvat. Datorita faptului ca PSP-ul(Program Segment Prefix) 
  contine tabela handlerelor folosite de program, si DOS-ul recunoaste un singur PSP actual, intr-o maniera asemanatoare trebuie salvat PSP-ul programului intrerupt si stabilit ca PSP actual PSP-ul programului. Toate aceste manevre se efectueaza cu ajutorul intreruperilor DOS:
  Salvare DTA:
  -intreruperea INT 21H, subfunctia 2FH, depune adresa zonei DTA curente in  registri ES:BX.
  Setarea DTA actual:
  -intreruperea INT 21H, subfunctia 1AH, inainte de apel trebuie fixata  adresa noii zone in perechea de registrii DS:DX.
  Salvarea PSP:
  -intreruperea INT 21H, subfunctia 62H, depune adresa de segment al PSP-ului in registrul BX, adresa de deplasament fiind 0.
  Setare PSP actual:
  -intreruperea INT 21H, subfunctia 50H, inainte de apel adresa noului PSP trebuie fixata in registrul BX.
Tema :
 -sa se scrie programul "ceas.c" care sa afiseze timpul curent luat 
  din RTC
  (Real Time Clock), in coltul de sus al ecranului. Se rescrie intreruperea INT 
  1CH, care va apela periodic AfisText(Ceas), Ceas fiind o rutina care apeleaza la 
  rindul ei intreruperea INT 1AH, care regaseste(in format BCD) valoarea timpului RTC.
  Pentru conversie din formatul BCD in caracter se foloseste functia BcdInChar.
  -sa se scrie programul rokey.c care permite introducerea de la tastatura a literelor speciale a limbii romane, redefinind niste combinatii de taste, cu ajutorul unui tabel TabelTaste. Pentru a putea folosi programul, trebuie sa adaugam in fisierul CONFIG.SYS linia COUNTRY= 01, 852, COUNTRY.SYS, iar in
  AUTOEXEC.BAT comenzile MODE CON CP PREP=((852)EGA.CPI);MODE CON CPSEL=852; 
  KEYB us. Programul afiseaza un mic help pe ecran la pornire. Redirecteaza intreruperea INT 16H; vechea intrerupere se pune in locul intreruperii INT 80H, nefolosita de sistem. Programul poate fi dezinstalat din linia de comanda printr-un nou apel al programului, sau cu combinatia de taste ALT-Z. Programul 
  faptului testeaza daca este sau nu rezident, respectiv se dezinstaleaza.
TabelTaste =
  ( (Cod_Ascii:0 ; Cod_Scan:30 ; Cod Nou:198), AALT AS
  (Cod_Ascii:1 ; Cod_Scan:30 ; Cod_Nou:199), ACRTL AS
  (Cod_Ascii:0 ; Cod_Scan:23 ; Cod_Nou:215), AALT IS
  (Cod_Ascii:9 ; Cod_Scan:23 ; Cod_Nou:140), ACRTL IS
  (Cod_Ascii:0 ; Cod_Scan:18 ; Cod_Nou:182), AALT ES
  (Cod_Ascii:5 ; Cod_Scan:18 ; Cod_Nou:131), ACRTL ES
  (Cod_Ascii:0 ; Cod_Scan:31 ; Cod_Nou:184), AALT SS
  (Cod_Ascii:19; Cod_Scan:31 ; Cod_Nou:173), ACTRL SS
  (Cod_Ascii:0 ; Cod_Scan:20 ; Cod_Nou:221), AALT TS
  (Cod_Ascii:20; Cod_Scan:20 ; Cod_Nou:238) ACTRL TS;
  -studiati programul t3.c+t3.asm, functiile sale si modul de implementare