231 lines
5.8 KiB
NASM
231 lines
5.8 KiB
NASM
|
;
|
||
|
; Copyright (c) Mix Software 1988
|
||
|
;
|
||
|
; Entry from an interrupt
|
||
|
; sets ds and ss to the proper values
|
||
|
; passes registers as arguments
|
||
|
; Called with a far return address followed by an
|
||
|
; interrupt return on the stack. All registers are
|
||
|
; in an unknown state.
|
||
|
;
|
||
|
IDT $_INTENT
|
||
|
DEF $_INTENT
|
||
|
DREF $$LIMIT ; Maximum limit of stack
|
||
|
DREF $$BOTTOM ; Start of stack
|
||
|
FREF $$MAXS
|
||
|
MARGIN EQU >100 ; Minimum stack needed
|
||
|
;
|
||
|
$_INTENT CLI
|
||
|
PUSH AX
|
||
|
MOV AX,SS
|
||
|
SEGCS
|
||
|
CMP AX,[PROGDS]
|
||
|
JNZ DIFFSTK
|
||
|
POP AX ; interrupt uses same stack
|
||
|
PUSH BP ; as the program
|
||
|
MOV BP,SP
|
||
|
XCHG AX,[BP][%4] ; ax = caller cs
|
||
|
XCHG BX,[BP][%2] ; ax = caller ip
|
||
|
POP BP
|
||
|
PUSH CX
|
||
|
PUSH DX
|
||
|
PUSH ES
|
||
|
PUSH DS
|
||
|
PUSH SI
|
||
|
PUSH DI
|
||
|
PUSH BP
|
||
|
MOV CX,CS
|
||
|
PUSH CX ; return to here
|
||
|
MOV CX,RET1
|
||
|
PUSH CX
|
||
|
PUSH AX ; Caller's address
|
||
|
PUSH BX
|
||
|
MOV AX,SS
|
||
|
MOV DS,AX
|
||
|
STI
|
||
|
RETFAR ; Go to caller with parms set
|
||
|
RET1 POP BP
|
||
|
POP DI
|
||
|
POP SI
|
||
|
POP AX
|
||
|
MOV DS,AX
|
||
|
POP AX
|
||
|
MOV ES,AX
|
||
|
POP DX
|
||
|
POP CX
|
||
|
POP BX
|
||
|
POP AX
|
||
|
IRET
|
||
|
;
|
||
|
DIFFSTK POP AX
|
||
|
PUSH DS
|
||
|
SEGCS
|
||
|
MOV DS,[PROGDS]
|
||
|
CLI
|
||
|
POP [SAVEDS]
|
||
|
MOV [SAVEDI],DI
|
||
|
MOV [SAVEAX],AX
|
||
|
MOV [SAVECX],CX
|
||
|
CMP %[STKLOCK],%0
|
||
|
JNZ FINDSTK
|
||
|
MOV %[STKLOCK],%1
|
||
|
MOV DI,[$$LIMIT]
|
||
|
ADD DI,[_INT_STK]
|
||
|
AND DI,>FFFE
|
||
|
MOV AX,SS ; switch stacks
|
||
|
MOV CX,SP
|
||
|
SEGCS
|
||
|
MOV SS,[PROGDS]
|
||
|
MOV SP,DI
|
||
|
MOV DI,CX
|
||
|
MOV DS,AX
|
||
|
MOV CX,RET2
|
||
|
JMPS NEWSTK
|
||
|
;
|
||
|
RET2 CLI
|
||
|
MOV AX,SS
|
||
|
MOV DS,AX
|
||
|
MOV %[STKLOCK],%0
|
||
|
POP BP
|
||
|
POP [SAVEDI]
|
||
|
POP SI
|
||
|
POP [SAVEDS]
|
||
|
POP AX
|
||
|
MOV ES,AX
|
||
|
POP DX
|
||
|
POP CX
|
||
|
POP BX
|
||
|
POP [SAVEAX]
|
||
|
ADD SP,%6 ; Remove cs:ip and flags
|
||
|
POP DI ; Interrupted task's sp
|
||
|
ADD DI,%4 ; Remove return from int function
|
||
|
POP AX ; Interrupted task's ss
|
||
|
MOV SS,AX ; Set to prior stack
|
||
|
MOV SP,DI
|
||
|
MOV AX,[SAVEAX]
|
||
|
MOV DI,[SAVEDI]
|
||
|
MOV DS,[SAVEDS]
|
||
|
IRET
|
||
|
;
|
||
|
; Search for stack space
|
||
|
;
|
||
|
FINDSTK MOV [SAVEES],ES
|
||
|
MOV AX,DS
|
||
|
MOV ES,AX
|
||
|
XOR AX,AX
|
||
|
MOV DI,[$$LIMIT] ; Scan for available stack
|
||
|
ADD DI,[_INT_STK]
|
||
|
MOV CX,[$$BOTTOM]
|
||
|
SUB CX,DI
|
||
|
SHR CX,1
|
||
|
REPZ
|
||
|
SCASW
|
||
|
SUB DI,%2
|
||
|
DEC DI
|
||
|
AND DI,>FFFE ; round down to word boundary
|
||
|
MOV CX,DI
|
||
|
SUB CX,[$$LIMIT]
|
||
|
CMP CX,MARGIN
|
||
|
JB NOSTACK
|
||
|
MOV ES,[SAVEES]
|
||
|
MOV AX,SS ; switch stacks
|
||
|
MOV CX,SP
|
||
|
SEGCS
|
||
|
MOV SS,[PROGDS]
|
||
|
MOV SP,DI
|
||
|
MOV DI,CX
|
||
|
MOV DS,AX
|
||
|
MOV CX,RET3
|
||
|
NEWSTK PUSH DS ; save interrupt's stack
|
||
|
PUSH DI
|
||
|
PUSH [DI][%2*4] ; flags
|
||
|
PUSH [DI][%2*3] ; interrupt cs
|
||
|
PUSH [DI][%2*2] ; interrupt ip
|
||
|
MOV AX,DS
|
||
|
PUSH DI
|
||
|
MOV DI,SS
|
||
|
MOV DS,DI
|
||
|
POP DI
|
||
|
PUSH [SAVEAX] ; ax
|
||
|
PUSH BX
|
||
|
PUSH [SAVECX] ; cx
|
||
|
PUSH DX
|
||
|
PUSH ES
|
||
|
PUSH [SAVEDS] ; DS
|
||
|
PUSH SI
|
||
|
PUSH [SAVEDI] ; DI
|
||
|
PUSH BP
|
||
|
MOV DS,AX
|
||
|
MOV AX,CS
|
||
|
PUSH AX ; return segment
|
||
|
PUSH CX ; return address
|
||
|
PUSH [DI][%2*1] ; Caller's address
|
||
|
PUSH [DI][%2*0]
|
||
|
MOV AX,SS
|
||
|
MOV DS,AX
|
||
|
STI
|
||
|
RETFAR ; Go to caller with parms set
|
||
|
;
|
||
|
NOSTACK PUSH DX
|
||
|
PUSH BX
|
||
|
MOV AX,CS
|
||
|
MOV DS,AX
|
||
|
MOV AX,>4000 ; Write message to stderr
|
||
|
MOV BX,2
|
||
|
MOV CX,MSGLEN
|
||
|
MOV DX,STKMSG
|
||
|
INT >21
|
||
|
POP BX
|
||
|
POP DX
|
||
|
JMPS GOBACK
|
||
|
;
|
||
|
RET3 CLI
|
||
|
MOV AX,SS
|
||
|
MOV DS,AX
|
||
|
POP BP
|
||
|
POP [SAVEDI]
|
||
|
POP SI
|
||
|
POP [SAVEDS]
|
||
|
POP [SAVEES]
|
||
|
POP DX
|
||
|
POP [SAVECX]
|
||
|
POP BX
|
||
|
POP [SAVEAX]
|
||
|
ADD SP,%6 ; Remove cs:ip and flags
|
||
|
MOV DI,SS
|
||
|
MOV ES,DI
|
||
|
POP DI ; Interrupted task's sp
|
||
|
ADD DI,%4 ; Remove return from int function
|
||
|
POP AX ; Interrupted task's ss
|
||
|
MOV CX,SP
|
||
|
MOV SS,AX ; Set to prior stack
|
||
|
MOV SP,DI
|
||
|
MOV DI,[$$LIMIT]
|
||
|
ADD DI,[_INT_STK]
|
||
|
SUB CX,DI
|
||
|
SHR CX,1
|
||
|
XOR AX,AX
|
||
|
REP
|
||
|
STOSW
|
||
|
GOBACK MOV AX,[SAVEAX]
|
||
|
MOV CX,[SAVECX]
|
||
|
MOV DI,[SAVEDI]
|
||
|
MOV ES,[SAVEES]
|
||
|
MOV DS,[SAVEDS]
|
||
|
IRET
|
||
|
;
|
||
|
STKMSG DB >0D,>0A,'Out of stack',>0D,>0A
|
||
|
MSGLEN EQU $-STKMSG
|
||
|
PROGDS EQU $+3
|
||
|
callfar $$MAXS
|
||
|
DORG 0
|
||
|
DDEF _INT_STK
|
||
|
SAVEAX DW 0-0
|
||
|
SAVECX DW 0-0
|
||
|
SAVEDI DW 0-0
|
||
|
SAVEDS DW 0-0
|
||
|
SAVEES DW 0-0
|
||
|
_INT_STK DW >400
|
||
|
STKLOCK DW 0
|
||
|
END
|