4.1. Identifiers

An identifier is, quite simply, a name. Identifiers are used in PBP for line labels and variable names. An identifier is any sequence of letters, digits, and underscores, although it must not start with a digit. Identifiers are not case sensitive, thus label, LABEL, and Label are all treated as equivalent. And while labels might be any number of characters in length, PBP only recognizes the first 31.

4.2. Line Labels

In order to mark statements that the program might wish to reference with GOTO or GOSUB commands, PBP uses line labels. Unlike many older BASICs, PBP doesn't allow line numbers and doesn't require that each line be labeled. Rather, any PBP line may start with a line label, which is simply an identifier followed by a colon (:).

	here:	Serout 0,N2400,["Hello, World!",13,10]
		Goto here

4.3. Variables

Variables are where temporary data is stored in a PICBASIC PRO™ program. They are created using the VAR keyword. Variables may be bits, bytes or words. Space for each variable is automatically allocated in the microcontroller=s RAM by PBP. The format for creating a variable is as follows:

	Label	VAR	Size{.Modifiers}

Label is any identifier, excluding keywords, as described above. Size is BIT, BYTE or WORD. Optional Modifiers add additional control over how the variable is created. Some examples of creating variable are:

	dog	var	byte
	cat	var	bit
	w0	var	word

There are no predefined user variables in PICBASIC PRO™. For compatibility sake, two files have been provided that create the standard variables used with the BASIC Stamps: Abs1defs.bas@ and Abs2defs.bas@. To use one of these files, add the line:

Include "bs1defs.bas"


Include "bs2defs.bas"

near the top of the PICBASIC PRO™gram. These files contain numerous VAR statements that create all of the BASIC Stamp variables and pin definitions.

However, instead of using these "canned" files, we recommend you create your own variables using names that are meaningful to you.

The number of variables available depends on the amount of RAM on a particular device and the size of the variables and arrays. PBP reserves approximately 24 RAM locations for its own use. It may also create additional temporary variables for use in sorting out complex equations.

4.4. Aliases

VAR can also be used to create an alias (another name) for a variable. This is most useful for accessing the innards of a variable.

	fido	var	dog		' fido is another name for dog
	b0	var	w0.byte0	' b0 is the first byte of word w0
	b1	var	w0.byte1	' b1 is the second byte of word w0
	flea	var	dog.0		' flea is bit0 of dog

The variable modifiers may also be used as part of variables in a statement:

b = w0.byte0




BIT0 or 0

Create alias to bit 0 of byte or word

BIT1 or 1

Create alias to bit 1 of byte or word

BIT2 or 2

Create alias to bit 2 of byte or word

BIT3 or 3

Create alias to bit 3 of byte or word

BIT4 or 4

Create alias to bit 4 of byte or word

BIT5 or 5

Create alias to bit 5 of byte or word

BIT6 or 6

Create alias to bit 6 of byte or word

BIT7 or 7

Create alias to bit 7 of byte or word

BIT8 or 8

Create alias to bit 8 of word

BIT9 or 9

Create alias to bit 9 of word

BIT10 or 10

Create alias to bit 10 of word

BIT11 or 11

Create alias to bit 11 of word

BIT12 or 12

Create alias to bit 12 of word

BIT13 or 13

Create alias to bit 13 of word

BIT14 or 14

Create alias to bit 14 of word

BIT15 or 15

Create alias to bit 15 of word


Create alias to low byte of word


Create alias to high byte of word

4.5. Arrays

Variable arrays can be created in a similar manner to variables.

Label VAR Size[Number of elements]

Label is any identifier, excluding keywords, as described above. Size is BIT, BYTE or WORD. Number of elements is how many array locations is desired. Some examples of creating arrays are:

sharks var byte[10]
fish var bit[8]

The first array location is element 0. In the fish array defined above, the elements are numbered fish[0] to fish[7] yielding 8 elements in total.

Because of the way arrays are allocated in memory, there are size limits for each type:


