Dec 222017
 
Various DOS routines using interrupts in QBASIC V4.0+.
File QBINTERS.ZIP from The Programmer’s Corner in
Category BASIC Language
Various DOS routines using interrupts in QBASIC V4.0+.
File Name File Size Zip Size Zip Type
BREAK.BAS 989 378 deflated
DOSVERS.BAS 886 347 deflated
DRIVE.BAS 975 355 deflated
EXIST.BAS 1014 414 deflated
FREE.BAS 953 393 deflated
GETKEY.BAS 1156 401 deflated
INTERRUP.DOC 9132 3162 deflated
INTERRUP.NEW 152054 34375 deflated
INTERRUP.SUM 44671 10468 deflated
MOUSE.BAS 2314 763 deflated
NEWDATE.BAS 1625 583 deflated
PRINTER.BAS 1503 462 deflated
PRINTOUT.BAS 737 293 deflated
READPOS.BAS 947 370 deflated
SCROLL.BAS 1535 592 deflated
SETDRIVE.BAS 1433 482 deflated
TPCREAD.ME 199 165 deflated
VIDEO.BAS 1668 491 deflated

Download File QBINTERS.ZIP Here

Contents of the INTERRUP.DOC file


REMARKS ON THE USE OF INTERRUPTS
David A. Wesson
24 Fairview St.
W. Hartford, CT 06119
203-523-1873


Here's everything I have pieced together to date about interrupts.

Interrupts are segments of memory where the various information is
stored that tells the computer what to do. These segments are
refered to in hex, example: INT &H21. Within these segments there
are subsegments named AX, BX, CX, DX and some other less frequently
used areas. Thus, each interrupt is made up of these subsegments
which actually are the locations where information is stored.
Further, each subsegment has a high area and a low area. This means
that the AX register is made up of AH on the left and AL on the
right. The AH section is refered to by taking the value to be sent
to that register and multiplying it by 256 in decimal or 100 in hex.
For example, a value of 2 or &H2 sent to an AH register will be sent
as (2 * 256) or &H200. Using this system, an AH and an AL value can
be sent simultaneously by adding the AL value to the AH value.

Example: AH = 2 and AL = 3 becomes &H200 + &H3 or (256 * 2) + 3

Even more information can be packed into a register by making
reference to the individual binary bits that make up the register.
When the AX register is set to zero, it would look like this:
00000000 00000000 with the left set being AH and the right AL.
In binary, the number 1 looks like 00000001 and the number 257 is
10000001. This is how the entire register retains a number. However,
each of the 8 places (or bits, refered to as number 0 through 7) can
be used separately to hold information. For example, if the 4th bit
is 1, then some state of the system is true, if 0 then false, such as
whether the printer is turned on or off.

The simplest example of the use of an interrupt is the Print Screen
function which is activated by hitting [Shift]+[PrtSc] on the
keyboard. To activate the same response directly from within a
program, a call can be made to INT &H05. Any call of any setting seems
to activate the function. Thus the syntax for this call is just to
invoke the interrupt with 0s for each subsegment. This means that
the values for AX, BX etc are all set to 0 when the interrupt call
is made. When a call to an AX, BX etc register is specified, that
value is passed in the call statement. When an AH, AL, BH, BL etc is
to be passed, the formula (such as &H200 + &H3) is sent to its
respective AX, BX etc register.

The syntax for setting up an interrupt call in QuickBasic 4.0+ is
somewhat determined by how you define the data structures. The
following example uses a structure similar to the one recommended
by Microsoft.


Please do not assume that these routines work without testing. I
accept no responsibility for anything that happens. Generally, the
worst you'll get is a hung system from running any of these.

'*****************************************************************************
'This routine sends an ASCII code to the printer buffer. The buffer does not
'print until a 10 (line feed) is received.
'*****************************************************************************

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

DIM SHARED inregs AS RegType, outregs AS RegType

DECLARE SUB printout (code)

printout 10

SUB printout (code)
inregs.ax = code: inregs.bx = 0: inregs.cx = 0: inregs.dx = 0
CALL interrupt(&H17, inregs, outregs)
END SUB

'*******************************************************************

