pcs/xli.mac

181 lines
4.5 KiB
Plaintext
Raw Normal View History

2023-05-20 05:57:06 -04:00
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