Skip to content
Merged

Int23 #290

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions kernel/entry.asm
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ segment HMA_TEXT
extern _cu_psp
extern _MachineId
extern critical_sp
extern int21_sp

extern int21regs_seg
extern int21regs_off
Expand Down Expand Up @@ -419,8 +420,10 @@ int21_4:

push si ; user SS:SP
push bp
mov [int21_sp], sp ; for int23
call _int21_service

global int21_exit
int21_exit: dec byte [_InDOS]

;
Expand Down
4 changes: 3 additions & 1 deletion kernel/kernel.asm
Original file line number Diff line number Diff line change
Expand Up @@ -611,8 +611,10 @@ int21regs_seg dw 0
critical_sp dw 0 ;268 - critical error internal stack
global current_ddsc
current_ddsc times 2 dw 0
global int21_sp
int21_sp dw 0

; Pad to 059ah
; Pad to 027ah
times (27ah - ($ - _internal_data)) db 0
global current_device
current_device times 2 dw 0 ;27A - 0??
Expand Down
191 changes: 24 additions & 167 deletions kernel/procsupt.asm
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@
extern _user_r

extern _break_flg ; break detected flag
extern _int21_handler ; far call system services
extern _int21_service
extern int21_exit
extern _InDOS
extern int21_sp

%include "stacks.inc"

Expand Down Expand Up @@ -100,177 +103,31 @@ _got_cbreak:

segment HMA_TEXT

;
; Special call for switching processes during break handling
;
; void interrupt far spawn_int23()
;
;
; +---------------+
; | flags | 22
; +---------------+
; | cs | 20
; +---------------+
; | ip | 18
; +---------------+
; | es | 16
; +---------------+
; | ds | 14
; +---------------+
; | bp | 12
; +---------------+
; | di | 10
; +---------------+
; | si | 8
; +---------------+
; | dx | 6
; +---------------+
; | cx | 4
; +---------------+
; | bx | 2
; +---------------+
; | ax | 0 <--- bp & sp after mov bp,sp
; +---------------+
;
global _spawn_int23
_spawn_int23:

;; 1999/03/27 ska - comments: see cmt1.txt
mov ds, [cs:_DGROUP_] ;; Make sure DS is OK
mov sp, [int21_sp]
mov bp, sp
clc
int 23h
mov sp, bp
mov bp, [_user_r]

; restore to user stack
cli ;; Pre-8086 don't disable INT autom.
;*TE PATCH
; CtrlC at DosInput (like C:>DATE does)
; Nukes the Kernel.
;
; it looks like ENTRY.ASM+PROCSUPT.ASM
; got out of sync.
;
; spawn_int() assumes a stack layout at
; usr_ss:usr:sp. but usr:ss currently contains 0
;
; this patch helps FreeDos to survive CtrlC,
; but should clearly be done somehow else.
mov ss, [_user_r+2]
RestoreSP

sti

; get all the user registers back
Restore386Registers
POP$ALL

;; Construct the piece of code into the stack

;; stack frame: during generation of code piece
;; <higher address>
;; BP | SP | Meaning
;; 7 | 11 | offset CALL FAR will push onto stack
;; 5 | 9 | CALL FAR segment
;; 3 | 7 | CALL FAR offset
;; 2 | 6 | CALL FAR ??regain_control_int23 | instruction byte
;; 0 | 4 | INT 23 <<should-be value of SP upon return>>
;; -2 | 2 | segment of address of INT-23 \ To jump to INT 23
;; -4 | 0 | offset of address of INT-23 / via RETF
;; Upon return from INT-23 the CALL FAR pushes the address of
;; the byte immediately following the CALL FAR onto the stack.
;; This value POPed and decremented by 7 is the value SP must
;; contain, if the INT-23 was returned with RETF2/IRET.

sub sp, byte 8 ;; code piece needs 7 bytes --> 4 words
push ss ;; prepare jump to INT-23 via RETF
push bp ;; will be offset / temp: saved BP
mov bp, sp
add bp, byte 4 ;; position BP onto INT-23
mov word [bp], 23cdh ;; INT 23h
mov byte [bp+2], 9ah ;; CALL FAR immediate
mov word [bp+3], ??regain_control_int23
mov word [bp+5], cs

;; complete the jump to INT-23 via RETF and restore BP
xchg word [bp-4], bp

