; Copyright (c) 1988, 1993 ; The Regents of the University of California. All rights reserved. ; ; %sccs.include.redist.semicolon% ; ; @(#)spintasm.asm 8.1 (Berkeley) 06/06/93 ; ; The code in this file complete the spint calls spint struc ; union REGS spint_ax dw 1 spint_bx dw 1 spint_cx dw 1 spint_dx dw 1 spint_si dw 1 spint_di dw 1 spint_cflag dw 1 ; struct SREGS spint_es dw 1 spint_cs dw 1 spint_ss dw 1 spint_ds dw 1 ; int intno spint_intno dw 1 ; int done spint_done dw 1 ; int rc spint_rc dw 1 ; spint ends ENTER MACRO ; Begin enter push bp mov bp,sp push ax push bx push cx push dx push bp push di push si push ds push es pushf mov cs:start_sp, sp mov cs:start_ss, ss ; End enter ENDM LEAVE MACRO ; Begin leave cli mov sp, cs:start_sp mov ss, cs:start_ss sti popf pop es pop ds pop si pop di pop bp pop dx pop cx pop bx pop ax mov sp,bp pop bp ret ; End leave ENDM GETREGS MACRO wherefrom mov si, wherefrom mov spint_segment, ds mov spint_offset, si mov ax, spint_ax[si] mov bx, spint_bx[si] mov cx, spint_cx[si] mov dx, spint_dx[si] ; XXX mov si, spint_si[si] mov di, spint_di[si] mov es, spint_es[si] ; Now, need to do DS, SI push spint_ds[si] mov si, spint_si[si] pop ds ENDM SETREGS MACRO mov cs:old_si, si mov cs:old_ds, ds mov ds, cs:spint_segment mov si, cs:spint_offset mov spint_ax[si], ax mov spint_bx[si], bx mov spint_cx[si], cx mov spint_dx[si], dx mov spint_si[si], si mov spint_di[si], di mov spint_cs[si], cs mov spint_ds[si], ds mov spint_es[si], es mov spint_ss[si], ss ; now, need to do SI, DS mov ax, old_si mov spint_si[si], ax mov ax, old_ds mov spint_ds[si], ax ENDM _TEXT segment byte public 'CODE' _TEXT ends _DATA segment word public 'DATA' _DATA ends CONST segment word public 'CONST' CONST ends _BSS segment word public 'BSS' _BSS ends DGROUP group CONST, _BSS, _DATA assume cs:_TEXT, ds:DGROUP, ss:DGROUP, es:DGROUP _TEXT segment start_sp dw 1 dup (?) ; For use in our 'longjmp' start_ss dw 1 dup (?) ; For use in our 'longjmp' spint_segment dw 1 dup (?) ; Segment of spawn control block spint_offset dw 1 dup (?) ; Offset of spawn control block old_si dw 1 dup (?) ; SI of interrupt issuer (temporary) old_ds dw 1 dup (?) ; DS of interrupt issuer (temporary) issuer_ss dw 1 dup (?) ; ss of person who called us (permanent) issuer_sp dw 1 dup (?) ; sp of person who called us (permanent) int21_stack db 100 dup (?) ; Stack for int21. ; ; _spint_int gets control on an interrupt. It switches the stack ; and does a 'return' from _spint_start. ; public __spint_int __spint_int proc near mov cs:issuer_sp, sp mov cs:issuer_ss, ss sti SETREGS LEAVE __spint_int endp ; ; _spint_start issues the dos interrupt after setting up the passed ; registers. When control returns to it, it sets spint->done to non-zero. ; public __spint_start __spint_start proc near ENTER GETREGS 4[bp] ; Now, switch to a different (short) stack. This is so ; that our games won't mess up the stack int 21 (hardware and, ; possibly, software) stores things on. cli mov cs:int21_stack, cs mov ss, cs:int21_stack mov sp, offset int21_stack add sp, (length int21_stack) - 4 sti int 21H ; Issue DOS interrupt SETREGS mov ds, cs:spint_segment mov si, cs:spint_offset mov spint_done[si], 1 ; We are done LEAVE __spint_start endp ; ; After _spint_int has faked a return from start_spawn, we come here to ; return to the interrupt issuer. ; public __spint_continue __spint_continue proc near ENTER GETREGS 4[bp] mov sp, cs:issuer_sp ; Restore SP mov ss, cs:issuer_ss ; Restore SS iret __spint_continue endp _TEXT ends end