Newsgroup: it.comp.lang.pascal
Titolo: Programmi Residenti in Memoria (TSR)

Salve !
Vorrei sapere come realizzare dei programmi residenti in Memoria (Virus,
CatturaSchermo, etc.........)
Grazie
P.S. : Andrebbe bene, anche in linguaggio assembler.

, il giorno Tue, 29 Jul 1997
10:06:44 +0200 hai scritto:
#Salve !
#
#Vorrei sapere come realizzare dei programmi residenti in Memoria
(Virus,
#CatturaSchermo, etc.........)
#
#
#Grazie
#
#P.S. : Andrebbe bene, anche in linguaggio assembler.
#
Ciao Alessandro, 
la creazione di TSR in se' e' piuttosto semplice in pascal, ma puo'
diventarne molto complessa la gestione, a seconda di quello che si
vuole realizzare. Ti indico alcuni passi necessari alla creazione di
un tsr:
1) limitare la memoria occupata dal programma, con $M, es:
(*$M 1024,0,0*)
solitamente i programmi tsr non allocano memoria nell'heap e
utilizzano poco stack, quindi questa dovrebbe andare sempre bene.
2) creare un gestore di interrupt che serva per "attivare" il nostro
tsr. Questa operazione e' semplificata dalla direttiva Interrupt, che
si prende carico di ripristinare i registri alla fine della procedura
e di inserire un IRET. Volendo possiamo anche sapere i valori dei
registri. Ricordarsi di impostare come Far le procedure. Es:
procedure MyIntr; Far; Interrupt;
procedure MyIntr (Flags, CS, IP, AX, BX, CX, DX, SI, DI, DS, ES, BP);
Far; Interrupt;
il corpo di questa procedura contiene tutto il codice necessario a
compiere il lavoro che dovra' svolgere il tsr.
Normalmente viene inserito un codice del genere:
begin
  asm
    PUSHF
    CALL OldIntr
  end;
  ...
end;
per richiamare la vecchia routine dell'interrupt che abbiamo
intercettato (OldIntr ne e' il puntatore, vediamo dopo quando gli
viene assegnato un valore); infatti la sequenza assembly PUSHF e CALL
corrisponde a quella generata da INT. Il POPF e' svolto dall' IRET
presente nella routine puntata da OldIntr, quindi non ce ne dobbiamo
preoccupare.
Un problemino e' rappresentato dalla non rientranza del dos, che
impedisce a suddetto s.o. di chiamare un interrupt dos quando ne sia
gia' attivo uno. Per superare questo problema si puo' (all'interno
della procedura interrupt):
1. controllare se e' attivo un servizio dos e in caso affermativo non
richiamarne un altro.
2. non chiamare mai servizi dos.
il primo metodo e' molto complesso e non lo so affrontare, per cui ti
consiglio il (2). Devo dire che pero' non ho (stranamente) mai avuto
problemi anche utilizzando servizi dos dall'interno del gestore.
3) scrivere il corpo del programma tsr, salvando in OldIntr la vecchia
routine interrupt ed impostando la nostra nuova routine come gestore.
Quindi rendere residente il programma con Keep(0).
Normalmente vengono utilizzati i seguenti interrupt come attivanti:
1C	Orologio
9	Tastiera
C	Com1
B	Com2
D	Hard disk
E	Floppy disk
F	Stampante
(i valori possono variare a seconda del sistema)
Un piccolo esempio potrebbe essere quello di un tsr che visualizza,
ogni secondo, l'orario nell'angolo in alto a destra dello schermo:
(*$M 1024,0,0*)
program TsrClock;
uses CRT, DOS;
var x, y, h, m, s, c, olds: Integer; 
  (* globali per non usare lo stack *)
    OldIntr: Pointer;
procedure MyIntr; Far; Interrupt;
begin
  asm  (* chiama vecchio gestore *)
    PUSHF
    CALL OldIntr
  end;
  GetTime (h, m, s, c);
  (* questa procedura viene chiamata 18,2 volte al secondo
  quindi controlliamo di scrivere l'orario solo una volta al secondo
  *)
  if s<>olds then begin
    olds:= s;
    x:= WhereX;
    y:= WhereY;
    GotoXY (70, 1);
    Write (h:2, ':', m:2, ':', s:2);
    GotoXY (x, y);
  end;
end;
begin
  (* $1C = Clock
  Preleviamo l'indirizzo del gestore di $1C *)
  GetIntVec ($1C, OldIntr);
  (* Impostiamo la nostra nuova proc. come gestore *)
  SetIntVec ($1C, @MyIntr);
  (* Mettiamo residente il programma *)
  Keep (0);
end.
Non l'ho testato per cui spero di non aver dimenticato qualcosa!
Fammi sapere se non hai capito qualcosa
CIAO
REMO FRANCESCHELLI - ITIAV 4a Info.
http://www.geocities.com/SiliconValley/Lakes/7668
(Programmazione in Pascal)
** Concentrazione = Forza **

[...]
Premetto subito che non ho idea di come possa funzionare un programma
del genere e che probabilmente sarebbe del tutto inutile che qualcuno
provasse a spiegarmelo. Comunque x curiosita' ho provato a compilarlo
con TP7. Xo' non gli piace Far; Interrupt; (dice che dopo il primo
vuole BEGIN) e vuole h, m, s, c ti tipo Word. Provando a togliere Far
e mettendo Word invece di Integer lo compila, ma provando a eseguirlo
zompa tutto.
Non e' che se ti capita potresti darci un'occhiata? (Se hai tempo, era
solo x vederlo funzionare...)
Ciao e grazie,
Luigi
--
|\/\/\/|              |\/\/\/|  Luigi Balduzzi
 \    /    |\/\/\/|    \    /   studente, 4 liceo scientifico
 | II |\/\/| .__. |\/\/| II |   Genova, Italy
 | II | II | |++| | II | II |
 |____|____|_|++|_|____|____|   e-mail: 