clc ;; set default action --> resume
; invoke the int 23 handler its address has been constructed
;; on the stack
retf

??regain_control_int23:

;; stack frame: constructed on entry to INT-23
;; <higher address>
; BP | SP | Meaning
;; 7 | 11 | offset CALL FAR will push onto stack
;; 5 | 9 | CALL FAR segment
;; 3 | 7 | CALL FAR offset
;; 2 | 6 | CALL FAR ??regain_control_int23 | instruction byte
;; 0 | 4 | INT 23 <<should-be value of SP upon return>>
;; -2 | 2 | segment of address of INT-23 \ To jump to INT 23
;; -4 | 0 | offset of address of INT-23 / via RETF
;; Upon return from INT-23 the CALL FAR pushes the address of
;; the byte immediately following the CALL FAR onto the stack.
;; This value POPed and decremented by 7 is the value SP must
;; contain, if the INT-23 was returned with RETF2/IRET.

;; stack frame: used during recovering from INT-23
;; <higher address>
;; BP | Meaning
;; 1 | <<next word onto stack, or value SP has to become>>
;; 0 | <<return address from CALL FAR>>
;; -1 | saved BP
;; -3 | saved AX
;; -7 | INT 23 <<should-be value of SP upon return>>

;; Somewhere on stack:
;; SP | Meaning
;; 4 | segment of return address of CALL FAR
;; 2 | offset of return address of CALL FAR
;; 0 | saved BP

push bp
mov bp, sp
mov bp, [bp+2] ;; get should-be address + 7
mov word [bp-3], ax ;; save AX
pop ax ;; old BP
mov word [bp-1], ax ;; preserve saved BP
mov ax, bp
dec ax ;; last used word of stack
dec ax ;; Don't use SUB to keep Carry flag
dec ax
xchg ax, sp ;; AX := current stack; SP corrected
;; Currently: BP - 7 == address of INT-23
;; should be AX + 4 --> IRET or RETF 2
;; ==> Test if BP - 7 == AX + 4
;; ==> Test if AX + 4 - BP + 7 == 0
pushf ;; preserve Carry flag
add ax, byte 4 + 7
sub ax, bp ;; AX := SP + 4
pop ax ;; saved Carry flag
jz ??int23_ign_carry ;; equal -> IRET --> ignore Carry
;; Carry is already cleared
push ax
popf ;; restore Carry flag

??int23_ign_carry:
pop ax ;; Restore the original register
jnc ??int23_respawn
;; The user returned via RETF 0, Carry is set
;; --> terminate program
;; This is done by set the _break_flg and modify the
;; AH value, which is passed to the _respawn_ call
;; into 0, which is "Terminate program".
push ds ;; we need DGROUP
mov ds, [cs:_DGROUP_]
inc byte [_break_flg]
pop ds

xor ah, ah ;; clear ah --> perform DOS-00 --> terminate

mov si, [_user_r+2]
jnc ??int23_respawn
;; The user returned via RETF 0, Carry is set
;; --> terminate program
;; This is done by set the _break_flg and modify the
;; AH value, which is passed to the _respawn_ call
;; into 0, which is "Terminate program".
inc byte [_break_flg]
push es
mov es, si
mov word [es:bp], 0 ;; clear ah --> perform DOS-00 --> terminate
pop es
??int23_respawn:
pop bp ;; Restore the original register
jmp DGROUP:_int21_handler
inc byte [_InDOS]
call _int21_service
jmp int21_exit

;
; interrupt enable and disable routines
Expand Down
14 changes: 12 additions & 2 deletions kernel/task.c
Original file line number Diff line number Diff line change
Expand Up @@ -974,8 +974,18 @@ VOID ASMCFUNC P_0(const struct config FAR *Config)

VOID ASMCFUNC P_0_exit(unsigned short retcode)
{
if (retcode == 0) {
_printf("\nShell %s exited, press any key...\n", GET_PTR(Shell));
if ((retcode & 0xff) == 0) {
switch (retcode >> 8) {
case 0:
_printf("\nShell %s exited, press any key...\n", GET_PTR(Shell));
break;
case 1:
_printf("\nShell %s aborted (^C), press any key...\n", GET_PTR(Shell));
break;
case 2:
_printf("\nShell %s aborted due to critical error, press any key...\n", GET_PTR(Shell));
break;
}
con_flush_stdin();
read_char_stdin(0);
} else {
Expand Down