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
|
|||
|
|