Home
Site Structure

Programming Home
  Basic Home
    GUI & OS Home
    QB Knowledge Base
    Professor Answers
    Codename Surena
    QB Downloads

Write Us

Special Links
QB DirectoryNEW

Codename Surena
Forums
Sepent Basic GUI & OS Home
Register Log In
QB Knowledge Base > How To Questions > Number 7

How to imitate CALL INTERRUPT in QBASIC 1.1?
Sometimes it is needed to call an interrupt service in QBASIC 1.1, and you know that this version of QBASIC doesn't support the INTERRUPT and INTERRUPTX routines. Here, there is a version of these routines that uses ABSOLUTE statement and can be used in QB1.1.

TYPE RegTypeX
	  AX    AS INTEGER
	  BX    AS INTEGER
	  CX    AS INTEGER
	  DX    AS INTEGER
	  BP    AS INTEGER
	  SI    AS INTEGER
	  DI    AS INTEGER
	  Flags AS INTEGER
	  DS    AS INTEGER
	  ES    AS INTEGER
END TYPE

TYPE RegType
	  AX    AS INTEGER
	  BX    AS INTEGER
	  CX    AS INTEGER
	  DX    AS INTEGER
	  BP    AS INTEGER
	  SI    AS INTEGER
	  DI    AS INTEGER
	  Flags AS INTEGER
END TYPE

'
'This procedure works the same as INTERRUPT routine in later
'versions of QuickBASIC.
'
'Parameters:
'	INTNUM: The interrupt number
'	InRegs: The values of registers for the interrupt routine
'	OutRegs: The values of the registers after calling the interrupt service
'
SUB Interrupt (INTNUM AS INTEGER, InRegs AS RegType, OutRegs AS RegType)
	DIM asm AS STRING
	DIM code(0) AS INTEGER

	asm = asm + CHR$(&H50)     'push ax
	asm = asm + CHR$(&H53)     'push bx
	asm = asm + CHR$(&H51)     'push cx
	asm = asm + CHR$(&H52)     'push dx
	asm = asm + CHR$(&H56)     'push si
	asm = asm + CHR$(&H57)     'push di
	asm = asm + CHR$(&H55)     'push bp
	asm = asm + CHR$(&H1E)     'push ds

	asm = asm + CHR$(&HB8) + MKI$(InRegs.Flags)        'mov  ax, inregs.flags
	asm = asm + CHR$(&H50)                             'push ax

	asm = asm + CHR$(&HB8) + MKI$(InRegs.AX)           'mov  ax, inregs.ax
	asm = asm + CHR$(&HBB) + MKI$(InRegs.BX)           'mov  bx, inregs.bx
	asm = asm + CHR$(&HB9) + MKI$(InRegs.CX)           'mov  cx, inregs.cx
	asm = asm + CHR$(&HBA) + MKI$(InRegs.DX)           'mov  dx, inregs.dx

	asm = asm + CHR$(&HBE) + MKI$(InRegs.SI)           'mov  si, inregs.si
	asm = asm + CHR$(&HBF) + MKI$(InRegs.DI)           'mov  di, inregs.di

	asm = asm + CHR$(&HBD) + MKI$(InRegs.BP)           'mov  bp, inregs.bp

	asm = asm + CHR$(&H9D)                             'popf

	asm = asm + CHR$(&HCD) + CHR$(INTNUM)              'int  intnum

	asm = asm + CHR$(&H50)     'push ax
	asm = asm + CHR$(&H53)     'push bx

	asm = asm + CHR$(&H9C)     'pushf
	asm = asm + CHR$(&H5B)     'pop  bx
	asm = asm + CHR$(&HB8) + MKI$(VARSEG(OutRegs.Flags))                             'mov  ax, varseg(outregs.flags)
	asm = asm + CHR$(&H8E) + CHR$(&HD8)                                              'mov  ds, ax
	asm = asm + CHR$(&H3E) + CHR$(&H89) + CHR$(&H1E) + MKI$(VARPTR(OutRegs.Flags))   'mov  ds:[varptr(outregs.flags)], bx

	asm = asm + CHR$(&H3E) + CHR$(&H89) + CHR$(&H36) + MKI$(VARPTR(OutRegs.SI))      'mov  ds:[varptr(outregs.si)], si

	asm = asm + CHR$(&H3E) + CHR$(&H89) + CHR$(&H3E) + MKI$(VARPTR(OutRegs.DI))      'mov  ds:[varptr(outregs.di)], di

	asm = asm + CHR$(&H3E) + CHR$(&H89) + CHR$(&H2E) + MKI$(VARPTR(OutRegs.BP))      'mov  ds:[varptr(outregs.bp)], bp

	asm = asm + CHR$(&H3E) + CHR$(&H89) + CHR$(&H16) + MKI$(VARPTR(OutRegs.DX))      'mov  ds:[varptr(outregs.dx)], dx

	asm = asm + CHR$(&H3E) + CHR$(&H89) + CHR$(&HE) + MKI$(VARPTR(OutRegs.CX))       'mov  ds:[varptr(outregs.cx)], cx

	asm = asm + CHR$(&H5B)                                                           'pop  bx
	asm = asm + CHR$(&H3E) + CHR$(&H89) + CHR$(&H1E) + MKI$(VARPTR(OutRegs.BX))      'mov  ds:[varptr(outregs.bx)], bx

	asm = asm + CHR$(&H58)                                                           'pop  bx
	asm = asm + CHR$(&H3E) + CHR$(&HA3) + MKI$(VARPTR(OutRegs.AX))                   'mov  ds:[varptr(outregs.ax)], ax

	asm = asm + CHR$(&H1F)     'pop  ds
	asm = asm + CHR$(&H5D)     'pop  bp
	asm = asm + CHR$(&H5F)     'pop  di
	asm = asm + CHR$(&H5E)     'pop  si
	asm = asm + CHR$(&H5A)     'pop  dx
	asm = asm + CHR$(&H59)     'pop  cx
	asm = asm + CHR$(&H5B)     'pop  bx
	asm = asm + CHR$(&H58)     'pop  ax

	asm = asm + CHR$(&HCB)     'retf
 
	REDIM code(LEN(asm) \ 2 + 1) AS INTEGER
	DEF SEG = VARSEG(code(0))
	FOR i = 1 TO LEN(asm)
		POKE VARPTR(code(0)) + i - 1, ASC(MID$(asm, i, 1))
	NEXT
	CALL Absolute(VARPTR(code(0)))
