181 lines
4.5 KiB
Plaintext
181 lines
4.5 KiB
Plaintext
subttl Macro definitions
|
||
|
||
; In segment 'segzero' set $ to the next multiple of 'n'.
|
||
align macro n,segzero
|
||
org $ - (($-segzero) MOD n) + n
|
||
endm
|
||
|
||
; Issue a DOS function request (int 21h) after
|
||
; setting up registers ax,bx,cx,dx,ds,es.
|
||
; Registers not specified are not affected by the macro,
|
||
; code to move a reg to itself is skipped, and
|
||
; moves between DS and ES are handled.
|
||
dos_fr macro rax,rbx,rcx,rdx,rds,res
|
||
ifnb <rax> ;;ax
|
||
ifidn <rax>,<ax>
|
||
else
|
||
mov ax,rax
|
||
endif
|
||
endif
|
||
ifnb <rbx> ;;bx
|
||
ifidn <rbx>,<bx>
|
||
else
|
||
mov bx,rbx
|
||
endif
|
||
endif
|
||
ifnb <rcx> ;;cx
|
||
ifidn <rcx>,<cx>
|
||
else
|
||
mov cx,rcx
|
||
endif
|
||
endif
|
||
ifnb <rdx> ;;dx
|
||
ifidn <rdx>,<dx>
|
||
else
|
||
mov dx,rdx
|
||
endif
|
||
endif
|
||
ifnb <res> ;;es
|
||
ifidn <res>,<ds>
|
||
push ds
|
||
pop es
|
||
else
|
||
ifidn <res>,<es>
|
||
else
|
||
mov es,res
|
||
endif
|
||
endif
|
||
endif
|
||
ifnb <rds> ;;ds
|
||
ifidn <rds>,<es>
|
||
push es
|
||
pop ds
|
||
else
|
||
ifidn <rds>,<ds>
|
||
else
|
||
mov ds,rds
|
||
endif
|
||
endif
|
||
endif
|
||
int 21h
|
||
endm
|
||
|
||
; Given the value of "active_exe", put into BX the corresponding byte offset
|
||
; into various tables. If table="itself", just load BX.
|
||
;
|
||
; Note: The calculated byte offset must fit into BL because we use BH for
|
||
; scratch. We don't affect any other register this way. If the
|
||
; number of entries allowed in the tables is enlarged so that we
|
||
; could overflow into BH, this macro will need changing. Changing
|
||
; a table's format will obviously affect this macro too.
|
||
load_index macro table
|
||
mov bx,active_exe
|
||
ifdif <itself>,<table>
|
||
xor bh,bh
|
||
endif
|
||
ifidn <load_table>,<table>
|
||
shl bx,1 ;; 2 bytes/entry
|
||
endif
|
||
ifidn <fb_table>,<table>
|
||
shl bx,1 ;; 4
|
||
shl bx,1
|
||
endif
|
||
ifidn <pb_table>,<table>
|
||
shl bx,1 ;; 4
|
||
shl bx,1
|
||
endif
|
||
ifidn <state_table>,<table>
|
||
mov bh,bl
|
||
shl bx,1 ;;shift BH and BL simultaneously
|
||
shl bl,1
|
||
shl bl,1
|
||
add bl,bh ;; 10
|
||
xor bh,bh
|
||
endif
|
||
ifidn <status_table>,<table>
|
||
shl bx,1 ;; 2
|
||
endif
|
||
endm
|
||
|
||
; *** All registers on entry except CS,IP belong to the child. ***
|
||
; *** On exit, all registers except CS,IP,DS still belong to the child. ***
|
||
; This routine captures all the child's registers' values (except CS:IP,
|
||
; which is located on the stack at the saved SS:SP).
|
||
; DS is changed to PCS's data segment.
|
||
save_state macro
|
||
push ds ;pushes are in child's data segment
|
||
push ax
|
||
mov ax,data
|
||
mov ds,ax ;DS points to PCS's data segment
|
||
pop ax ;get back ax
|
||
mov save_ax,ax
|
||
mov save_bx,bx
|
||
mov save_cx,cx
|
||
mov save_dx,dx
|
||
mov save_si,si
|
||
mov save_di,di
|
||
pop ax ;get back ds (stack now same as on entry)
|
||
mov save_ds,ax
|
||
mov save_es,es
|
||
mov save_ss,ss
|
||
mov save_sp,sp
|
||
mov save_bp,bp
|
||
endm
|
||
|
||
; Save the parent's (i.e. PCS's) segment and pointer registers.
|
||
save_parent macro
|
||
mov pcs_state.st_es,es ;save our state
|
||
mov pcs_state.st_ss,ss
|
||
mov pcs_state.st_sp,sp
|
||
mov pcs_state.st_bp,bp
|
||
mov pcs_state.st_ds,ds
|
||
endm
|
||
|
||
; Restore the parent's segment and pointer registers.
|
||
restore_parent macro
|
||
mov bx,offset pcs_state ;restore parent's state
|
||
cli
|
||
mov es,[bx].st_es
|
||
mov ss,[bx].st_ss
|
||
mov sp,[bx].st_sp
|
||
mov bp,[bx].st_bp
|
||
;; mov ds,[bx].st_ds ;save_state made DS active already
|
||
sti
|
||
endm
|
||
|
||
; Save off our registers and restore child's, then resume child.
|
||
call_child macro x
|
||
save_parent
|
||
load_index state_table
|
||
lea bx,state_table[bx]
|
||
cli ; restore child's state
|
||
mov es,[bx].st_es
|
||
mov ss,[bx].st_ss
|
||
mov sp,[bx].st_sp
|
||
mov bp,[bx].st_bp
|
||
mov ds,[bx].st_ds
|
||
sti
|
||
xlidbg&x label byte
|
||
nop ;;this gets replaced with INT 3 for debug
|
||
nop
|
||
db 0CBh ;resume child via far return
|
||
endm
|
||
|
||
; Save off child's registers and restore ours, then continue.
|
||
resume_parent macro
|
||
save_state ;save child's registers in global area
|
||
restore_parent
|
||
load_index state_table
|
||
lea bx,state_table[bx]
|
||
mov ax,save_ds ;save child's regs in child-local area
|
||
mov [bx].st_ds,ax
|
||
mov ax,save_es
|
||
mov [bx].st_es,ax
|
||
mov ax,save_ss
|
||
mov [bx].st_ss,ax
|
||
mov ax,save_sp
|
||
mov [bx].st_sp,ax
|
||
mov ax,save_bp
|
||
mov [bx].st_bp,ax
|
||
endm
|
||
|