page 60,132 title "CLOCK riprogrammazione int 1ch ;*************************************************************************** ; CLOCK.ASM ;--------------------------------------------------------------------------- ;DESCRIZIONE: L'interrupt 1ch viene chiamato 18.2 volte al secondo dalla ; CPU. Precisamente il sistem timer collegato al PIC 8259 genera ; l'interrupt 08h che a sua volta chiama l'INT 1Ch ; Questa funzione decrementa un contatore caricato con 18 e quanto arriva a ; zero (circa ogni secondo) aggiorna l'ora sul monitor. ; La funzione rimane attiva fino a quando si preme un tasto ; - se il tasto Š F1 allora l'interrupt rimane in memoria (TSR) ; - altrimenti esco reimpostando il vecchio interrupt ;--------------------------------------------------------------------------- ;--------------------------------------------------------------------------- ;SEGMENTO:codice ;DESCRIZIONE: Contiene tutto il programma ed anche i dati. Quindi DS=CS ;--------------------------------------------------------------------------- codice SEGMENT ;ORG 0100h ;solo per file com ASSUME CS:codice,DS:codice,ES:codice,SS:codice Inizio: jmp Installa ;------------------------VARIABILI------------------------------------------ ;indirizzo vecchio gestore interrupt Old_1c_o DW ? ;offset del vecchio int. Old_1c_s DW ? ;segmento del vecchio int. N_TICK DB 18 ;contatore Video DW 0b800h ;indirizzo memoria video ;buffer per la memorizzazione dell'ora hh:mm:ss hh_10 DB '0' ;ora decine hh_1 DB '0' ;ora unit… DB ':' mm_10 DB '0' mm_1 DB '0' DB ':' ss_10 DB '0' ss_1 DB '0' DB 0 ;--------------NUOVO INTERRUPT 1CH ----------------------------------------- New_1c: sti ;INTR on ;salvo i registri utilizzati push ax push cx push si push di push ds push es ;assicuro che ds=cs push cs pop ds dec N_TICK ;decrementa il contatore jz SetTime ;se zero aggiorna lo schermo end_1c: pop es pop ds pop di pop si pop cx pop ax iret ;fine dell'interrupt ;--------------AGGIONRO IL MONITOR ----------------------------------------- SetTime: mov N_TICK,18 ;ricarico il contatore inc ss_1 ;Š passato un secondo cmp ss_1,'9' ;se nove secondi jle ShowTime ;se minore o uguale mov ss_1,'0' ;se qui allora aggiorno le decine inc ss_10 cmp ss_10,'6' jl ShowTime mov ss_10,'0' inc mm_1 cmp mm_1,'9' jle ShowTime mov mm_1,'0' inc mm_10 cmp mm_10,'6' jl ShowTime mov mm_10,'0' inc hh_1 cmp hh_1,'9' ja NuovaOra cmp hh_1,'3' jnz ShowTime cmp hh_10,'1' jnz ShowTime mov hh_1,'1' mov hh_10,'0' jmp ShowTime NuovaOra: inc hh_10 mov hh_1,'0' ShowTime: mov ax,video push ax pop es ;es punta ora al video buffer ;per visualizzare l'ora sullo schermo devo trasferire i byte ;contenuti in hh......ss nella locazione di memoria per il ;buffer video relativa alla coordinata desiderata, chein questo ;caso Š la prima riga a destra. Quindi il primo byte di ;destinazione (DI) Š (80x2)-(8x2)=144. ;il primo byte di sorgente (SI) Š hh_10 ;il numero di byte da trasferire Š 8 (hh:mm:ss) ;la direzione deve essere in avanti (CLD) mov si,OFFSET hh_10 mov di,144 mov cx,8 cld a: movsb ;mov es:di,ds:si si++ di++ inc di ;tralascio il byte di attributi video loop a ;fino a che cx=0 jmp end_1c ;dimensione in byte di memoria da proteggere. L'operatore MASM $ ;indica l'indirizzo di memoria della riga in cui viene utilizzato ;per cui 'inizio' Š l'inidirizzo di memoria della prima riga di ;programma, la variabile proteggi, contiene la dimensione in byte ;del programma (esclusa la parte che segue). Questa variabile ;serve per proteggere la memoria al momento dell'uscita dal ;dal programma. Quando si termina il programma, il dos libera ;automaticamente, tutta la memoria che occupava il programma. ;In questo modo viene distrutto anche il nuovo gestore ;dell'interrupt da noi scritto. Per questo motivo se si desidera ;rendere sempre valida la riprogrammazione di dato interrupt ;Š necessario preservarlo dalla distruzione operata dal dos. ;L'operazione di protezione della memoria Š nota come TSR, e ;in questo programma viene eseguita all'etichetta 'tsr'. ;diversamente, se si desidera che la riprogrammazione deve essere ;valida solo per la durata del programma, sempre a causa della ;distruzione della memoria operata dal dos, Š necessario prima di ;uscire dal programma reimpostare il vecchio interrupt. Questa seconda ;ipostesi viene eseguita all'etichetta fine. Proteggi EQU $ - inizio mess DB "CLOCK !! Premi un tasto per uscire",13,10 DB "Se premi F1 resta residente in memoria..",13,10,"$" ;--------------RIPROGRAMMAZIONE DELL'INTERRUPT ----------------------------- Installa: push cs ;pongo pop ds ;ds=cs ;cerco l'indirizzo del vettore attuale per INT 1Ch mov al,1Ch ;interrupt richiesto mov ah,35h ;richiesta vettore interrupt int 21h ;pone ES:BX l'indirizzo dell'int. mov old_1c_o,bx ;memorizzo l'offset mov old_1c_s,es ;memorizzo il segmento ;riprogrammo il vettore per INT 1Ch mov al,1Ch ;interrupt da riprogrammare mov ah,25h ;riprogrammazione interrupt mov dx,OFFSET New_1c ;offset dell'interrupt int 21h ;set nuovo int 1ch all'indirizzo DS:New_1c mov ah,09h ;stampo un messagio sullo schermo mov dx,OFFSET mess int 21h ;ciclo di richiesta caratteri ciclo: mov ah,1 ;richiesta caratteri int 16h ;c'e' un carattere in buffer tastiera ? jz ciclo ;nessun carattere nel buffer tastiera cmp ax,3B00h ;scan code per F1 je tsr ;se tasto= F1 salvo l'INT in memoria fine: ;reimpostazione vecchio interrupt mov dx,old_1c_o ;in DX l'offset del vecchio interrupt mov ax,old_1c_s ;il segmento del vecchio interrupt mov ds,ax ;lo metto in DS mov al,1Ch ;INT da riprogrammare mov ah,25h ;riprogrammazione INT int 21h ;uscita al DOS mov al,0 mov ah,4ch int 21h tsr: ;Termina e Sta Residente (TSR) ;in dx metto la dimensione in paragrafi (16 byte) della parte di ;memoria da proteggere PSP compreso ;+15 [byte] per margine di sicurezza ;/16 [byte/paragrafo] per ottenere il numero dei pragrafi ;+16 [paragrafi] dimensione PSP (256 byte=16par*16byte) mov dx,((OFFSET CS:Proteggi+15)/16)+16 mov al,0 mov ah,31h int 21h Codice ENDS END inizio