Developing Software in Assembly Language
6812 Assembly Language Examples
By Jonathan W. Valvano

     This article, which discusses assembly language programming, accompanies the book Embedded Microcomputer Systems: Real Time Interfacing published by Brooks-Cole 1999. This document has four overall parts
     Overview
     Syntax (fields, pseudo ops)
     Local variables
     Examples

Stack Usage and Interrupts on the 6812
      parameter passing in C
      stack initialization and overflow check
      setting interrupt vectors
     

Other Examples
      Arithmetic Examples on the 6812
      Shift Examples on the 6812
      FIFO Queue Examples on the 6812
      Interpreters on the 6812
      Control Structure Examples on the 6812 

 

--------------------------------------------------------------------------------------
How parameters are passed in C
In order to understand both the machine architecture and the C compiler, we can look at the assembly code generated. This example shows a simple C program with three global variables
x1,x2,x3, two local variables both called y and three function parameters z1,z2,z3.

int x1;
static int x2;
const int x3=1000;
int add3(int z1, int z2, int z3){ int y;
    y=z1+z2+z3;
    return(y);}
void main(void){ int y;
    x1=1000;
    x2=1000;
    y=add3(x1,x2,x3);

The compiler we will study is the ImageCraft ICC12 version 5.1 for the Motorola 6812. The linker/loader allocates 3 segmented memory areas: code pointed to by the PC; global accessed with absolute addressing; and locals pointed to by the stack pointer SP. The global symbols, _x1 _x2_x3, will be assigned or bound by the linker/loader. The three instructions pshx tfr s,x and leas -8,sp allocates the local variable, and establishes a stack frame pointer, X. This compiler passes the first input parameter (z1) into the subroutine by placing it in register D. The remaining parameters (z2, z3 in this example) are pushed on the stack by the main program before the subroutine is called. The first operation the subroutine performs is to push the remaining parameter on the stack (pshd) so that all three parameters, z1 z2 z3, are on the stack. Also notice that the main program allocates space for the parameters it needs to push when it calls add3 at the beginning of main.

--------------------------------------------------------------------------------------
Stack initialization and overflow check on the 6812

InitialSP     equ  $0C00
StackSize     equ  100
StackBoundary equ  InitialSP-StackSize

;********* this is the regular stack initialization
main   lds   #InitialSP

;********* add this code to check for overflow*******
       cps   #StackBoundary
       blo   Overflow   
; goes to Overflow if more than 100 bytes pushed

 

The following figure shows the stack before and after the bsr instruction is executed on the 6812.

The rts instruction will return to the program that called the subroutine.

 

The following figure shows the stack before and after the call instruction is executed on the 6812.

The rtc instruction will return to the program that called the subroutine.

 

--------------------------------------------------------------------------------------
Installing interrupt handlers

      This first example places in ROM. The interrupt vectors can not be changed at run time.
      org  $E000    ; ROM
main   lds  #$00FF   ; initialize stack
       bsr  ritual   ; initialization of hardware, data structures
loop   
;* main program ******** foreground thread ********
      bra   loop   ;repeat forever

;***called by software using SWI instruction ********
SWIhan
      ;SWI handler
      rti
;***called periodically by clock hardware ********
RTIhan
      ;RTI handler
      rti
;***called by external IRQ hardware or KeyWakeupD ********
IRQhan
      ;IRQ handler
      rti
;***called by external XIRQ hardware********
XIRQhan
      ;XIRQ handler
      rti
; Assume interrupt vectors are in protected ROM
; the ROM vectors can't be changed dynamically
      org   $FFF0
      fdb   RTIhan   ; $FFF0 is RTI vector
      fdb   IRQhan   ; $FFF2 is IRQ vector (key wakeup D)
      fdb   XIRQhan   ; $FFF4 is XIRQ vector
      fdb   SWIhan   ; $FFF6 is SWI vector
      org   $FFFE
      fdb   main   ; reset vector

      This second example places indirect jmp instructions in RAM so that the interrupt vectors can be changed at run time.
   org   $0800   ; RAM locations
; $0800 to $0802 contain a jmp to the RTI interrupt handler
      rmb   3
; $0803 to $0805 contain a jmp to the IRQ interrupt handler
      rmb   3
; $0806 to $0808 contain a jmp to the XIRQ interrupt handler
      rmb   3
; $0809 to $080B contain a jmp to the SWI interrupt handler
      rmb   3
      org   $F000   ; EEPROM
; Set the SWI interrupt vector dynamically
; input RegX points to SWIhandler
SetSWI movb #$06,$0809 ; install jmp opcode (extended)
       stx  $080A      ; operand field of the jmp instruction
       rts
; Set the XIRQ interrupt vector dynamically
; input RegX points to XIRQhandler
SetXIRQ movb #$06,$0806 ; install jmp opcode (extended)
        stx  $0807      ; operand field of the jmp instruction
       rts
; Set the IRQ interrupt vector dynamically
; input RegX points to IRQhandler
SetIRQ movb #$06,$0803 ; install jmp opcode (extended)
       stx  $0804      ; operand field of the jmp instruction
       rts
; Set the RTI interrupt vector dynamically
; input RegX points to RTIhandler
SetRTI movb #$06,$0800 ; install jmp opcode (extended)
       stx  $0801      ; operand field of the jmp instruction
       rts
main   lds  #$0C00     ; initialize stack
       ldx  #SWIhand
       bsr  SetSWI     ; dynamically install vector
       bsr  ritual
loop   bsr  func1
       bsr  func2
       bra   loop      ;repeat forever
SWIhan
      ;... handler
      rti
; Assume interrupt vectors are in protected EEPROM
; the EEPROM vectors can't be changed dynamically
      org   $FFF0
      fdb   $0800   ; $FFF0 is RTI vector
      fdb   $0803   ; $FFF2 is IRQ vector (key wakeup D)
      fdb   $0806   ; $FFF4 is XIRQ vector
      fdb   $0809   ; $FFF6 is SWI vector
      org   $FFFE
      fdb   main    ; reset vector

For more information on interrupts, see Chapter 4 in the book,
Embedded Microcomputer Systems: Real Time Interfacing by Jonathan W. Valvano, Brooks/Cole Publishing Co., December 1999.

The following figure shows the stack before and after the swi instruction is executed. A hardware interrupt will also push registers on the stack, and set the I bit.

The rti instruction is used to return from a hardware or a software interrupt.

 

This document has four overall parts
     Overview
     Syntax (fields, pseudo ops)
     Local variables
     Examples