8. Assembly Language Programming

Assembly language routines can be a useful adjunct to a PICBASIC PRO™ Compiler program. While in general most tasks can be done completely in PICBASIC PRO™, there are times when it might be necessary to do a particular task faster, or using a smaller amount of code space, or just differently than the compiler does it. At those times it is useful to have the capabilities of an in-line assembler.

It can be beneficial to write most of a program quickly using the PICBASIC PRO™ language and then sprinkle in a few lines of assembly code to increase the functionality. This additional code may be inserted directly into the PBP program or included as another file.

8.1. Two Assemblers - No Waiting

Upon execution, PBP first compiles the program into assembly language and then automatically launches an assembler. This converts the assembler output into the final .HEX file which can be programmed into a microcontroller.

Two different assemblers may be used with PBP: PM, our PICmicro Macro Assembler, and MPASM, Microchip=s assembler. PM is included with the compiler while MPASM must be obtained directly from Microchip via their web site or is included with their PICmicro programmers.

There are benefits and drawbacks to using each assembler. PM is handy because it is included as part of PBP. It is also much faster than MPASM and can assemble much larger programs in DOS. PM includes an 8051-style instruction set that is more intuitive than the Microchip mnemonics. For complete information on the PICmicro Macro Assembler, see the PM.TXT file on disk.

MPASM, on the other hand, has the capability of creating a .COD file. This file contains additional information that can be very useful with simulators and emulators. MPASM is also more compatible with the wide variety of assembly language examples found on the web and in Microchip=s data books.

PBP defaults to using PM. To use MPASM with PBP, simply copy all of the MPASM files into their own subdirectory, perhaps named MPASM. This subdirectory must also be in the DOS PATH.

MPASM may be used with PBP in two ways. If the command line option "-ampasm" is used, MPASM will be launched following compilation to complete the process. MPASM will display its own screen with its progress.

PBP -ampasm filename

Alternatively, the command line option "-amp" will launch MPASM in quiet mode and only display any errors. However, the launcher consumes additional memory that is therefore not available to MPASM.

PBP -amp filename

For maximum memory availability to MPASM, the command line option "-ampasm" should be used or the Windows version of MPASM, "-ampasmwin" should be used.

In any case, MPASM is not included with PBP and must be obtained from Microchip.

8.2. Programming in Assembly Language

PBP programs may contain a single line of assembly language preceded by an Aat@ symbol (@), or one or more lines of assembly code preceded by the ASM keyword and ended by the keyword and ended by the ENDASM keyword. Both keywords appear on their lines alone.

	@	bsf	PORTA,0

		bsf	STATUS,RP0
		bcf	TRISA,0
		bcf	STATUS,RP0

The lines of assembly are copied verbatim into the assembly output file. This allows the PBP program to use all of the facilities of PM, the PICmicro Macro Assembler. This also, however, requires that the programmer have some familiarity with the PBP libraries. PBP=s notational conventions are similar to other commercial compilers and should come as no shock to programmers experienced enough to attempt in-line assembly.

All identifier names defined in a PBP program are similarly defined in assembly, but with the name preceded with an underscore ( _ ). This allows access to user variables, constants, and even labeled locations, in assembly.

Thus, any name defined in assembly starting with an underscore has the possibility of conflicting with a PBP generated symbol. If conflict is avoided, can these underscored assembly values be accessed from PBP? No. Remember, the underscored names generated by PBP are only shadows of the actual information defined in the compiler. Since in-line assembly is copied directly to the output file and not processed by the compiler, the compiler not only lacks any type or value information about assembly symbols, it is completely unaware that they exist. If variables are to be shared between assembly and PBP, you must define the variables in PBP.

Just as underscored symbols have possible conflicts, so do symbols not starting with underscores. The problem is internal library identifiers. Luckily, most library identifiers contain a '?' or make reference to one of the working registers (such as R0). Avoiding such names should be reduce problems. If you should have a name collision, the compiler will report the duplicate definitions as an error.

In assembly language the comment designator changes from the single quote (>) in PICBASIC PRO™ to a semicolon (;).

	' PICBASIC PRO™ comment
	; Assembly language comment

8.3. Placement of In-line Assembly

PBP statements execute in order of appearance in the source. The organization of the code is as follows: Starting at location 0, the reset vector, PBP inserts some startup code followed by a jump to INIT. Next, the called-for library subroutines are stuffed in. At the end of the library is INIT, where any additional initialization is completed. Finally, at the label MAIN, the compiled PICBASIC PRO™ statement code is added.

The first executable line that appears in the PICBASIC PRO™ source is where the program starts execution. That statement literally appears in memory right behind the controller=s startup and library code, right after the MAIN label.

The tendency of programmers is to place their own library functions written using the in-line assembler either before or after their code. In light of the above explanation, this could create some obvious problems. If they appear early in the program, the assembly routines execute prior to any PBP instructions (some programmers will invariably exploit this feature). If they appear at the tail of the program, execution which "falls off the end" of the PBP statements may mysteriously find themselves unintentionally executing assembly routines.

There are a couple of deciding factors as to where might be the best place to insert assembly language subroutines. If the entire program fits into 2K (one code page), place your assembly routines after your PBP code. If you need to terminate your program, explicitly place an END or STOP statement at the end of your code rather than floating off into space.

If the program is longer than 2K, it could make more sense to put the assembly language routines at the beginning of the PBP program. This should ensure them of being in the first code page so that you know where to find them. This is the way assembly language interrupt routines should be handled.

If the routines are placed at the front, you must include a GOTO (or JMP) around the code to the first executable PBP statement. See the section on interrupts for an example of this.

The actual code for the assembly language routines may be included in your program or in a separate file. If a routine is used by only one particular PICBASIC PRO™ program, it would make sense to include the assembler code within the PBP source file. This routine can then be accessed using the CALL command.

If it is used by several different PBP programs, a separate file containing the assembly routines can simply be included at the appropriate place in the PICBASIC PRO™ source:

		Include “myasm.inc”

8.4. Another Assembly Issue

PICmicro MCU registers are banked. PBP keeps track of which register bank it is pointing to at all times. It knows if it is pointing to a TRIS register, for example, it needs to change the bank select bits before it can access a PORT.

It also knows to reset the bank select bits to 0 before making a Call or a Jump. It does this because it can=t know the state of the bank select bits at the new location. So anytime there is a change of locale or a label that can be called or jumped to, the bank select bits are zeroed.

It also resets the bank select bits before each ASM and the @ assembler shortcut. Once again, the assembler routine won=t know the current state of the bits so they are set to a known state. The assembler code must be sure to reset the bank select bits before it exits, if it has altered them.