Q58103: How to Convert Unsigned Integer from Another Language to BASIC
Article: Q58103 Product(s): See article Version(s): 4.00 4.00b 4.50 Operating System(s): MS-DOS Keyword(s): ENDUSER | SR# S900111-205 B_BasicCom S_C H_MASM S_QuickC | mspl13_basic Last Modified: 10-JAN-1991 This article describes how to convert an unsigned integer value (returned from another language) to a BASIC LONG integer, keeping the sign correct. Bit manipulation is necessary in this conversion because BASIC does not support an unsigned integer data type. This information applies to Microsoft QuickBASIC versions 4.00, 4.00b, and 4.50, to Microsoft BASIC Compiler versions 6.00 and 6.00b for MS-DOS and MS OS/2, and to Microsoft BASIC Professional Development System (PDS) versions 7.00 and 7.10 for MS-DOS and MS OS/2. BASIC does not support an unsigned integer data type. However, there are times when a BASIC program must accept an unsigned integer type returned after calling a function in languages such as C or assembly language. If your other-language routine returns an unsigned integer to a BASIC INTEGER data type, and if the value of the integer exceeds 32,767 (or 7FFF hex), it will PRINT in BASIC as a negative number, even though the CALLed routine meant to return a positive number in the range of 32,768 to 65,535 (passed as an unsigned integer). In such a case, your BASIC program must convert the number to a positive number stored in a BASIC long integer. BASIC stores both INTEGER and LONG data types as signed two's-complement numbers. In signed two's-complement format, the highest bit in the number is a a sign bit. When a BASIC program is passed an unsigned integer from another language, and the number is in the range of 32,768 to 65,535, the highest bit will be set, causing BASIC to treat the number as negative. For more information, see Pages 16-17 of "Microsoft QuickBASIC 4.0: BASIC Language Reference," in the "Data Types" Chapter 2; or see an assembly language book that discusses signed two's-complement data types. You can convert an unsigned integer to a positive BASIC LONG integer as follows: 1. Check if the integer is positive or zero. If BASIC already recognizes the number as positive or zero, then either use it as is, or assign it directly to a long integer and skip the next three steps. 2. Otherwise, if the number (x%) is negative, then set the high bit to zero, as follows: x% = x% AND &H7FFF& 3. Assign the number to a long integer, as follows: y& = x% 4. Then set the 15th bit (counting from bit zero) back to a one, as follows: y& = (y& OR &H8000&) The long integer (y&) now contains the correct positive integer that the other-language routine meant to pass back to BASIC. A simple way to do this is to use the following function: FUNCTION Unsigned&(param%) Unsigned& = &HFFFF& AND param% END FUNCTION Example 1 --------- The following program converts the unsigned integer stored in x% to a positive LONG integer stored in y&: x% = -1 ' -1 in two's complement is 65535 as unsigned integer IF x% < 0 THEN ' Set the 15th bit to zero (counting from bit 0): x% = (x% AND &H7FFF&) ' Assign it to a LONG integer: y& = x% ' Set the 15th bit back to a one: y& = (y& OR &H8000&) ELSE y& = x% END IF PRINT y& ' Prints 65535 Example 2 --------- The following is a BASIC code example that CALLs the INTERRUPT routine provided in QB.QLB or QB.LIB. This program accesses the PC system clock to get the number of clock ticks since midnight. It then calculates the number of seconds (in hundredths) since midnight. To run the program in the QuickBASIC editor, you must load the QB.QLB library, as follows: QB TIMEINT.BAS /L QB.QLB For BASIC PDS 7.00 and 7.10 do the following instead: QBX TIMEINT.BAS /L QBX.QLB To compile and LINK the program, use the following: BC TIMINT.BAS; LINK TIMINT,,,QB.LIB; For BASIC PDS 7.00 and 7.10 LINK as follows instead: LINK TIMEINT,,,QBX.LIB; Code Example ------------ DEFLNG A-Z ' $INCLUDE: 'qb.bi' CONST tps = 18.2064699073# ' tps is ticks per second DIM inregs AS RegType, outregs AS RegType DIM flag AS INTEGER, Previous AS LONG CLS WHILE 1 inregs.ax = 0 CALL INTERRUPT(&H1A, inregs, outregs) ' CX should never be larger than &H0017, so direct ' assignment is possible. ticks& = outregs.cx * &H10000 ' This IF statement is the part that accomplished the conversion. ' First, only convert if BASIC thinks it's a negative number. IF outregs.dx < 0 THEN ' Set the 15th bit to zero (counting from 0) a2& = (outregs.dx AND &H7FFF&) ' Assign it to a LONG integer. ticks& = (ticks& + a2&) ' Set the 15th bit back to a one. ticks& = (ticks& OR &H8000&) ELSE ' Otherwise, just assign it to a long or use it 'as is'. ticks& = ticks& + outregs.dx END IF IF Previous > ticks& THEN BEEP ' It's midnight! Previous = ticks& Previous = ticks& seconds# = ticks& / tps 'ticks per second LOCATE 10, 10 PRINT "Clock ticks since midnight: "; PRINT ticks& LOCATE 11, 10 PRINT "Seconds since midnight: "; ' Print out the seconds to the hundredths place. PRINT USING "######.##"; seconds# WEND END
THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY.
Copyright Microsoft Corporation 1986-2002.