home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Sound Sensations!
/
sound_sensations.iso
/
midifile
/
cmtcmu
/
break.asm
< prev
next >
Wrap
Assembly Source File
|
1990-06-28
|
9KB
|
369 lines
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