;**********************************************************************; ;* P L I N K C A . A S M *; ;*--------------------------------------------------------------------*; ;* Aufgabe : Stellt die Assemblerschnittstelle zum C- *; ;* Programm dar und enth„lt die Interrupt- *; ;* Handler dieses Programms *; ;**********************************************************************; IGROUP group _text ;Zusammenfassung der Programm-Segmente DGROUP group _bss, _data ;Zusammenfassung der Daten-Segmente assume CS:IGROUP, DS:DGROUP, ES:DGROUP, SS:DGROUP _BSS segment word public 'BSS' ;dieses Segment nimmt alle nicht ini- _BSS ends ;tialisierten statischen Variablen auf _DATA segment word public 'DATA' ;alle initialisierten globalen und ;statischen Variablen werden in diesem ;Segment untergebracht _DATA ends ;== Konstanten ========================================================= KB_PORT = 60h ;Tastatur-Port INT_CTR = 20h ;Port des Interrupt-Controllers EOI = 20h ;End-of-Interrupt-Kommando ESCAPE = 1 ;Scan-Code von Escape ;== Programm =========================================================== _TEXT segment byte public 'CODE' ;das Codesegment ;-- Public-Deklarationen interner Funktionen --------------------------- public _IntrInstall ;erm”glicht Aufruf aus C-Programm public _IntrRemove public _EscapeDirekt ;-- Variablen fr die Interrupt-Handler ---------------------------------- ;-- (nur ber das Codesegment zug„nglich) -------------------------------- key_ptr dd 0 ;Zeiger auf Variable fr ESCAPE escdirekt db 0 ;bei Escape kein Time-Out ausl”sen sec_ptr dd 0 ;Zeiger auf sekundenflag sec_wait db 0 ;wait 18 ticks ;-- die folgenden Variablen nehmen die alten Adressen der Interrupt- --- ;-- Handler auf, die durch neue Interrupt-Handler ersetzt wurden --- int9_ptr equ this dword ;alter Interrupt-Vektor 9h int9_ofs dw 0 ;Offsetadresse des alten Handlers int9_seg dw 0 ;Segmentadresse des alten Handlers int1C_ptr equ this dword ;alter Interrupt-Vektor 1Ch int1C_ofs dw 0 ;Offsetadresse des alten Handlers int1C_seg dw 0 ;Segmentadresse des alten Handlers ;----------------------------------------------------------------------- ;-- IntrInstall : Installiert die Interrupt-Handler ---- ;-- Aufruf von C: void IntrInstall( int far * escape_flag, ;-- int far * sec_flag ); _IntrInstall proc near sframe0 struc ;Struktur zum Zugriff auf den Stack bp0 dw ? ;nimmt BP auf ret_adr0 dw ? ;Rcksprungadresse escptr dd ? ;FAR-Zeiger auf das ESCAPE-Flag secptr dd ? ;FAR-Zeiger auf den Sekundenflag sframe0 ends ;Ende der Struktur frame equ [ bp - bp0 ] push bp ;BP auf dem Stack sichern mov bp,sp ;SP nach BP bertragen push si ;-- die Argumente vom Stack holen und bearbeiten ------------ les si,frame.escptr ;Zeiger auf ESCAPE-Flag laden mov word ptr key_ptr,si ;und in Codesegment-Variablen mov word ptr key_ptr+2,es ;ablegen les si,frame.secptr ;Zeiger auf Timeout-Z„hler laden mov word ptr sec_ptr,si ;und in Codesegment-Variablen mov word ptr sec_ptr+2,es ;ablegen mov cs:sec_wait,18 ;-- die Adressen der umzuleitenden Interrupt-Handler holen -- mov ax,3509h ;Interrupt-Vektor 9h holen int 21h ;DOS-Interrupt aufrufen mov int9_ofs,bx ;Adresse des Handlers in den ent- mov int9_seg,es ;sprechenden Variablen merken mov ax,351Ch ;Interrupt-Vektor 1Ch holen int 21h ;DOS-Interrupt aufrufen mov int1C_ofs,bx ;Adresse des Handlers in den ent- mov int1C_seg,es ;sprechenden Variablen merken ;-- die neuen Intrrupt-Handler installieren ----------------- push ds ;Datensegment merken mov ax,cs ;DS auf CS setzen mov ds,ax mov ax,2509h ;Fkt.nr.: Interrupt 9h setzen mov dx,offset int09 ;DS:DX nimmt Adresse des Handler auf int 21h ;DOS-Interrupt aufrufen mov ax,251Ch ;Fkt.nr.: Interrupt 1Ch setzen mov dx,offset int1C ;DS:DX nimmt Adresse des Handler auf int 21h ;DOS-Interrupt aufrufen pop ds ;DS wieder vom Stack holen pop si pop bp ret ;zurck zum Aufrufer _IntrInstall endp ;----------------------------------------------------------------------- ;-- IntrRemove : Deaktiviert die Interrupt-Handler wieder ;-- Aufruf von C: void IntrRemove( void ); _IntrRemove proc near cli ;keine Interrupts mehr zulassen push ds ;DS sichern mov ax,2509h ;Fkt.nr: Handler fr INT 9 setzen mov ds,int9_seg ;Segmentadresse des alten Handler mov dx,int9_ofs ;Offsetadresse des alten Handler int 21h ;den alten Handler wieder installieren mov ax,251Ch ;Fkt.nr: Handler fr INT 1C setzen mov ds,int1C_seg ;Segmentadresse des alten Handler mov dx,int1C_ofs ;Offsetadresse des alten Handler int 21h ;den alten Handler wieder installieren pop ds ;DS wieder zurckholen sti ;Interrupts wieder erlauben ret ;zurck zum Aufrufer _IntrRemove endp ;Ende der Prozedur ;----------------------------------------------------------------------- ;-- EscapeDirekt: Legt fest, ob bei Escape ein Time-Out ausgel”st ---- ;-- werden soll ;-- Aufruf von C: void EscapeDirekt( int Ausloesen ); _EscapeDirekt proc near sframe1 struc ;Struktur zum Zugriff auf den Stack bp1 dw ? ;nimmt BP auf ret_adr1 dw ? ;Rcksprungadresse escflag dw ? ;TRUE oder FALSE sframe1 ends ;Ende der Struktur frame equ [ bp - bp1 ] push bp ;BP auf dem Stack sichern mov bp,sp ;SP nach BP bertragen mov al,byte ptr frame.escflag ;Flag laden mov cs:escdirekt,al ;und in CS-Variable ablegen pop bp ret ;zurck zum Aufrufer _EscapeDirekt endp ;----------------------------------------------------------------------- ;-- es folgen die neuen Interrupt-Handler ------------------------------ ;----------------------------------------------------------------------- assume CS:IGROUP, DS:nothing, ES:nothing, SS:nothing ;-- der neue Interrupt 09h-Handler ------------------------------------- int09 proc far push ax ;AX und auf dem Stack sichern in al,KB_PORT ;Scan-Code vom Tastatur-Port holen cmp al,128 ;Release-Code? jae i9_end ;Ja, gar nicht erst testen cmp al,ESCAPE ;Nein, aber ESCAPE? jne i9_end ;Nein, an alten Handler weiterreichen ;-- es wurde ESCAPE bet„tigt -------------------------------- push ds ;DS und SI merken push si lds si,key_ptr ;Zeiger auf ESCAPE-Variable laden mov word ptr [si],1 ;ESCAPE-Flag auf 1 setzen pop si ;DS und SI wieder restaurieren pop ds mov al,EOI ;Ende des Interrupts anzeigen out INT_CTR,al pop ax ;AX zurckholen iret ;zurck zum unterbrochenen Programm i9_end: pop ax ;AX zurckholen jmp cs:[int9_ptr] ;zum alten Handler springen int09 endp ;-- der neue Interrupt 1Ch-Handler ------------------------------------- int1C proc far push ds ;DS und SI merken push si dec cs:sec_wait cmp cs:sec_wait,0 jne no_second lds si,sec_ptr ;Zeiger auf sec-flag laden mov word ptr [si],1 ;Flag setzen mov cs:sec_wait,18 ;reload sec-counter no_second: pop si ;DS und SI wieder restaurieren pop ds jmp cs:[int1C_ptr] ;weiter zum alten Interrupt-Handler int1C endp ;------------------------------------------------------------------------- _text ends ;Ende des Codesegments end ;Ende des Programms