In this example, the TYPE section defines the data structure for the
values that are sent to the interrupt (INREGS) and are returned by
the interrupt (OUTREGS). Here, the AX register of INT &H17 is to be
sent the ASCII value defined here as "code". Code is sent to the
subroutine, where it is packed into the AX section of the INREGS
packet as INREGS.AX . This results in code being placed in the
printer buffer waiting to be printed when a code = 10 is received.
In this example, only a 10 is sent, which results in a Line Feed
being sent to the printer. This routine should facilitate sending
upper ASCII codes or some peculiar codes that would be inconvenient
to send otherwise. (Anyway, I figured out how to do it, that's all
that counts.) Other functions are more complex and can't be
approached in QB any other way.

In the next example, the returned values of the registers are what
are important.

'****************************************************************************
'This routine reads the current position of the cursor--row and column.
'****************************************************************************

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

DIM SHARED inregs AS RegType, outregs AS RegType

DECLARE SUB readpos (row, col)

CLS
LOCATE 9, 14
readpos row, col
PRINT row, col

SUB readpos (row, col)
inregs.ax = &H300: inregs.bx = 0: inregs.cx = 0: inregs.dx = 0
CALL interrupt(&H10, inregs, outregs)
dh = FIX(outregs.dx / 256)
dl = outregs.dx - (dh * 256))
row = dh + 1
col = dl + 1
END SUB

'****************************************************************************

In this example, the value of &H3 is being sent to the AH register of
INT &H10 as AX = &H300 (&H3 * 100). This causes the interrupt to send
back the cursor position contained in the DX register. The row value
is contained in the DH section, column value in the DL section.
Thus, the math that seperates the DH and DL out of the DX register
is shown:

dh equals the integer value of dx divided by 256.
dl equals what's left in the dx register after the dh is removed.

Thus, if the cursor is at row 11, column 4, the dx register would
return (10 * 265) + 3 or 2653. (The row and column are noted as
beginning at LOCATE 0,0 which is impossible in QB, but means
LOCATE 1,1).

When the information you want is packed at the binary level, the
unpacking is more complex. In the following example, the individual
bits are seperated to see what each 0 or 1 value is:

'*****************************************************************************
'This routine checks to see if printer (assumes LPT1:) is turned on. If the
'returned value is 0 then the printer is OFF LINE, if 1 the printer is ON lINE
'*****************************************************************************

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

DIM SHARED inregs AS RegType, outregs AS RegType

DECLARE FUNCTION printer ()

PRINT printer

FUNCTION printer
inregs.ax = 2 * 256: inregs.dx = 0
CALL interrupt(&H17, inregs, outregs)
ah = FIX(outregs.ax / 256)
bit7 = FIX(ah / 128)
bit6 = FIX((ah - (bit7 * 128)) / 64)
bit5 = FIX((ah - (bit7 * 128) - (bit6 * 64)) / 32)
bit4 = FIX((ah - (bit7 * 128) - (bit6 * 64) - (bit5 * 32)) / 16)
bit3 = FIX((ah - (bit7 * 128) - (bit6 * 64) - (bit5 * 32) - (bit4 * 16)) / 8)
bit2 = FIX((ah - (bit7 * 128) - (bit6 * 64) - (bit5 * 32) - (bit4 * 16) - (bit3 * 8)) / 4)
bit1 = FIX((ah - (bit7 * 128) - (bit6 * 64) - (bit5 * 32) - (bit4 * 16) - (bit3 * 8) - (bit2 * 4)) / 2)
bit0 = FIX((ah - (bit7 * 128) - (bit6 * 64) - (bit5 * 32) - (bit4 * 16) - (bit3 * 8) - (bit2 * 4) - (bit1 * 2)))
PRINT bit0; bit1; bit2; bit3; bit4; bit5; bit6; bit7
printer = ABS(bit6)
END FUNCTION

In this value, bit 6 contains the clue as to whether the printer is
turned on. This example sends the value of 2 to AH of INT &H17 and
then reads the bits in the AH section of OUTREGS.AX.

'*******************************************************************

This archive contains a set of interrupt routines written in
QuickBasic 4.5. To use them, load the QB.QLB file when you enter the
editor.

Example command line: QB video /Lqb.qlb

To compile from the DOS line, modify the link command as follows:

LINK ,,,qb.lib,


The next piece of information you need is to know which interrupts
do what and what registers to use. Fortunately, a group of super-PD
programmers have compiled a list of all the known interrupt calls.
A summary of that file is in INTERRUP.SUM and a half subset of their
full text is in INTERRUP.NEW. To get the full file, plus all the
rest of their information, look for their updates on EXEC-PC or
other major bulletin boards. This subset is included to get you
started.













 December 22, 2017  Add comments

Leave a Reply