END SUB

'
'This procedure works the same as INTERRUPTX routine in later
'versions of QuickBASIC.
'
'This routine, supports segment registers (DS and ES) in addition
'to the registers supported by INTERRUPT routine.
'
'Parameters:
'	INTNUM: The interrupt number
'	InRegs: The values of registers for the interrupt routine
'	OutRegs: The values of the registers after calling the interrupt service
'
SUB InterruptX (INTNUM AS INTEGER, InRegs AS RegTypeX, OutRegs AS RegTypeX)
	DIM asm AS STRING
	DIM code(0) AS INTEGER

	asm = asm + CHR$(&H50)     'push ax
	asm = asm + CHR$(&H53)     'push bx
	asm = asm + CHR$(&H51)     'push cx
	asm = asm + CHR$(&H52)     'push dx
	asm = asm + CHR$(&H56)     'push si
	asm = asm + CHR$(&H57)     'push di
	asm = asm + CHR$(&H55)     'push bp
	asm = asm + CHR$(&H6)      'push es
	asm = asm + CHR$(&H1E)     'push ds

	asm = asm + CHR$(&HB8) + MKI$(InRegs.Flags)        'mov  ax, inregs.flags
	asm = asm + CHR$(&H50)                             'push ax

	asm = asm + CHR$(&HB8) + MKI$(InRegs.DS)           'mov  ax, inregs.ds
	asm = asm + CHR$(&H8E) + CHR$(&HD8)                'mov  ds, ax

	asm = asm + CHR$(&HB8) + MKI$(InRegs.ES)           'mov  ax, inregs.es
	asm = asm + CHR$(&H8E) + CHR$(&HC0)                'mov  es, ax

	asm = asm + CHR$(&HB8) + MKI$(InRegs.AX)           'mov  ax, inregs.ax
	asm = asm + CHR$(&HBB) + MKI$(InRegs.BX)           'mov  bx, inregs.bx
	asm = asm + CHR$(&HB9) + MKI$(InRegs.CX)           'mov  cx, inregs.cx
	asm = asm + CHR$(&HBA) + MKI$(InRegs.DX)           'mov  dx, inregs.dx

	asm = asm + CHR$(&HBE) + MKI$(InRegs.SI)           'mov  si, inregs.si
	asm = asm + CHR$(&HBF) + MKI$(InRegs.DI)           'mov  di, inregs.di

	asm = asm + CHR$(&HBD) + MKI$(InRegs.BP)           'mov  bp, inregs.bp

	asm = asm + CHR$(&H9D)                             'popf

	asm = asm + CHR$(&HCD) + CHR$(INTNUM)              'int  intnum

	asm = asm + CHR$(&H50)     'push ax
	asm = asm + CHR$(&H53)     'push bx

	asm = asm + CHR$(&H9C)     'pushf
	asm = asm + CHR$(&H5B)     'pop  bx
	asm = asm + CHR$(&HB8) + MKI$(VARSEG(OutRegs.Flags))                             'mov  ax, varseg(outregs.flags)
	asm = asm + CHR$(&H8E) + CHR$(&HD8)                                              'mov  ds, ax
	asm = asm + CHR$(&H3E) + CHR$(&H89) + CHR$(&H1E) + MKI$(VARPTR(OutRegs.Flags))   'mov  ds:[varptr(outregs.flags)], bx

	asm = asm + CHR$(&H3E) + CHR$(&H89) + CHR$(&H36) + MKI$(VARPTR(OutRegs.SI))      'mov  ds:[varptr(outregs.si)], si

	asm = asm + CHR$(&H3E) + CHR$(&H89) + CHR$(&H3E) + MKI$(VARPTR(OutRegs.DI))      'mov  ds:[varptr(outregs.di)], di

	asm = asm + CHR$(&H3E) + CHR$(&H89) + CHR$(&H2E) + MKI$(VARPTR(OutRegs.BP))      'mov  ds:[varptr(outregs.bp)], bp

	asm = asm + CHR$(&H3E) + CHR$(&H89) + CHR$(&H16) + MKI$(VARPTR(OutRegs.DX))      'mov  ds:[varptr(outregs.dx)], dx

	asm = asm + CHR$(&H3E) + CHR$(&H89) + CHR$(&HE) + MKI$(VARPTR(OutRegs.CX))       'mov  ds:[varptr(outregs.cx)], cx

	asm = asm + CHR$(&H5B)                                                           'pop  bx
	asm = asm + CHR$(&H3E) + CHR$(&H89) + CHR$(&H1E) + MKI$(VARPTR(OutRegs.BX))      'mov  ds:[varptr(outregs.bx)], bx

	asm = asm + CHR$(&H58)                                                           'pop  bx
	asm = asm + CHR$(&H3E) + CHR$(&HA3) + MKI$(VARPTR(OutRegs.AX))                   'mov  ds:[varptr(outregs.ax)], ax

	asm = asm + CHR$(&H8C) + CHR$(&HC0)                                              'mov  ax, es
	asm = asm + CHR$(&H3E) + CHR$(&HA3) + MKI$(VARPTR(OutRegs.ES))                   'mov  ds:[varptr(outregs.es)], ax
  
	asm = asm + CHR$(&H8C) + CHR$(&HD8)                                              'mov  ax, ds
	asm = asm + CHR$(&H3E) + CHR$(&HA3) + MKI$(VARPTR(OutRegs.DS))                   'mov  ds:[varptr(outregs.ds)], ax

	asm = asm + CHR$(&H1F)     'pop  ds
	asm = asm + CHR$(&H7)      'pop  es
	asm = asm + CHR$(&H5D)     'pop  bp
	asm = asm + CHR$(&H5F)     'pop  di
	asm = asm + CHR$(&H5E)     'pop  si
	asm = asm + CHR$(&H5A)     'pop  dx
	asm = asm + CHR$(&H59)     'pop  cx
	asm = asm + CHR$(&H5B)     'pop  bx
	asm = asm + CHR$(&H58)     'pop  ax

	asm = asm + CHR$(&HCB)     'retf
  
	REDIM code(LEN(asm) \ 2 + 1) AS INTEGER
	DEF SEG = VARSEG(code(0))
	FOR i = 1 TO LEN(asm)
		POKE VARPTR(code(0)) + i - 1, ASC(MID$(asm, i, 1))
	NEXT
	CALL Absolute(VARPTR(code(0)))
END SUB
		

For using these routines, you should declare a variable of type RegType (or RegTypeX) to set the values of the registers. You may also declare another variable of this type (or you may use the same variable) to receive the value of the registers after calling the interrupt service.

To get the above code in a BAS file, as well as an example of using the routines, you can download intrpt.zip.