jy...@usa.net
==============================  powwow: 
gi...@genova.it

jy...@usa.net
 (Luigi Balduzzi), il giorno Mon, 08 Sep 1997 14:04:51 GMT
hai scritto:
#>(*$M 1024,0,0*)
#>program TsrClock;
#>[...]
#
#Premetto subito che non ho idea di come possa funzionare un programma
#del genere e che probabilmente sarebbe del tutto inutile che qualcuno
#provasse a spiegarmelo. Comunque x curiosita' ho provato a compilarlo
#con TP7. Xo' non gli piace Far; Interrupt; (dice che dopo il primo
#vuole BEGIN) e vuole h, m, s, c ti tipo Word. Provando a togliere Far
#e mettendo Word invece di Integer lo compila, ma provando a eseguirlo
#zompa tutto.
#Non e' che se ti capita potresti darci un'occhiata? (Se hai tempo,
era
#solo x vederlo funzionare...)
#Ciao e grazie,
#Luigi
#
Ciao, hai ragione, infatti ho ricevuto delle mail dove mi veniva
chiesto proprio dello che dici tu.
Colgo quindi l'occasione per ricopiare sul ng le risposte che ho dato
a queste persone per evitare che qualcun'altro perda tempo
inutilmente:
------------------------------------------
hai ragione, il problema e' che non si possono associare le direttive
Interrupt e Far (forse interrupt la "comprende" gia?? mah!). Per
risolvere il problema e star sul sicuro, modifica quella riga cosi':
...
(*$f+*)
procedure MyIntr; Interrupt;
...
Inoltre c'e' un altro errore nella definizione delle variabili, che
devono essere di tipo word (per la chiamata a GetTime):
var x, y, h, m, s, c, olds: Word;
dunque, a questo punto ti devo delle spiegazioni: in realta' io quel
tsr non l'ho *mai* testato nella sua versione "finale". Infatti, come
ben sai, se il programma non fosse funzionato bene, avrei dovuto tutte
le volte riavviare il computer per scaricarlo dalla memoria, e questa
soluzione e' un po' scomoda. Per testarlo, ne ho fatta una versione
leggermente diversa che pero' non si installa come tsr ma modifica
solamente il vettore di interruzioni e poi lo ripristina prima di
terminare l'esecuzione.
Cioe', al posto di keep(0), ho messo:
ReadLn;
SetIntVec ($1C, OldInter);
Con questo codice da me funziona tutto bene (si puo' scrivere nel
readln) e non si blocca niente, mentre, a quanto pare, dopo
l'installazione come tsr si verificano quei problemi.
Passiamo dunque ad esaminare questi problemi. Nella versione
"originale" del programma (quella sul ng) io avevo avvertito che il
programma poteva non funzionare correttamente, ed in effetti e'
proprio il comportamento che dovrebbe in teoria avere. Ti riscrivo
quello avevo scritto sul ng:
Il problema e' la "non rientranza" del dos, cioe' che questo s.o. e'
programmato (talmente male) in modo da non permettere una chiamata ad
un interrupt dos quando ne sia gia attivo (in esecuzione) un altro,
pena il probabile crash del sistema.
Per riuscire a superare il problema, si puo' (1) non chiamare mai un
interrupt dos oppure (2) non chiamare un interrupt dos quando ne e'
attivo un altro.
Io non sono capace di fare il (2), quindi l'unica e' di *non* chiamare
mai, all'interno della routine di interrupt, un servizio dos. Il
nostro programma invece chiama proprio GetTime, che a sua volta chiama
Int 21h servizio ... (non mi ricordo...) che quindi provoca un crash.
La chiamata a WriteLn invece non dovrebbe avere problemi in quanto con
il Pascal 7 non viene utilizzato il servizio dos per la
visualizzazione ma viene scritto direttamente sulla memoria video. Se
hai TP 6 credo che invece venga utilizzato il servizio dos e ti devi
fare tu una procedura che scriva direttamente nella mem. video.
Per fare solo un test, potresti modificare il programma togliendo la
chiamata a GetTime e facendogli visualizzare nell'angolo a destra un
numero intero che viene incrementato ad ogni chiamata.
----------------------------------------
C'e' anche un metodo per disinstallare i TSR, se qualcuno e'
interessato puo' contattarmi che forse in due ce la facciamo :-)
---------------------------------------
Al prossimo upload al mio sito ho deciso di mettere alcuni TSR, vi
faro' poi sapere appena lo faccio.
Ciao,
