home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Supreme Volume 6 #1
/
swsii.zip
/
swsii
/
102
/
S3BAS11.ZIP
/
S3DATE.BAS
< prev
next >
Wrap
BASIC Source File
|
1993-04-02
|
7KB
|
213 lines
' 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