Assembly Language Example

This project demonstrates how to build projects with only assembly language source files. It uses PORT D to turn on selected LEDs on the PIC32 Starter Kit. You may change the definition of LEDS in the source code to select which LEDs will be on. It should be a number between 1 and 7 to light at least one LED.

The PIC32 Gnu gcc compiler will use the 'C' pre-processor if the assembly language file has an extension of .S (uppercase). If the extension is .s (lowercase), the pre-processor is not invoked. The pre-processor handles statements such as #include, #define, and enables conditional compilation.

The global symbol main must be defined and must correspond to a function. The standard C start-up code will call main, and after main returns will place the processor in an endless loop. This means that the loop in the example program is not really necessary. The same objective could be met by returning from the main program.

The example provides several functions for PIO output pins, similar to the macros provided by the peripherals library.

Note that the MIPS assembler uses $ to denote registers: $a0, $v0, and $zero, for example.

This code was modified from a version "ports_control_assembly_example" found in a collection of code examples on microchip.com/pic32 (look for link to code examples). The example shows us how to incorporate standard MIPS assembly language in the PIC32 development environment.

Assembly Source

Download: assembly.zip

/*********************************************************************
 *
 *                  Example Assembly Project
 *
 *********************************************************************
 * FileName:        ports_control.S
 *
 * Processor:       PIC32MX
 * 
 * Assembler/Compiler/Linker:  MPLAB C32
 *
 *********************************************************************
 *
 * Description:
 * This project demonstrates how to build projects with only
 * assembly language source files.
 * This example uses "S" extension so that the 'C' pre-processor
 * can be used.
 *
 * This example provides simple assembly application. It uses
 * standard C Startup code provided by the C32 compiler.
 *
 *  This code was modified from a version
 *  "ports_control_assembly_example" found in a collection of code
 *  examples on microchip.com.
 *
 ********************************************************************/
#include <p32xxxx.h>

#define LEDS 0x5  

    /* define all global symbols here */
    .global main

    /* define which section (for example "text")
     * does this portion of code resides in. Typically,
     * all your code will reside in .text section as
     * shown below.
     */
    .text

    /* This is important for an assembly programmer. This
     * directive tells the assembler that don't optimize
     * the order of the instructions as well as don't insert
     * 'nop' instructions after jumps and branches.
    */
    .set noreorder

/*********************************************************************
 * main()
 * This is where the PIC32 start-up code will jump to after initial
 * set-up.
 ********************************************************************/

.ent main /* directive that marks symbol 'main' as function in ELF
           * output
           */

main:
    ori     $a0, $zero, LEDS
    jal     mPORTDSetDigitalOut
    nop

    /* Call function to set relevant pins in port D.
     * The 'jal' instruction places the return address in $ra.
     */
    ori        $a0, $zero, LEDS
    jal        mPORTDSetBits
    nop

    /* endless loop */
endless:
    j        endless
    nop

.end main /* directive that marks end of 'main' function and registers
           * size in ELF output
           */

/*********************************************************************
 * mPORTDClearBits(int bits)
 * This function clears the specified bites in IOPORT D.
 *
 * pre-condition: $ra contains return address
 * Input: Bit mask in $a0
 * Output: none
 * Side effect: clears bits in IOPORT D
 ********************************************************************/
.ent mPORTDClearBits 
mPORTDClearBits:
    /* function prologue - save registers used in this function 
     * on stack and adjust stack-pointer
     */
    addiu    $sp, $sp, -4
    sw        $s0, 0($sp)

    la        $s0, LATDCLR
    sw        $a0, 0($s0)        /* clear specified bits */
    
    /* function epilogue - restore registers used in this function
     * from stack and adjust stack-pointer
     */
    lw        $s0, 0($sp)
    addiu    $sp, $sp, 4

    /* return to caller */
    jr        $ra
    nop
.end mPORTDClearBits

/*********************************************************************
 * mPORTDSetBits(int bits)
 * This function sets the specified bites in IOPORT D.
 *
 * pre-condition: $ra contains return address
 * Input: Bit mask in $a0
 * Output: none
 * Side effect: sets bits in IOPORT D
 ********************************************************************/
.ent mPORTDSetBits 
mPORTDSetBits:
    /* function prologue - save registers used in this function 
     * on stack and adjust stack-pointer
     */
    addiu    $sp, $sp, -4
    sw        $s0, 0($sp)

    la        $s0, LATDSET
    sw        $a0, 0($s0)        /* Set specified bits */
    
    /* function epilogue - restore registers used in this function
     * from stack and adjust stack-pointer
     */
    lw        $s0, 0($sp)
    addiu    $sp, $sp, 4

    /* return to caller */
    jr        $ra
    nop
.end mPORTDSetBits

/*********************************************************************
 * mPORTDClearBits(int bits)
 * This function clears the specified bites in IOPORT D.
 *
 * pre-condition: $ra contains return address
 * Input: Bit mask in $a0
 * Output: none
 * Side effect: clears bits in IOPORT D
 ********************************************************************/
.ent mPORTDSetDigitalOut 
mPORTDSetDigitalOut:
    /* function prologue - save registers used in this function 
     * on stack and adjust stack-pointer
     */
    addiu    $sp, $sp, -4
    sw        $s0, 0($sp)

    la        $s0, TRISDCLR
    sw        $a0, 0($s0)        /* clear specified bits (for output) */
    
    /* function epilogue - restore registers used in this function
     * from stack and adjust stack-pointer
     */
    lw        $s0, 0($sp)
    addiu    $sp, $sp, 4

    /* return to caller */
    jr        $ra
    nop
.end mPORTDSetDigitalOut


Maintained by John Loomis, last updated 18 July 2008