home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
QBasic & Borland Pascal & C
/
Delphi5.iso
/
C
/
Samples
/
CASM.ARJ
/
SYSINT.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-09-05
|
7KB
|
413 lines
;_ sysint.asm Tue Jan 26 1988 Modified by: Walter Bright */
;Copyright (C) 1984-1988 by Northwest Software
;All Rights Reserved
;Written by Walter Bright
;Define ROM in order to generate a ROMable version
;ROM equ 1
nobdos equ 1 ;turn off definition of bdos macro
include macros.asm
begdata
c_extrn _doserrno,word
enddata
;struct WORDREGS {unsigned ax,bx,cx,dx,si,di,cflag,flags; };
_ax equ 0
_bx equ 2
_cx equ 4
_dx equ 6
_si equ 8
_di equ 10
_cflag equ 12
_flags equ 14
;struct SREGS { unsigned es,cs,ss,ds; };
_es equ 0
_cs equ 2
_ss equ 4
_ds equ 6
begcode sysint
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Get values of segment registers.
; segread(struct SREGS *sregs);
c_public segread
func segread
push BP
mov BP,SP
if SPTR
mov BX,P[BP]
mov _es[BX],ES
mov _cs[BX],CS
mov _ss[BX],SS
mov _ds[BX],DS
else
push DS
lds BX,P[BP]
mov _es[BX],ES
mov _cs[BX],CS
mov _ss[BX],SS
pop AX
mov _ds[BX],AX
mov DS,AX
endif
pop BP
ret
c_endp segread
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Generate an interrupt.
; Use:
; int int86(unsigned intnum, union REGS *input, union REGS *output);
; intnum = 8086 software interrupt number
; input = input register values
; output = output register values
; Returns:
; value of flags
; BP offset to first parameter passed to int86()
Q equ (P + 4 * SAVESIDI + 2)
c_public int86
func int86
.save <SI,DI>
.push <BP,DS>
mov BP,SP
;for return from interrupt, we need:
; flags
; segment
; offset
pushf
pop DX
push DX ;flags
push CS ;segment
mov AX,offset intret
push AX ;offset
and DH,0Ch ;reset T and I flags
push DX ;flags
ifdef ROM
clr BX
mov ES,BX ;look at base page
mov BL,Q[BP] ;interrupt number
shl BX,1
shl BX,1 ;*4 to get addr of vector
push ES:word ptr 2[BX] ;segment
push ES:word ptr [BX] ;offset
else
mov AL,Q[BP]
mov AH,35h
int 21h ;get vector in ES:BX
push ES
push BX
endif
if SPTR
mov BX,Q+2[BP] ;input registers
else
push DS
lds BX,Q+2[BP]
endif
mov AX,_ax[BX]
mov CX,_cx[BX]
mov DX,_dx[BX]
mov SI,_si[BX]
mov DI,_di[BX]
mov BX,_bx[BX]
if LPTR
pop DS
endif
iret ;fake an interrupt
intret:
mov BP,SP ;BP might have been trashed
intret2:
if SPTR
pop DS ;restore default DS
push BX
mov BX,Q+2+SIZEPTR[BP]
else
push BX
lds BX,Q+2+SIZEPTR[BP]
endif
INTTAIL:
pushf
pop _flags[BX]
mov _ax[BX],AX
mov _cx[BX],CX
mov _dx[BX],DX
mov _si[BX],SI
mov _di[BX],DI
pop _bx[BX]
sbb CX,CX ;note that status of C is maintained
mov _cflag[BX],CX ;set _cflag to non-zero if carry was set
if LPTR
pop DS
endif
jnc INT1 ;if no error occurred
mov _doserrno,AX
INT1:
cld ;C rules state that direction flag is forward
pop BP
.restore <DI,SI>
ret
c_endp int86
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Generate an interrupt.
; Use:
; intnum = BDOS interrupt number
; input = & struct regval, input register values
; output = & struct regval, output register values
; segregs = & struct SREGS, input segment registers
; val = int86x(intnum,input,output,segregs);
; Returns:
; value of flags
c_public int86x
func int86x
.save <SI,DI>
.push <BP,DS>
mov BP,SP
;for return from interrupt, we need:
; flags
; segment
; offset
pushf
pop DX
push DX ;flags
push CS ;segment
mov AX,offset intretx
push AX ;offset
and DH,0Ch ;reset T and I flags
push DX ;flags
ifdef ROM
clr BX
mov ES,BX ;look at base page
mov BL,Q[BP] ;interrupt number
shl BX,1
shl BX,1 ;*4 to get addr of vector
push ES:word ptr 2[BX] ;segment
push ES:word ptr [BX] ;offset
else
mov AL,Q[BP]
mov AH,35h
int 21h ;get vector in ES:BX
push ES
push BX
endif
if SPTR
mov BX,Q+2+SIZEPTR+SIZEPTR[BP] ;segregs
mov ES,_es[BX]
push _ds[BX]
mov BX,Q+2[BP] ;input registers
else
lds BX,Q+2+SIZEPTR+SIZEPTR[BP]
mov ES,_es[BX] ;value of ES for interrupt
push _ds[BX] ;value of DS for interrupt
lds BX,Q+2[BP]
endif
mov AX,_ax[BX]
mov CX,_cx[BX]
mov DX,_dx[BX]
mov SI,_si[BX]
mov DI,_di[BX]
mov BX,_bx[BX]
pop DS
iret ;fake an interrupt
intretx:
mov BP,SP
push BX
push DS
if SPTR
mov DS,[BP] ;default DS
mov BX,Q+2+SIZEPTR+SIZEPTR[BP] ;segregs
else
lds BX,Q+2+SIZEPTR+SIZEPTR[BP]
endif
mov _es[BX],ES ;value of ES after interrupt
pop _ds[BX] ;value of DS after interrupt
pop BX
jmp intret2
c_endp int86x
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Generate a DOS interrupt.
; Use:
; input = & struct regval, input register values
; output = & struct regval, output register values
; val = intdos(input,output);
; Returns:
; value of flags
c_public intdos
func intdos
.save <SI,DI>
.push <BP,DS>
mov BP,SP
if SPTR
mov BX,Q[BP] ;input registers
else
push DS
lds BX,Q[BP]
endif
mov AX,_ax[BX]
mov CX,_cx[BX]
mov DX,_dx[BX]
mov SI,_si[BX]
mov DI,_di[BX]
mov BX,_bx[BX]
if LPTR
pop DS
endif
int 21h
intdosfinish:
if SPTR
pop DS ;restore default DS
push BX
mov BX,Q+SIZEPTR[BP]
else
push BX
lds BX,Q+SIZEPTR[BP]
endif
jmp INTTAIL
c_endp intdos
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Generate a DOS interrupt.
; Use:
; input = & struct regval, input register values
; output = & struct regval, output register values
; segregs = & struct SREGS, input segment registers
; val = intdosx(input,output,segregs);
; Returns:
; value of flags
c_public intdosx
func intdosx
.save <SI,DI>
.push <BP,DS>
mov BP,SP
if SPTR
mov BX,Q+SIZEPTR+SIZEPTR[BP] ;BX = segregs
;Get ES and DS from *segregs.
;Can't realistically load SS or CS!
mov ES,_es[BX]
push _ds[BX] ;value of DS for interrupt
mov BX,Q[BP] ;input registers
else
lds BX,Q+SIZEPTR+SIZEPTR[BP]
mov ES,_es[BX]
push _ds[BX]
lds BX,Q[BP]
endif
mov AX,_ax[BX]
mov CX,_cx[BX]
mov DX,_dx[BX]
mov SI,_si[BX]
mov DI,_di[BX]
mov BX,_bx[BX]
pop DS
int 21h
push BX
push DS
if SPTR
mov BX,Q+SIZEPTR+SIZEPTR[BP]
mov DS,[BP] ;restore default DS
else
lds BX,Q+SIZEPTR+SIZEPTR[BP]
endif
mov _es[BX],ES
pop _ds[BX]
pop BX
jmp intdosfinish
c_endp intdosx
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Call BDOS.
; Use:
; val = bdos(func,dx,al)
; func = BDOS function number
; dx = value for dx register
; al = value for al register
; Returns:
; low 8 bits: value returned in AL
; high 8 bits: 0
if SPTR
c_public bdosx
func bdosx
c_endp bdosx ;behaves identical to bdos()
endif
c_public bdos
func bdos
push BP
mov BP,SP
.save <SI,DI>
mov DX,P+2[BP]
mov AL,P+4[BP]
mov AH,P[BP]
int 21h
B1: jnc B2
mov _doserrno,AX
B2:
ifndef MSC
clr AH
endif
.restore <DI,SI>
pop BP
ret
c_endp bdos
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Call BDOS.
; Use:
; val = bdosx(func,dsdx,al)
; func = BDOS function number
; dsdx = value for ds:dx register pair
; al = value for al register
; Returns:
; low 8 bits: value returned in AL
; high 8 bits: 0
if LPTR
c_public bdosx
func bdosx
push BP
mov BP,SP
.save <SI,DI>
push DS
lds DX,P+2[BP]
mov AL,P+2+SIZEPTR[BP]
mov AH,P[BP]
int 21h
pop DS
jmp B1
c_endp bdosx
endif
endcode sysint
end