How to Convert Unsigned Integer from Another Language to Basic (58103)



The information in this article applies to:

  • Microsoft QuickBASIC 4.0
  • Microsoft QuickBASIC 4.0b
  • Microsoft QuickBASIC 4.5
  • Microsoft BASIC Compiler for MS-DOS and OS/2 6.0
  • Microsoft BASIC Compiler for MS-DOS and OS/2 6.0b
  • Microsoft Basic Professional Development System (PDS) for MS-DOS and MS OS/2 7.0
  • Microsoft Basic Professional Development System (PDS) for MS-DOS and MS OS/2 7.1

This article was previously published under Q58103

SUMMARY

This article describes how to convert an unsigned integer value (returned from another language) to a Basic LONG integer, keeping the sign correct. This conversion is necessary because Basic does not support an unsigned integer data type.

MORE INFORMATION

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 a language such as C or assembly language, or after calling an MS-DOS interrupt.

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," or see an assembly language book that discusses signed two's-complement data types.

Here is the simplest function to convert a 2 byte unsigned integer (stored in the Basic variable num%) to an unsigned number stored in a Basic LONG integer:
   num% = -1
   PRINT unsignedlong&(num%)   ' Prints 65535
   FUNCTION unsignedlong& (num%)
       IF num% < 0 THEN
               unsignedlong& = num% + 65536
       ELSE
               unsignedlong& = num%
       END IF
   END FUNCTION
				
You can also convert an unsigned integer to a positive Basic LONG integer using bit manipulation 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. 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.
Here is the simplest bit manipulation function to convert an unsigned integer to a positive Basic LONG integer:
   num% = -1
   PRINT Unsigned&(num%)   ' Prints 65535
   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.0 and 7.1 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.0 and 7.1 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
				

Modification Type:MinorLast Reviewed:1/9/2003
Keywords:KB58103 kbAudDeveloper