PAGE 56,132
TITLE IntCode.ASM
SUBTTL QBASIC Interpreter DOS/BIOS interrupt call bin file
;
; IntCode.ASM - (C) 1991 by Brent Ashley
; Allows interrupt calls from within QBASIC Interpreter.
; Parameter: pointer to var of TYPE RegTypeX same as in QB4.5
; If DS or ES in structure is set to -1, they are initialized to
;   DGROUP (BASIC's DS)
; Calls interrupt 21h unless caller modifies bin file on the fly
;   with user-defined INTERRUPT subprogram, as distributed
;   by author.
;
; Written with Microsoft QC/QuickAssembler v2.51 
;   
; Assembled as follows:
;   QCL IntCode.ASM
;   EXE2BIN IntCode
;   DEL IntCode.EXE
;   DEL IntCode.OBJ
;

; Equates for Rgs parameter
AX_ = +0
BX_ = +2
CX_ = +4
DX_ = +6
BP_ = +8
SI_ = +10
DI_ = +12
FL_ = +14
DS_ = +16
ES_ = +18

.MODEL medium, BASIC
.CODE

Int21 PROC  USES si di ds, Rgs:PTR WORD

LOCAL TempBP:WORD, BasicDS:WORD, TempBX:WORD, TempDS:WORD

  push bp           ; save bp for later

  mov bx,Rgs        ; use bx as index ptr to Rgs registers var

  mov ax,[bx].DS_   ; check ds for -1
  cmp ax,0FFFFh     ; 
  jne dschecked     ; if not, skip default setting
  push ds
  pop [bx].DS_      ; set to default ds
dschecked:  
  mov ax,[bx].ES_   ; check es for -1
  cmp ax,0FFFFh     ; 
  jne eschecked     ; if not, skip default setting
  push ds
  pop [bx].ES_      ; default es to ds
eschecked:  

  mov ax,[bx].BP_   ; load TempBP thru ax while bp in use for stack frame
  mov TempBP,ax

  mov ax,[bx].AX_   ; load ax 
                    ; bx loaded later due to indexing
  mov cx,[bx].CX_   ; load cx
  mov dx,[bx].DX_   ; load dx
  mov si,[bx].SI_   ; load si
  mov di,[bx].DI_   ; load di

  push [bx].ES_     ; use push/pop for seg regs
  pop es            ; load es

  push [bx].BX_     ; hold this for now
  push ds           ; save data seg now - it was needed for Rgs var
  pop BasicDS       ;
  push [bx].DS_     ;
  pop ds            ;

  mov bp,TempBP     ; load bp 
  pop bx            ; load bx
  
  int 21h           ; do it

  push bp           ; save returned bp
  mov bp,sp         ; restore our stack frame
  mov bp,[bp+2]     ; from stack (saved at start of routine)

  mov TempBX,bx     ; save bx to stack var
  mov bx,Rgs        ; restore Rgs ptr

  push ds           ; save ds to stack var
  pop TempDS        ;
  push BasicDS      ;
  pop ds            ; restore BASIC ds

  mov [bx].AX_,ax   ; load Rgs from registers
  mov ax,TempBX     ; load Rgs.bx from stack var thru ax
  mov [bx].BX_,ax   ;
  mov [bx].CX_,cx   ; cx
  mov [bx].DX_,dx   ; dx
  pop ax            ; bp thru ax
  mov [bx].BP_,ax   ;
  mov [bx].SI_,si   ; si
  mov [bx].DI_,di   ; di

  pushf             ; save flags to Rgs
  pop [bx].FL_      ;

  push es           ; es
  pop [bx].ES_      ;

  mov ax,TempDS     ; load ds from int return
  mov [bx].DS_,ax   ;

  pop dx            ; pop saved bp and discard

  ret               ; return to caller

Int21   ENDP

END
