This is only a preview of the June 1994 issue of Silicon Chip. You can view 35 of the 96 pages in the full issue, including the advertisments. For full access, purchase the issue for $10.00 or subscribe for access to the latest issues. Articles in this series:
Items relevant to "A Coolant Level Alarm For Your Car":
Items relevant to "An 80-Metre AM/CW Transmitter For Amateurs":
Items relevant to "Convert Your Phono Inputs To Line Inputs":
Items relevant to "A PC-Based Nicad Battery Monitor":
Articles in this series:
Articles in this series:
Articles in this series:
|
COMPUTER BITS
BY DARREN YATES
BIOS interrupts: your
computer’s nuts & bolts
This month, we continue our discussion on
BIOS routines & look at how you can gain access
to them using QBasic & QuickBASIC 4.5. In this
article, we take a look at the keyboard routines
& see how you can check the keyboard status.
The built-in operating system
(BIOS) is the most basic level at which
structured routines can be accessed
and used by your computer. They handle everything from keyboard input
to disc drives to video displays and
updating the real-time clock.
By using these routines, you can
gain access to areas of your machine
that are not easily done through normal programming methods and you
can perform new tasks that are not
found in standard languages.
Most computer programs you buy
these days all use combinations of key
strokes in order for some function to
take place. Windows is a perfect example. To get the FILE menu to appear,
you have to press the ALT key down
and then “F”. QBasic and QuickBASIC
both use this type of key function in
their integrated devel
opment environments.
Other keys
However, the BIOS can actually go
quite a bit further than that by allowing
you to check the following keys:
• right SHIFT key
• left SHIFT key
• CONTROL key
• ALT key
• INSERT key
• NUM LOCK key
• SCROLL LOCK key
• CAPS LOCK key
BIOS Interrupt 16H, service 02H is
designated READ KEYBOARD SHIFT
TABLE 1: AX Register On Return From INT 16 Service 02H
Bit 7
Bit 6
Bit 5
Bit 4
Bit 3
Bit 2
Bit 1
Bit 0
x
Insert key on
x
Caps Lock on
x
Num Lock
x
Scroll Lock
x
Alt key pressed
x
Control key pressed
x
Left shift key pressed
x
66 Silicon Chip
Right shift key pressed
STATUS and returns an 8-bit code,
each bit representing the setting of
one of the above keys. This is shown
in detail in Table 1. As you can see,
the most significant bit represents the
INSERT key, bit 6 the CAPS LOCK key
and so on. Note that a “1” for each bit
means that the key is either down or
locked on. Note also that it’s possible
to distinguish between the right and
left shift keys which is not normally
achievable in most languages.
QuickBASIC is not very good at
allowing programmers to check for
multiple keys down and all of the
routines provided only allow you to
check for one key at a time. However,
the people at Microsoft did at least
give us the ability to access the interrupts through the CALL INTERRUPT()
subroutine.
Unfortunately, CALL INTERRUPT()
didn’t make it into QBASIC either so
we’ve used the generic CALL ABSOLUTE() to perform the same task.
Keyboard.bas
The program elsewhere in this
column, KEYBOARD.BAS, uses CALL
ABSOLUTE(), QuickBASIC’s assembly
language link, to access the BIOS
interrupt 16H and will give you an
idea of how to use this program to
add to your own programs. Wherever
possible, we have included remarks
to give you a clearer picture of what
is going on.
As with other programs that we
have presented over recent times, the
assembly code is placed into DATA
statements and then read into an
integer array called ASMPROGRAM.
Each data line contains one instruction which is listed next to it in the
remarks. The &H indicates that the
hexadecimal code is being entered
which is automatically converted
across to decimal.
Let’s just pause for a moment and
take a look at the assembly code. The
first line – PUSH BP – pushes the base
pointer onto the stack. The BP register
is a secondary stack pointer which is
used to access data on the stack relative
to a given location. We are simply storing the current value while we muck
around elsewhere.
The next line – MOV BP,SP – is
short for “MOVe the value of the stack
pointer(SP) into the base pointer (BP)”.
This makes the base pointer look at the
area where our assembly program is.
After that comes MOV AH,02H
which places the hex number 02 into
the register AH. Remember that there
are four general purpose registers in
the 8086 – AX to DX – each of which
can be referenced by the high or low
8-bits; ie, AH and AL, BH and BL and
so on. Loading 02 into AH forewarns
the program that we are requesting
service 2 of the following interrupt.
That interrupt is performed upon
the instruction INT 16H. Once completed, the keyboard status bits are
returned in the lower 8-bits of AX;
ie, in half-register AL. The next line
uses some indirect addressing – the
most powerful addressing mode the
8086 has – and moves the contents of
the base pointer + 6 into register BX.
This is where some newcomers can
get a bit stuck. It doesn’t store the value
of the “base pointer + 6” into BX but
rather the contents of the base pointer
+ 6 from the stack into BX.
MOV [BX],AX tells the computer
to store the current contents of the
AX register into the memory address
pointed to by register BX. Remember
that AX contains our keyboard info in
its lower 8 bits. Again, this is another
bit of indirect addressing.
POP BP returns the stored value
of BP back from the stack to restore
the original base pointer, ready to go
back to the BASIC program and RET 2
returns us to the BASIC program. The
“2” tells the machine to adjust the
stack pointer to account for the integer
variable X (all integer variables are two
bytes wide).
Once the code is entered into the
array, the segment and offset address
of the first element in the array must
be found. This is so that we can tell
the CALL ABSOLUTE() routine where
the assembly language routine begins.
This is done by the VARSEG and
VARPTR commands.
VARSEG finds the segment address
of the array while VARPTR finds the
offset address. You’ll notice that the
current segment is transferred to the
segment address of the array in the
one line: DEF SEG = VARSEG(ASM
PROGRAM(1)).
The CALL command is then made
with the offset address of the first element of the array as well as the return
variable X as the two arguments.
Upon return, variable X contains the
8-bit information in decimal code; ie,
if the INSERT key is on, X will contain
128. If the ALT key is down as well,
the code will be 136 (128 + 8). Each bit
is then just stripped from the variable
and then the appropriate action taken.
AND statement
Using the AND statement is exactly
like using normal digital logic gates but
it is one that often gives new program
mers a good deal of trouble.
As an example, let’s take a look at
the theoretical line:
VALUE = 112 AND 64
June 1994 67
Basic Listing For Keyboard Utility
‘ Keyboard Shift Status Utility
‘ Copyright 1994 Darren Yates B.Sc.
‘ for Silicon Chip Publications Pty Ltd
DEFINT A-Z
DIM asmprogram(1 TO 20)
position(0) = 5
position(1) = 15
position(2) = 27
position(3) = 38
position(4) = 47
position(5) = 54
position(6) = 62
position(7) = 71
DATA &h55
DATA &h89,&he5
DATA &hb4,&h02
DATA &hcd,&h16
DATA &h8b,&h5e,&h06
DATA &h89,&h07
DATA &h5d
DATA &hca,&h02,&h00
: ‘ PUSH BP
: ‘ MOV BP,SP
: ‘ MOV AH,02h
: ‘ INT 16h
: ‘ MOV BX,[BP+6]
: ‘ MOV [BX],AX
: ‘ POP BP
: ‘ RET 2
start = VARPTR(asmprogram(1))
DEF SEG = VARSEG(asmprogram(1))
FOR byte = 0 TO 16 - 1
READ newbyte
POKE start + byte, newbyte
NEXT byte
CLS
LOCATE 1, 1: PRINT “Keyboard SHIFT status utlity”
LOCATE 2, 1: PRINT “Copyright 1994 Darren Yates B.Sc.”
DO WHILE UCASE$(an$) <> “Q”
DEF SEG = VARSEG(asmprogram(1))
CALL absolute(x, VARPTR(asmprogram(1)))
DEF SEG
LOCATE 4, 1: PRINT “ <Insert> <Caps lock> <Num Lock> <Scrl
Lock> <Alt> <Ctrl> <L Shft> <R Shft> “
FOR bit = 7 TO 0 STEP -1
IF x AND (2 ^ bit) THEN
LOCATE 5, position(7 - bit): COLOR 15, 1: PRINT “ON “
ELSE
LOCATE 5, position(7 - bit): COLOR 7, 8: PRINT “OFF”
END IF
NEXT bit
COLOR 7, 8
LOCATE 7, 1: PRINT “ Press <Q> to quit. . .”
an$ = INKEY$
LOOP
END
68 Silicon Chip
Now we can assume that we are dealing with two
8-bit numbers since both are less than 256. If we look at
the number 112 in binary notation, this works out to be
01110000. The number 64 becomes 01000000.
Now just as you would expect in digital electronics, the
AND function in BASIC works the same way; ie, each bit is
high only if both corresponding bits of the two operands
are high. Doing some simple maths:
01110000
01000000+
01000000
Hence, the answer returned to variable VALUE is 64.
The AND function is therefore ideal for checking if a
particular bit is set or cleared.
Getting back to KEYBOARD.BAS, once the CALL subroutine has been completed, the segment address has to
be returned to BASIC’s current modus operandi so that
the BASIC section of the program can continue.
All of this is performed inside a DO..LOOP loop so that
a continuous check can been made on the keyboard until
such time as the “Q” key has been pressed.
Now each bit is checked inside a FOR..NEXT loop and
although it may not be immediately apparent, each run
of the loop corresponds to one of the eight bits in variable
X. By ANDing the variable with 2 raised to the power
of the current loop pointer, we can check each bit from
the most significant bit (bit 7) down to bit 0. BASIC has
no trouble converting between hex, decimal and binary
code and each one is used where appropriate to make
understanding the program easier.
Now if the particular bit which the FOR..NEXT loop is
looking at is set, then the program prints the word “ON”
at the appropriate position on the screen underneath that
particular key function. We could have used a stack of
IF..THEN statements or the CASE SELECT statement or
any number of alternatives but we think this is the most
compact.
As well as that, the program is also quite quick as you
would expect when running machine code. The array
POSITION holds the correct tab points so that after each
bit is checked the right response can be printed in the
correct position. This also saves us having to have separate
PRINT statements for each bit. Since the POSITION array
only has seven elements, we don’t need to dimension it,
which saves us another program line.
This program will work on all versions of QBasic as
well as QuickBASIC versions 4 and up. You can try it also
on anything from an XT to a Pentium and you shouldn’t
have any problems as the CALL ABSOLUTE() command
can only handle 8086/88 mnemonics.
Next month, we look at another BIOS interrupt
which will enable you to speed up some Windows
SC
operations.
Where To Buy The Software
We can supply copies of both KEYBOARD.BAS and a
compiled version, KEYBOARD.EXE, on either a 5.25-inch
or 3.5-inch disc for $7 plus $3 postage and packaging.
You can send in a cheque/money order to SILICON CHIP,
PO Box 139, Collaroy, NSW 2097; or phone in your credit
card details on (02) 979 5644.
|