Maximum Number of elements







* Processor dependent. See the section on memory allocation for more information.

Arrays must fit entirely within one RAM bank on most PICmicros. They may not span RAM banks on 14-bit or 17Cxxx devices. (Arrays may span banks on 18Cxxx devices. Byte- and word-sized arrays are only limited in length by the amount of memory.) The compiler will assure that arrays will fit in memory before successfully compiling.

4.6. Constants

Named constants may be created in a similar manner to variables. It can be more convenient to use a constant name instead of a constant number. If the number needs to be changed, it may be changed in only one place in the program; where the constant is defined. Variable data cannot be stored in a constant.

Label CON Constant expression

Some examples of constants are:

mice con 3
traps con mice * 1000

4.7. Symbols

SYMBOL provides yet another method for aliasing variables and constants. It is included for BS1 compatibility. SYMBOL cannot be used to create a variable. Use VAR to create a variable.

	SYMBOL lion = cat	' cat was previously created using VAR
	SYMBOL mouse = 1	' Same as mouse con 1

4.8. Numeric Constants

PBP allows numeric constants to be defined in the three bases: decimal, binary and hexadecimal. Binary values are defined using the prefix '%' and hexadecimal values using the prefix '$'. Decimal values are the default and require no prefix.

	100	' Decimal value 100
	%100	' Binary value for decimal 4
	$100	' Hexadecimal value for decimal 256

For ease of programming, single characters are converted to their ASCII equivalents. Character constants must be quoted using double quotes and must contain only one character (otherwise, they are string constants).

	"A"	' ASCII value for decimal 65
	"d"	' ASCII value for decimal 100

4.9. String Constants

PBP doesn't provide string handling capabilities, but strings can be used with some commands. A string contains one or more characters and is delimited by double quotes. No escape sequences are supported for non-ASCII characters (although most PBP commands have this handling built-in).

	Lcdout "Hello"	' Output String (Short for "H","e","l","l","o")

Strings are usually treated as a list of individual character values.

4.10. Ports and Other Registers

All of the PICmicro registers, including the ports, can be accessed just like any other byte-sized variable in PICBASIC PRO™. This means that they can be read from, written to or used in equations directly:

	PORTA = %01010101	' Write value to PORTA
	anyvar = PORTB & $0f	' Isolate lower 4 bits of PORTB and 
				place result in anyvar

4.11. Pins

Pins may be accessed in a number of different ways. The best way to specify a pin for an operation is to simply use its PORT name and bit number:

	PORTB.1 = 1	' Set PORTB, bit 1 to a 1

To make it easier to remember what a pin is used for, it should be assigned a name using the VAR command. In this manner, the name may then be used in any operation:

led	var	PORTA.0	' Rename PORTA.0 as led
	High led		' Set led (PORTA.0) high

For compatibility with the BASIC Stamp, pins used in PICBASIC PRO™ Compiler commands may also be referred to by number, 0 - 15. These pins are physically mapped onto different PICmicro hardware ports dependent on how many pins the microcontroller has.

No. PICmicro Pins

0 - 7

8 - 15







28-pin (except 14C000)



28-pin (14C000)






*GPIO and PORTA do not have 8 I/O pins.

If a port does not have 8 pins, such as PORTA, only the pin numbers that exist may be used, i.e. 8 - 12. Using pin numbers 13 - 15 will have no discernable effect.

This pin number, 0 - 15, has nothing to do with the physical pin number of a PICmicro. Depending on the particular PICmicro, pin number 0 could be physical pin 6, 21 or 33, but in each case it maps to PORTB.0 (or GPIO.0 for 8-pin devices, or PORTC.0 for a PIC14C000) .

Pins may be referenced by number (0 - 15), name (e.g. Pin0, if one of the bsdefs.bas files are included or you have defined them yourself), or full bit name (e.g. PORTA.1). Any pin or bit of the microcontroller can be accessed using the latter method.

