home *** CD-ROM | disk | FTP | other *** search
- ' S3 Demo of calling interrupts using Microsoft's
- ' Visual BASIC for DOS.
- '
- ' Copyright April 1, 1993 George Spafford
- '
- ' This program is for AT BIOS type machines ONLY!
- ' It reads the date from the Real Time Clock chip
- ' using Interrupt 1AH and function 04H.
- '
- '-------------------------------------------------
-
- 'To use the in-line assembly calls, you must start
- 'your BASIC compiler with its specified library that
- 'contains support for the additional calls.
- 'For VBDOS: VBDOS S3DATE /L VBDOS
- ' QB 4.5: QB S3DATE /L QB
- '
- 'So on and so forth. If you do not, then you will get
- 'an error message stating that the function can not be
- 'found when the program attempts to execute the
- 'CALL INTERRUPT subroutine.
-
- 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
-
- 'The ?X registers are all 16 bit registers. Each
- '16 bit register can be split into two 8 bit registers
- 'titled ?H for high and ?L for low. For example, AX
- 'is comprised of AH and AL. BASIC operates at the
- '16 bit register level.
-
- DECLARE SUB INTERRUPT (IntNum AS INTEGER, InReg AS RegType, OutReg AS RegType)
-
- DIM InReg AS RegType
- DIM OutReg AS RegType
-
- DEFINT A-Z 'by default our variables will be
- 'integers.
-
- 'This example uses INT 1AH function 04H to read the
- 'Real Time Clock (RTC) date. It also serves as a good
- 'example on how to read and set high/low values in
- 'the 16 bit registers.
-
- 'One note on variable notation, in BASIC, &H signifies
- 'a hexadecimal value. This greatly simplifies making
- 'system calls since it saves you from converting to
- 'decimal.
-
- CLS
- PRINT "S3 Demo of reading the RTC Date using interrupts"
-
-
- 'CALL THE INTERRUPT
-
- IntNum = &H1A 'int 1AH
- InReg.AX = &H4 * 256 'loads &H4 into AH
- 'this is the function value
- 'this will destroy AL, multiplying
- 'by 256 shifts the 4H value to the
- 'high 8 bit register - remember,
- 'an 8-bit reg is 128, two is 256.
-
- CALL INTERRUPT(IntNum, InReg, OutReg)
-
- 'The next segment is an error trap. If the carry
- 'flag, which is in the flag register as bit 0, tests
- 'true, then the RTC is reporting that there is a
- 'problem. The use of bits will be discussed later.
-
- IF OutReg.Flags AND 1 THEN
- PRINT "ERROR: RTC reports a dead battery."
- END
- END IF
-
- 'Just a note about the below code segment,
- 'you must check for long integers, if the
- 'register were to contain a negative number,
- 'you must add 65536 to it to get the value.
- 'Essentially you are converting from a word
- 'to a Dword since QB interprets the highest bit
- 'as a indicator of the sign of a number. A
- 'Dword is a long integer with a value up to
- '2^31. In a large program, you should make
- 'the conversion routine a function.
-
- IF OutReg.CX < 0 THEN
- DWord& = OutReg.CX + 65536
- ELSE
- DWord& = OutReg.CX
- END IF
- CH = DWord& \ 256 'get CH from CX
- CL = DWord& AND &HFF 'get CL from CX
-
- IF OutReg.DX < 0 THEN
- DWord& = OutReg.DX + 65536
- ELSE
- DWord& = OutReg.DX
- END IF
- DH = DWord& \ 256 'get DH from DX
- DL = DWord& AND &HFF 'get DL from DX
-
-
- 'The next part is due to the Motorola MC-146818
- 'Real Time Clock Processor which is used in AT's.
- 'It returns the answer as a Binary Coded Decimal
- 'also known as a BCD. A BCD has its answer as
- 'two 4-bit values. Thus, our 8-bit registers must
- 'first be evaluated for the low value (V1) and the
- 'high value (V2). This bit wise evaluation is
- 'performed by using the AND operator. For a
- 'bit to be in position 1, it will test true with
- 'the value of one since the bit interpretation of
- '1 is 00000001. Thus, any number with a bit in
- 'the 1 position will test true under the AND
- 'function. This is where bit values come into
- 'play. I will explain this better after the
- 'following code segment.
-
- 'INTERPRET THE DATA
-
- V1 = 0: V2 = 0
- IF CH AND 1 THEN V1 = 1 'Low: bit 1
- IF CH AND 2 THEN V1 = V1 + 2 ' 2
- IF CH AND 4 THEN V1 = V1 + 4 ' 3
- IF CH AND 8 THEN V1 = V1 + 8 ' 4
-
- IF CH AND 16 THEN V2 = 1 'High: bit 1
- IF CH AND 32 THEN V2 = V2 + 2 ' 2
- IF CH AND 64 THEN V2 = V2 + 4 ' 3
- IF CH AND 128 THEN V2 = V2 + 8 ' 4
-
- 'Okay, all data can be represented as bits. For
- 'a single 8 bit byte, there are 8 possible
- 'positions.
- 'binary: Decimal:
- '00000001 = 2^0 = 1
- '00000010 = 2^1 = 2
- '00000100 = 2^2 = 4
- '00001000 = 2^3 = 8
- '00010000 = 2^4 = 16
- '00100000 = 2^5 = 32
- '01000000 = 2^6 = 64
- '10000000 = 2^7 = 128
- 'The AND operator allows you to test each bit
- 'position using the decimal value.
-
- Cent$ = LTRIM$(STR$(V2)) + LTRIM$(STR$(V1))
-
- V1 = 0: V2 = 0
- IF CL AND 1 THEN V1 = 1 'Low: bit 1
- IF CL AND 2 THEN V1 = V1 + 2 ' 2
- IF CL AND 4 THEN V1 = V1 + 4 ' 3
- IF CL AND 8 THEN V1 = V1 + 8 ' 4
- IF CL AND 16 THEN V2 = 1 'High: bit 1
- IF CL AND 32 THEN V2 = V2 + 2 ' 2
- IF CL AND 64 THEN V2 = V2 + 4 ' 3
- IF CL AND 128 THEN V2 = V2 + 8 ' 4
-
- Year$ = LTRIM$(STR$(V2)) + LTRIM$(STR$(V1))
-
- V1 = 0: V2 = 0
- IF DH AND 1 THEN V1 = 1 'Low: bit 1
- IF DH AND 2 THEN V1 = V1 + 2 ' 2
- IF DH AND 4 THEN V1 = V1 + 4 ' 3
- IF DH AND 8 THEN V1 = V1 + 8 ' 4
- IF DH AND 16 THEN V2 = 1 'High: bit 1
- IF DH AND 32 THEN V2 = V2 + 2 ' 2
- IF DH AND 64 THEN V2 = V2 + 4 ' 3
- IF DH AND 128 THEN V2 = V2 + 8 ' 4
-
- Month$ = LTRIM$(STR$(V2)) + LTRIM$(STR$(V1))
-
- 'To use less code, you could use a subroutine
- 'or two functions to get the V1 and V2 values.
- 'I opted for laying them out in a top-to-bottom
- 'manner to allow for easy reading.
- 'Note, you must clear V1 and V2 before you
- 'test the bits or else you may get an erronous
- 'figure if one of the 4-bit registers is 0.
-
- V1 = 0: V2 = 0
- IF DL AND 1 THEN V1 = 1 'Low: bit 1
- IF DL AND 2 THEN V1 = V1 + 2 ' 2
- IF DL AND 4 THEN V1 = V1 + 4 ' 3
- IF DL AND 8 THEN V1 = V1 + 8 ' 4
- IF DL AND 16 THEN V2 = 1 'High: bit 1
- IF DL AND 32 THEN V2 = V2 + 2 ' 2
- IF DL AND 64 THEN V2 = V2 + 4 ' 3
- IF DL AND 128 THEN V2 = V2 + 8 ' 4
-
- Day$ = LTRIM$(STR$(V2)) + LTRIM$(STR$(V1))
-
- LOCATE 4, 1
- PRINT "Century.....: "; Cent$
- PRINT "Year........: "; Year$
- PRINT "Month.......: "; Month$
- PRINT "Day.........: "; Day$
-
- 'So there you have it. Heck, if you feel lazy,
- 'then just use the DATE$ function ;-)
-
- END
-
-