home *** CD-ROM | disk | FTP | other *** search
- title BREAK - handle ctrl-break
- ;*****************************************************************************
- ; Change Log
- ; Date | Change
- ;-----------+-----------------------------------------------------------------
- ; 11-Aug-85 | Created
- ; 1-Sep-85 | Rearranged so _clrctl precedes its call (needed in P model)
- ; 31-Dec-85 | Made special copy for Adagio support. Stripped out most stuff
- ; | and handle DOS ctrl-break exit
- ; 1-Jan-86 | Use 1 for control-break and 2 for control-C
- ; 1-Jan-86 | Cause return to skip over sub instruction (forcing ignore code
- ; | acceptance) on PC/AT
- ; 2-Jan-86 | take out m: from include m:dos.mac
- ;****************************************************************************/
- include dos.mac
- debug=0
- subttl Documentation
- ;*****************************************************************************
- ; This code uses the standard Lattice interface. The logical device 'm:'
- ; represents the memory model being used. Supply your own path to dos.mac
- ;
- ; This code is intended to allow me to break out of various perverse
- ; loops in my application code.
- ;
- ; * * * W A R N I N G * * *
- ;
- ; This code is an extreme *HACK*. It solves my problem. It may not solve
- ; yours. I make no guarantees. Use at your own risk!
- ;
- ; Restrictions
- ;
- ; Failure to clear the handler before exiting the program will lead to
- ; various bizarre behavior. Calling the initialization more than once
- ; will confuse the world beyond practical recovery.
- ;
- ; Abstract
- ;
- ; A procedure is called to establish the existence of the control-break
- ; handler (interrupt 1BH). If a control-break is taken during program
- ; the flag _CBREAK is set to true
- ;
- ; This code is to be linked into the user's application.
- ;
- ; This code also sets up a handler for the DOS ctrl-brk exit; this is called
- ; if DOS sees a C-C character come by.
- ;
- ; * * * B E W A R E * * *
- ;
- ; This code is delicate and high-risk. It works well enough for my one
- ; application. I may have missed all sorts of bizarre DOS or BIOS hacks.
- ;
- ; It is not guaranteed to be bug-free. The user assumes all risk in using
- ; it. This is code that should be used only if you understand enough of
- ; DOS/BIOS hacking to be sure it will work for you.
- ;
- ;
-
- subttl Interface specifications
- ;-----------------------------------------------------------------------------
- ; extern void _setctl();
- ;
- ; Effects:
- ; Establishes a Ctrl-brk abort handler
- ;
- ; Limitations:
- ; May only be called once; subsequent calls may damage universe
- ;
- ;-----------------------------------------------------------------------------
- ; extern void _clrctl();
- ;
- ; Effects:
- ; Resets the Ctrl-brk abort handler
- ;
- ; Limitations:
- ; Should be called only if _setctl() has been called. However, if
- ; _setctl has not already been called, nothing will happen.
- ;
- ;*****************************************************************************
-
- subttl Working storage
- extrn _CBREAK:word
- ; This storage is in the data segment
- ; public _CBREAK
- DSEG
- even
- ;_CBREAK dw 0
- OLD_BIOS label DWORD ; we store former 1BH vector here
- OLD_BIP DW 0 ; 0, not ?
- OLD_BCS DW 0 ; 0, not ?
-
- OLD_DOS label DWORD ; we store former 23H vector here
- OLD_DIP DW 0
- OLD_DCS dw 0
-
- ENDDS
-
-
- subttl Vector locations
- VECTORS SEGMENT AT 0H
- ORG 1BH*4 ; BIOS ctrl-brk interrupt vector
- CTLBRK LABEL DWORD
- CTLBRK_IP DW ? ; IP of BIOS control-break vector
- CTLBRK_CS DW ? ; CS of BIOS control-break vector
-
- ORG 23H*4 ; DOS ctrl-brk interrupt vector
- DOSCBRK LABEL DWORD
- DOSC_IP DW ?
- DOSC_CS DW ?
- VECTORS ENDS
-
-
-
- subttl Code segment storage
- ;
- ; This is in the code segment because I don't know how to make it addressible
- ; in the data segment
- ;
- PSEG
-
-
- subttl CTLSEEN - CTRL-BREAK handler
- ;-----------------------------------------------------------------------------
- ; ctlseen
- ; Inputs:
- ; None; called as interrupt routine via interrupt 1BH
- ;
- ; Result:
- ; AL=0FFH
- ;
- ; Effects:
- ; sets _CBREAK to true.
- ;-----------------------------------------------------------------------------
-
- CTLSEEN PROC FAR
-
-
- if debug
- int 3
- endif
- push ax
- push ds
- mov ax,seg _CBREAK
- mov ds,ax
- mov ds:_CBREAK,1
- pop ds
- pop ax
- push es
- mov AX,0F000H ; from the ROM,
- mov ES,AX ; we want pc ID
- mov AH,ES:0FFFEH ; The Peter Norton Programmer's Guide to the
- ; IBM PC, page 60
- cmp AH,0FCH ; PC/AT?
- jnz no
- if debug
- int 3 ; WARNING! If you have this debug trap
- ; enabled, and continue from it, the
- ; ctrl-key-up transition is lost (because
- ; the key went up to talk to the debugger)
- ; this confuses the world; you will have to
- ; hit the control-key once to get the
- ; world resynchronized.
-
- endif
- ; We increment the return address by 2
- ;
- ; +-------------------+
- ; SS | (ES) | ES:0[BP]
- ; +-------------------+
- ; | (BP) | ES:2[BP]
- ; +-------------------+
- ; | IP | ES:4[BP]
- ; +-------------------+
- ; | CS | ES:6[BP]
- ; +-------------------+
- mov AX,SS
- mov ES,AX
- push BP
- mov BP,SP
- inc WORD PTR ES:4[BP]
- inc WORD PTR ES:4[BP]
- pop BP
- no: mov AX,-1
- ; "ignore" character
- ; PC/XT ref page A-31 lines 2090-2091, page A-33
- ; lines 2217-2219
- ; PC/AT ref page 5-118 loc 2AE..285 indicates this
- ; has no effect for the /AT, which is why we did
- ; the above hack
- pop ES
- iret ;return
-
- CTLSEEN ENDP
-
- CTLC PROC FAR ; Control-C handler
- push ax
- push ds
- mov ax,seg _CBREAK
- mov ds,ax
- mov ds:_CBREAK,2
- pop ds
- pop ax
- iret ;return
- CTLC ENDP
-
- subttl _clrctl - Clear CTL-BRK vector
- ;-----------------------------------------------------------------------------
- ; extern void _clrctl();
- ;
- ; Resets the ctrl-break interrupt vector
- ;-----------------------------------------------------------------------------
- PUBLIC _clrctl
- IF LPROG
- _clrctl PROC FAR
- ELSE
- _clrctl PROC NEAR
- ENDIF
-
- ; OldES := ES;
-
- push ES ; save old ES
- push AX ; save old AX
- push BX
-
- if debug
- int 3
- mov AH,62H
- int 21H ; get program segment prefix
- mov PSP,BX ; save it
- endif
-
- ; ES := Segment(&Vectors);
-
- mov AX,VECTORS
- mov ES,AX
- ASSUME ES:VECTORS
-
- ; Disable_Interrupts();
-
- CLI ; turn off interrupts
-
- ; if(OLD_BIOS == 0) goto NoVectorStored
-
- mov AX,WORD PTR OLD_BIOS
- cmp AX,0 ; is it zero?
- je NoBIOSStored
-
- ; CTLBRK.IP := OLD_BIOS.IP
-
- mov WORD PTR CTLBRK,AX
-
- ; CTLBRK.CS := OLD_BIOS.CS
-
- mov AX,WORD PTR OLD_BIOS[2]
- mov WORD PTR CTLBRK[2],AX
-
- NoBIOSStored:
-
- mov AX,WORD PTR OLD_DOS
- cmp AX,0 ; initialized?
- je NoDOSStored ; no, no dos vector
-
- ; DOSCBRK.IP = OLD_DOS.IP
-
- mov WORD PTR DOSCBRK,AX
-
- ; DOSCBRK.CS := OLD_DOS.CS
-
- mov AX,WORD PTR OLD_DOS[2]
- mov WORD PTR DOSCBRK[2],AX
-
- NoDOSStored:
-
- ; Enable_interrupts();
-
- STI ; allow interrupts
-
- ; ES := OldES;
-
- pop BX
- pop AX
- pop ES
-
- ret ; return to caller
-
- PSP: DW ?
- _clrctl ENDP
-
- subttl _setctl - Set CTL-BRK vector
- ;-----------------------------------------------------------------------------
- ; extern void _setctl()
- ;-----------------------------------------------------------------------------
-
- PUBLIC _setctl
- IF LPROG
- _setctl PROC FAR
- ELSE
- _setctl PROC NEAR ; set CTL-BRK interrupt
- ENDIF
- push BP ; C prolog
- mov BP,SP ; ...
-
- if debug
- int 3
- endif
-
- ASSUME ES:VECTORS
-
- ; OldES := ES;
-
- push ES ; save old ES
- push AX ; save old AX
-
- ; ES := Segment(&Vectors);
-
- mov AX,VECTORS
- mov ES,AX
-
- ; Disable_Interrupts();
-
- CLI ; turn off interrupts
-
- ; OLD_BIOS.IP := CTLBRK.IP
-
- mov AX,WORD PTR CTLBRK
- mov WORD PTR OLD_BIOS,AX
-
- ; OLD_BIOS.CS := CTLBRK.CS
-
- mov AX,WORD PTR CTLBRK[2]
- mov WORD PTR OLD_BIOS[2],AX
-
- ; CTLBRK := &CTLSEEN
-
- mov CTLBRK_IP,OFFSET CTLSEEN
- mov CTLBRK_CS,CS
-
- ; OLD_DOS.IP := DOSCBRK.IP
-
- mov AX,WORD PTR DOSCBRK
- mov WORD PTR OLD_DOS,AX
-
- ; OLD_DOS.CS := DOSCBRK.CS
-
- mov AX,WORD PTR DOSCBRK[2]
- mov WORD PTR OLD_DOS[2],AX
-
- ; DOSCBRK := &CTLC
-
- mov DOSC_IP,OFFSET CTLC
- mov DOSC_CS,CS
-
- ; Enable_interrupts();
-
- STI ; allow interrupts
-
- ; ES := OldES;
-
- pop AX
- pop ES
-
- ; return;
- pop BP ; C epilog
- ret ; return to caller
-
- _setctl ENDP
-
- ENDPS
- END
-