The pin names (i.e. Pin0) are not automatically included in your program. In most cases, you would define pin names as you see fit using the VAR command:

led var PORTB.3

However, two definition files have been provided to enhance BASIC Stamp compatibility. The file Abs1defs.bas@ or Abs2defs.bas@ may be included in the PICBASIC PRO™ program to provide pin and bit names that match the BASIC Stamp names.

Include "bs1defs.bas"


Include "bs2defs.bas"

BS1DEFS.BAS defines Pins, B0-B13, W0-W6 and most of the other BS1 pin and variable names.

BS2DEFS.BAS defines Ins, Outs, B0-B25, W0-W12 and most of the other BS2 pin and variable names.

When a PICmicro powers-up, all of the pins are set to input. To use a pin as an output, the pin or port must be set to an output or a command must be used that automatically sets a pin to an output.

To set a pin or port to an output (or input), set its TRIS register. Setting a TRIS bit to 0 makes its pin an output. Setting a TRIS bit to 1 makes its pin an input. For example:

	TRISA = %00000000		' Or TRISA = 0

sets all the PORTA pins to outputs.

	TRISB = %11111111		' Or TRISB = 255

sets all the PORTB pins to inputs.

	TRISB = %11111111		' Or TRISB = 255

Sets all the even pins on PORTC to outputs, and the odd pins to inputs. Individual bit directions may be set in the same manner.

TRISA.0 = 0

sets PORTA, pin 0 to an output. All of the other pin directions on PORTA are unchanged.

The BASIC Stamp variable names Dirs, Dirh, Dirl and Dir0-Dir15 are not defined and should not be used with the PICBASIC PRO™ Compiler. TRIS should be used instead, but has the opposite state of Dirs.

This does not work in PICBASIC PRO™:

	Dir0 = 1	' Doesn’t set pin PORTB.0 to output

Do this instead:

	TRISB.0 = 0	' Set pin PORTB.0 to output

or simply use a command that automatically sets the pin direction.


