![]() | ![]() |
|
|
Breve guida ai TSR ed altro
Dunque, un TSR è un programma residente in memoria. Le operazioni da fare per caricarlo consistono nella gestione del vettore degli indirizzi INT.
La procedura standard consiste nel salvare l'indirizzo dell'INT da sostituire in una variabile, mettere il nostro ed infine ripristinarlo in uscita.
Lo schema è questo:
START PROC NEAR
jmp INSTALLAZIONE ;Etichetta di salto allo start
ROUTINE: ;Etichetta di inizio del blocco da eseguire quando avverrà la chiamata
push ax ;Push di salvataggio registri
push bx
push cx
push dx
push es
push si
push di
sti ;set interrupt
;LA NOSTRA ROUTINE DA ESEGUIRE COME TSR IN INT
;VA INSERITA QUI' (ESEMPIO: SCAMBIASCHERMO, OROLOGIO) ...
;E TERMINERA' QUI
cli ;clear interrupt
mov al,20h ;blocco sconosciuto
out 20h,al ; ma necessario
pop di ;ripristino dei registri
pop si
pop es
pop dx
pop cx
pop bx
pop ax
iret ;interrupt return
INSTALLAZIONE:
;LA PARTE INSTALLAZIONE E' STANDARD E NON VA MODIFICATA, A MENO ;CHE NON VENGANO MODIFICATE LE ETICHETTE UTILIZZATE ;DALL'ISTRUZIONE lea , PERCHE' SONO I PUNTI DI "RIFERIMENTO" PER LA ;MEMORIA!!!
mov ah,25h
mov al,1ch
lea dx,ROUTINE
int 21h
lea dx,INSTALLAZIONE
inc dx
int 27h
Questo tipo di soluzione non è particolarmente complessa, in quanto si usa un'interrupt periodico che attiva il TSR, ma è anche possibile ridefinire quasi tutti gli INT del sistema, compresa ad esempio la gestione del buffer o della tastiera...
Comunque tenete presente la seguente regola: mai chiamare nel vostro TSR altri INT DOS, pena il blocco totale del PC... ma del resto potete chiamare qualche routine del BIOS...
Inoltre il canale INT utilizzato ha un periodo molto basso, dovete quindi mettere in preventivo di rallentarne la velocità magari con l'uso di una variabile di supporto che serve a fare saltare alcune volte l'esecuzione della procedura, come nell'esempio completo che segue e che consiste nello spostare il video periodicamente (il valore di T non interessa in questa sede):
PAGE ,132 ; (CTRL-OH) IBM PC PRINTER CONDENSED MODE
TITLE SKELCOM - SAMPLE.COM STYLE ROUTINE
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG,DS:CSEG,SS:CSEG,ES:CSEG ;ALREADY SET BY DOS LOADER
ORG 100H ;SKIP TO END OF THE PSP
ENTPT: JMP START ;COM FILE ENTRY ALWAYS AT 100H
xsaltare db 050h ;QUESTA E' LA NOSTRA VARIABILE DI SUPPORTO
START PROC NEAR
jmp INSTALLA ;SALTA AD INSTALLA PER INSTALLARE LA ROUTINE DI INT
INVERTI:
push ax
push bx
push cx
push dx
push es
push si
push di
dec xsaltare
jnz SALTA_INT
mov xsaltare,050h
sti
mov ax,0b800h
mov es,ax
mov si,0
mov di,158
mov dx,25
ciclo2: mov cx,80
ciclo:
mov bl,es:[di]
mov al,es:[si]
mov es:[si],bl
mov es:[di],al
inc si
dec di
loop ciclo
add si,80
add di,240
dec dx
jnz ciclo2
SALTA_INT:
cli
mov al,20h
out 20h,al
pop di
pop si
pop es
pop dx
pop cx
pop bx
pop ax
iret
INSTALLA:
mov ah,25h
mov al,1ch
lea dx,INVERTI ;NOME PER LA NOSTRA "ROUTINE"
int 21h
lea dx,INSTALLA
inc dx
int 27h
START ENDP
CSEG ENDS
END ENTPT
L'unica cosa da notare è la variabile xsaltare utilizzata per non effettuare la chiamata. Notare che salto esattamente la parte , perchè per evitare confusioni od errori preferisco evitare di saltare i push ed i pop, nonché la parte sti,cli,ecc. jumpando direttamente su IRET.
PAGE ,132 ; (CTRL-OH) IBM PC PRINTER CONDENSED MODE
TITLE SKELCOM - SAMPLE.COM STYLE ROUTINE
CSEG SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CSEG,DS:CSEG,SS:CSEG,ES:CSEG ;ALREADY SET BY DOS LOADER
ORG 100H ;SKIP TO END OF THE PSP
ENTPT: JMP START ;COM FILE ENTRY ALWAYS AT 100H
;insert constants and work area (data) here
vett db 100 dup(0)
msg1 db 'INSERISCI IL N. DI VALORI DA ORDINARE (MAX.100)',13,10,0
msg2 db 'INSERISCI I VALORI IN ESA (BYTE<FF)',13,10,0
ENDL db 13,10,0
save db 0
START PROC NEAR
;rileviamo il n. di elementi
mov SI,offset msg1
call stampastringa
call aquis8bit
mov cx,0
mov cl,dl
mov SI,offset msg2
call stampastringa
mov SI,0
INSERISCI:
call aquis8bit
mov vett[SI],dl
inc SI
loop inserisci
mov vett[SI],0FFh
mov cx,SI
dec cx
mov DI,offset vett
call boubble_sort
mov ah,4ch ; FINE DEL PROGRAMMA (DOS)
int 21h
; STAMPASTRINGA : procedura che stampa a video una stringa formato C
; INPUT : Registro SI (Offset stringa)
; REG DISTRUTTI: ax,bx,dx,SI
; REG RITORNATI: /
STAMPASTRINGA PROC NEAR
CICLO: mov dl,[SI]
cmp dl,0
jz FINE
inc SI
mov ah,2
int 21h
jmp CICLO
FINE: RET
STAMPASTRINGA ENDP
END START
; AQUIS8BIT : Procedura che aquisisce 2 n. esa e li memorizza
; INPUT : /
; REG DISTRUTTI: ax,dx
; REG RITORNATI: dl
AQUIS8BIT PROC NEAR
INSERISCI:
mov ah,1
int 21h
cmp al,13
jz INSERISCI
mov dl,al
mov ah,1
int 21h
cmp al,13
jz FINE
sub dl,30h
mov cl,4
shl dl,cl
sub al,30h
or dl,al
mov SI,offset endl
call STAMPASTRINGA
FINE: RET
AQUIS8BIT ENDP
END START
; BOUBBLE_SORT : procedura che ordina un array con tecnologia boubble sort
; INPUT : Registro DI (Offset array), cx (n.elementi)
; REG DISTRUTTI: ax,bx,cx,dx,SI,DI
; REG RITORNATI: /
BOUBBLE_SORT PROC NEAR
mov dx,cx
dec cx
CICLOES: mov di,0
CICLOIN: mov al,[SI+DI]
mov bl,[SI+DI+1]
cmp al,bl
jbe ok
mov [SI+DI],bl
mov [SI+DI+1],al
OK: inc DI
loop CICLOIN
mov cx,dx
dec dx
jnz CICLOES
RET
BOUBBLE_SORT ENDP
END START
RET ;NEAR RETURN TO DOS
START ENDP
CSEG ENDS
END ENTPT
START PROC NEAR
mov SI,0
mov DI,3840
mov ax,0b800h
mov es,ax
cicloes:mov cx,160
CICLO: mov al,es:[DI]
mov bl,es:[SI]
mov es:[SI],al
mov es:[DI],bl
inc SI
inc DI
loop CICLO
sub DI,320
cmp si,1920
jnz cicloes
RET ;NEAR RETURN TO DOS
START ENDP
CSEG ENDS
END ENTPT
lung dw 0
vet db 09,11,08,07,06,15,04,03,02,01,0ffh
mov si,0
mov ax,0
mov bx,0
;insert constants and work area (data) here
START PROC NEAR
conta: mov al,vet[si]
cmp al,0ffh
jz ordina
inc si
mov lung,si
jmp conta
ordina: mov si,0
ciclo: mov bl,vet[si]
cmp bl,vet[si+1]
jae nonmag
mov ah,vet[si+1]
mov vet[si],ah
mov vet[si+1],bl
nonmag: inc si
cmp si,lung
je ordina
jmp ciclo
;insert code here
RET ;NEAR RETURN TO DOS
START ENDP
CSEG ENDS
END ENTPT
;insert constants and work area (data) here
serpenteplus db '>OOOOO[1]'
serpente db ' '
quovadis db 2 ;PER IL MOMENTO CL
l_ovest dw 0 ,160,320,480,640,800, 960,1120,1280,1440,1600,1760,1920,2080,2240,2400,2560,2720,2880,3040,3200,3360,3520,3680,3840
l_est dw 158,318,478,638,798,958,1118,1278,1438,1598,1758,1918,2078,2238,2398,2558,2718,2878,3038,3198,3358,3518,3678,3838,3998
att1 dw 0FFFFh
att2 dw 0FFFFh
NORD equ 0
EST equ 1
SUD equ 2
OVEST equ 3
START PROC NEAR
mov ax,0b800h ;PUNTARE AL SEGMENTO VIDEO
mov es,ax
mov SI,2384
mov DI,0
mov quovadis,EST
mov cl,32
mov ch,serpente
;RICERCA POSIZIONE INIZIALE SERPENTE
POSIZIONE:
add SI,2
cmp es:[SI],cl
jnz POSIZIONE
CICLO:
;RANDOMIZE POSIZIONALE
mov dx,109
mul dx
add ax,583
cmp al,128
jbe DESTRA
;Casi Sinistri
cmp quovadis,EST
jz TO_NORD
cmp quovadis,SUD
jz TO_EST
cmp quovadis,OVEST
jz TO_SUD
jmp TO_OVEST
DESTRA:
cmp quovadis,NORD ;Casi di Destra
jz TO_EST
cmp quovadis,EST
jz TO_SUD
cmp quovadis,OVEST
jz TO_NORD
jmp TO_OVEST
TO_NORD:
mov quovadis,NORD
mov DI,SI ; aggiorno DI
sub DI,160 ; -160 S il carattere posizionato sopra
cmp DI,0 ; altrimenti esco dal segmento (e dal video)
jl TO_CICLO ; estraggo un'altra direzione
cmp es:[DI],cl ; la via S libera?
jnz TO_CICLO ; no, estraggo un'altra direzione
mov es:[DI],ch ; s, cancello il precedente
mov es:[SI],cl ; metto il serpente nella nuova pos.
mov SI,DI ; aggiorno il puntatore principale
call DELAY
call EXIT
jmp TO_NORD ;
TO_SUD:
mov quovadis,SUD
mov DI,SI ; aggiorno DI
add DI,160 ; +160 S il carattere posizionato sotto
cmp DI,3998 ; altrimenti esco dal segmento (e dal video)
jnc TO_CICLO ; estraggo un'altra direzione
cmp es:[DI],cl ; la via S libera?
jnz TO_CICLO ; no, estraggo un'altra direzione
mov es:[DI],ch ; s, cancello il precedente
mov es:[SI],cl ; metto il serpente nella nuova pos.
mov SI,DI ; aggiorno il puntatore principale
call DELAY
call EXIT
jmp TO_SUD
to_ciclo: jmp ciclo
TO_EST:
mov quovadis,EST
mov DI,SI ; aggiorno DI
add DI,2 ; +2 S il carattere posizionato a destra
mov BP,0
LIMITEST:
cmp DI,l_est[BP] ; altrimenti esco dal segmento (e dal video)
jz TO_CICLO
add BP,2
cmp BP,50 ; estraggo un'altra direzione
jnz LIMITEST
cmp es:[DI],cl ; la via S libera?
jnz TO_CICLO ; no, estraggo un'altra direzione
mov es:[DI],ch ; s, cancello il precedente
mov es:[SI],cl ; metto il serpente nella nuova pos.
mov SI,DI ; aggiorno il puntatore principale
call DELAY
call EXIT
jmp TO_EST
TO_OVEST:
mov quovadis,OVEST
mov DI,SI ; aggiorno DI
sub DI,2 ; -2 S il carattere posizionato a sinistra
mov BP,0
LIMITOVEST:
cmp DI,l_ovest[BP] ; altrimenti esco dal segmento (e dal video)
jz TO_CICLO
add BP,2
cmp BP,50 ; estraggo un'altra direzione
jnz LIMITOVEST
cmp es:[DI],cl ; la via S libera?
jnz TO_CICLO ; no, estraggo un'altra direzione
mov es:[DI],ch ; s, cancello il precedente
mov es:[SI],cl ; metto il serpente nella nuova pos.
mov SI,DI ; aggiorno il puntatore principale
call DELAY
call EXIT
jmp TO_OVEST
DELAY: mov att1,40h
mov att2,0FFFFh
EXTER: dec att2
jnz EXTER
dec att1
jnz exter
RET
EXIT: push dx
push cx
push bx
push ax
mov ah,02h ;controllo lo stato della tastiera
int 16h ;con l'INT 16h servizio 2...
cmp al,01h ;SHIFT S attivo?
jz FINE ;se s, esco
pop ax ;altrimenti ripristino
pop bx
pop cx
pop dx
RET ;e ritorno
FINE: pop ax ;altrimenti ripristino
pop bx
pop cx
pop dx
mov ah,4ch
int 21h
RET ;NEAR RETURN TO DOS
RET
START ENDP
CSEG ENDS
END ENTPT
Privacy |
Articolo informazione
Commentare questo articolo:Non sei registratoDevi essere registrato per commentare ISCRIVITI |
Copiare il codice nella pagina web del tuo sito. |
Copyright InfTub.com 2025