A PBP comment starts with either the REM keyword, the single quote ('), or the semi-colon (;). All following characters on this line are ignored.

Unlike many BASICs, REM is a unique keyword and not an abbreviation for REMark. Thus, variables names may begin with REM (although REM itself is not valid).

4.13. Multi-statement Lines

In order to allow more compact programs and logical grouping of related commands, PBP supports the use of the colon (:) to separate statements placed on the same line. Thus, the following two examples are equivalent:

	W2 = W0
	W0 = W1
	W1 = W2

is the same as:

	W2 = W0 : W0 = W1 : W1 = W2

This does not, however, change the size of the generated code.

4.14. Line-extension Character

The maximum number of characters that may appear on one PBP line is 256. Longer statements may be extended to the next line using the line-extension character (_) at the end of each line to be continued.

	Branch B0,[label0,label1,label2,_


Other BASIC source files may be added to a PBP program by using INCLUDE. You may have standardized subroutines, definitions or other files that you wish to keep separate. The Stamp and serial mode definition files are examples of this. These files may be included in programs where they are necessary, but kept out of programs where they are not needed.

The included file=s source code lines are inserted into the program exactly where the INCLUDE is placed.

INCLUDE "modedefs.bas"

4.16. DEFINE

Some elements, like the clock oscillator frequency and the LCD pin locations, are predefined in PBP. DEFINE allows a PBP program to change these definitions, if desired.

DEFINE may be used to change the predefined oscillator value, the DEBUG pins and baud rate and the LCD pin locations, among other things. 

These definitions must be in all upper case. If not, the compiler may not recognize them. No error message will be produced for DEFINEs the compiler does not recognize.

See the appropriate sections of the manual for specific information on these definitions. A complete list of DEFINEs is in Appendix B.

	DEFINE OSC 4			'Oscillator speed in
					 MHz: 3(3.58) 4 8 10
					 12 16 20 25 32 33 40

4.17. Math Operators

Unlike the BASIC Stamp, the PICBASIC PRO™ Compiler performs all math operations in full hierarchal order. This means that there is precedence to the operators. Multiplies and divides are performed before adds and subtracts, for example. To ensure the operations are carried out in the order you would like, use parenthesis to group the operations:

A = (B + C) * (D - E)

All math operations are unsigned and performed with 16-bit precision.

Math Operators









Top 16 Bits of Multiplication


Middle 16 Bits of Multiplication




Remainder (Modulus)


Shift Left


Shift Right


Absolute Value*




2n Decode



DIV 32

31-bit x 15-bit Divide








Reverse Bits




Square Root


Bitwise AND


Bitwise OR


Bitwise Exclusive OR


Bitwise NOT


Bitwise NOT AND


Bitwise NOT OR


Bitwise NOT Exclusive OR

*Implementation differs from BASIC Stamp.

4.17.1. Multiplication

PBP performs 16x16 multiplication. The '*' operator returns the lower 16 bits of the 32-bit result. This is the typical multiplication found in most programming languages. The '**' operator returns the upper 16 bits of the 32-bit result. These two operators can be used in conjunction to perform 16x16 multiplication that produces 32-bit results.

	W1 = W0 * 1000	' Multiply value in W0 by 1000 and place the result in W1
	W2 = W0 ** 1000	' Multiply W0 by 1000 and place the high order 16 bits (which may be 0) in W2

The >*/= operator returns the middle 16 bits of the 32-bit result.

	W3 = W1 */ W0	' Multiply W1 by W0 and place the middle 16 bits in W3

4.17.2. Division

PBP performs 16x16 division. The '/' operator returns the 16-bit result. The '//' operator returns the remainder. This is sometimes referred to as the modulus of the number.

	W1 = W0 / 1000	' Divide value in W0 by 1000 and place the result in W1
	W2 = W0 // 1000	' Divide value in W0 by 1000 and place the remainder in W2

4.17.3. Shift

The '<<' and '>>' operators shift a value left or right, respectively, 0 to 15 times. The newly shifted-in bits are set to 0.

	B0 = B0 << 3	' Shifts B0 left 3 places (same as multiply by 8)
	W1 = W0 >> 1	' Shifts W0 right 1 position and places result in W1 (same as divide by 2)

4.17.4. ABS

ABS returns the absolute value of a number. If a byte is greater than 127 (high bit set), ABS will return 256 - value. If a word is greater than 32767 (high bit set), ABS will return 65536 - value.

	B1 = ABS B0

4.17.5. COS

COS returns the 8-bit cosine of a value. The result is in two=s complement form (i.e. -127 to 127). It uses a quarter-wave lookup table to find the result. Cosine starts with a value in binary radians, 0 to 255, as opposed to the usual 0 to 359 degrees.

	B1 = COS B0

4.17.6. DCD

DCD returns the decoded value of a bit number. It changes a bit number (0 - 15) into a binary number with only that bit set to 1. All other bits are set to 0.

	B0 = DCD 2		' Sets B0 to %00000100

4.17.7. DIG

DIG returns the value of a decimal digit. Simply tell it the digit number (0 - 4 with 0 being the rightmost digit) you would like the value of, and voila.

	B0 = 123		' Set B0 to 123
	B1 = B0 DIG 1	' Sets B1 to 2 (digit 1 of 123)
4.17.8. DIV32 

PBPs multiply (*) function operates as a 16-bit x 16-bit multiply yielding a 32-bit result. However, since the compiler only supports a maximum variable size of 16 bits, access to the result had to happen in 2 steps: c = b * a returns the lower 16 bits of the multiply while d = b ** a returns the upper 16 bits. There was no way to access the 32-bit result as a unit.

In many cases it is desirable to be able to divide the entire 32-bit result of the multiply by a 16-bit number for averaging or scaling. A new function has been added for this purpose: DIV32. DIV32 is actually limited to dividing a 31-bit unsigned integer (max 2147483647) by a 15-bit unsigned integer (max 32767). This should suffice in most circumstances.

As the compiler only allows a maximum variable size of 16 bits, DIV32 relies that a multiply was just performed and that the internal compiler variables still contain the 32-bit result of the multiply. No other operation may occur between the multiply and the DIV32 or the internal variables may be altered, destroying the 32-bit multiplication result.

This means, among other things, that ON INTERRUPT must be DISABLEd from before the multiply until after the DIV32. If ON INTERRUPT is not used, there is no need to add DISABLE to the program. Interrupts in assembler should have no effect on the internal variables so they may be used without regard to DIV32.

The following code fragment shows the operation of DIV32:

a 	Var 	Word
b 	Var 	Word
c 	Var 	Word
dummy 	Var 	Word

	b = 500
	c = 1000

	Disable 	' Necessary if On Interrupt used

	dummy = b * c 	' Could also use ** or */
	a = DIV32 100

	Enable 		' Necessary if On Interrupt used

This program assigns b the value 500 and c the value 1000. When multiplied together, the result would be 500000. This number exceeds the 16-bit word size of a variable (65535). So the dummy variable contains only the lower 16 bits of the result. In any case, it is not used by the DIV32 function. DIV32 uses variables internal to the compiler as the operands.

In this example, DIV32 divides the 32-bit result of the multiplication b * c by 100 and stores the result of this division, 5000, in the word-sized variable a.

4.17.9. MAX and MIN

MAX and MIN returns the maximum and minimum, respectively, of two numbers. It is usually used to limit numbers to a value.

	B1 = B0 MAX 100	' Set B1 to the larger of B0 and 100 (B1 will be between 100 & 255)
	B1 = B0 MIN 100	' Set B1 to the smaller of B0 and 100 (B1 can’t be bigger than 100)

4.17.10. NCD

NCD returns the priority encoded bit number (1 - 16) of a value. It is used to find the highest bit set in a value. It returns 0 if no bit is set.

	B0 = NCD %01001000	' Sets B0 to 7

4.17.11. REV

REV reverses the order of the lowest bits in a value. The number of bits to be reversed is from 1 to 16.

	B0 = %10101100 REV 4	' Sets B0 to %10100011

4.17.12. SIN

SIN returns the 8-bit sine of a value. The result is in two=s complement form (i.e. -127 to 127). It uses a quarter-wave lookup table to find the result. Sine starts with a value in binary radians, 0 to 255, as opposed to the usual 0 to 359 degrees.

	B1 = SIN B0

4.17.13. SQR

SQR returns the square root of a value. Since PICBASIC PRO™ only works with integers, the result will always be an 8-bit integer no larger than the actual result.

	B0 = SQR W1	' Sets B0 to square root of W1

4.17.14. Bitwise Operators

Bitwise operators act on each bit of a value in boolean fashion. They can be used to isolate bits or add bits into a value.

	B0 = B0 & %00000001	' Isolate bit 0 of B0
	B0 = B0 | %00000001	' Set bit 0 of B0
	B0 = B0 ^ %00000001	' Reverse state of bit 0 of B0

4.18. Comparison Operators

Comparison operators are used in IF..THEN statements to compare one expression with another. These comparisons are unsigned. They cannot be used to check if a number is less than 0.

Comparison Operator


= or ==


<> or !=

Not Equal


Less Than


Greater Than


Less Than or Equal


Greater Than or Equal

If i > 10 Then loop

4.19. Logical Operators

Logical operators differ from bitwise operations. They yield a true/false result from their operation. Values of 0 are treated as false. Any other value is treated as true. They are mostly used in conjunction with the comparison operators in an IF..THEN statement. The operators supported are:

Logical Operator


AND or &&

Logical AND

OR or ||

Logical OR

XOR or ^^

Logical Exclusive OR


Logical NAND


Logical NOR


Logical NXOR

If (A == big) AND (B > mean) Then run

Be sure to use parenthesis to tell PBP the exact order you want the operations to be performed.