Developing Software in Assembly Language
6812 Assembly Language Arithmetic 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

Arithmetic Examples on the 6812
      32-bit addition
      unsigned 8-bit addition with ceiling
      signed 8-bit addition with ceiling/floor
      unsigned 16-bit addition with ceiling
      signed 16-bit addition with ceiling/floor
      32-bit subtraction
      unsigned 8-bit subtraction with ceiling
      signed 8-bit subtraction with ceiling/floor
      unsigned 16-bit subtraction with ceiling
      signed 16-bit subtraction with ceiling/floor
      8-bit unsigned multiply by 10
      16-bit unsigned multiply by 10
      digital filter
      8-bit table lookup and interpolation
      16-bit table lookup and interpolation
      8-bit Fuzzy Logic example
      16-bit Fuzzy Logic example

Other Examples
      Stack Usage and Interrupts on the 6812
      Interpreters on the 6812
      Shift Examples on the 6812
      FIFO Queue Examples on the 6812
      Control Structure Examples on the 6812 

--------------------------------------------------------------------------------------
32-bit addition P=N+M

      org   $0800
N   .blkb   4   ; first 32-bit number
M   .blkb   4   ; second 32-bit number
P   .blkb   4   ; third 32-bit number
      org   $F000
; 32 bit addition P=N+M
; Input:   Two 32-bit numbers N,M
; Output:   One 32 bit sum P
; Error:   C/V set for unsigned/signed overflow
add32 ldaa   N+3   ; start with least significant byte
      adda   M+3
      staa   P+3
      ldaa   N+2   ; next byte
      adca   M+2   ; carry from previous addition
      staa   P+2
      ldaa   N+1   ; next byte
      adca   M+1   ; carry from previous addition
      staa   P+1
      ldaa   N     ; last byte
      adca   M     ; carry from previous addition
      staa   P
; C bit set if unsigned overflow
; V bit set if signed overflow
; Z bit set if result is zero
      rts

--------------------------------------------------------------------------------------
32-bit subtraction P=N-M on the 6812

N   ds   4   ; first 32-bit number
M   ds   4   ; second 32-bit number
P   ds   4   ; third 32-bit number
sub32 ldaa   N+3   ; start with least significant byte
      suba   M+3
      staa   P+3
      ldaa   N+2   ; next byte
      sbca   M+2   ; carry from previous addition
      staa   P+2
      ldaa   N+1   ; next byte
      sbca   M+1   ; carry from previous addition
      staa   P+1
      ldaa   N     ; last byte
      sbca   M     ; carry from previous addition
      staa   P
; C bit set if unsigned overflow
; V bit set if signed overflow
; Z bit set if result is zero
      rts

--------------------------------------------------------------------------------------
8-bit unsigned addition with overflow checking P=N+M on the 6812

N   ds   1   ; first 8-bit number
M   ds   1   ; second 8-bit number
P   ds   1   ; third 8-bit number
add8  ldaa   N   ; first number
      adda   M   ; add second number
; C bit set if unsigned overflow
      bcc    SetP   ; skip if no overflow
      ldaa   #255   ; set at maximum (ceiling)
SetP  staa   P
      rts

--------------------------------------------------------------------------------------
8-bit signed addition with overflow checking P=N+M on the 6812

N   ds   1   ; first 8-bit number
M   ds   1   ; second 8-bit number
P   ds   1   ; third 8-bit number
add8s ldaa   N   ; first number
      adda   M   ; add second number
; V bit set if signed overflow
      bvc    SetP    ; skip if no overflow
      bpl    floor   ; is positive, should be -128
ceil  ldaa   #127    ; set at maximum (ceiling)
      bra    SetP
floor ldaa   #-128   ; set to minumum (floor)
SetP  staa   P
      rts

--------------------------------------------------------------------------------------
16-bit unsigned addition with overflow checking P=N+M on the 6812

N   ds   2   ; first 16-bit number
M   ds   2   ; second 16-bit number
P   ds   2   ; third 16-bit number
add16 ldd    N   ; first number
      addd   M   ; add second number
; C bit set if unsigned overflow
      bcc    SetP   ; skip if no overflow
      ldd    #65535 ; set at maximum (ceiling)
SetP  std    P
      rts

--------------------------------------------------------------------------------------
16-bit signed addition with overflow checking P=N+M on the 6812

N   ds   2   ; first 16-bit number
M   ds   2   ; second 16-bit number
P   ds   2   ; third 16-bit number
add16s ldd   N   ; first number
       addd  M   ; add second number
; V bit set if signed overflow
       bvc   SetP    ; skip if no overflow
       bpl   floor   ; is positive, should be -32768
ceil   ldd   #32767  ; set at maximum (ceiling)
       bra   SetP
floor  ldd   #-32768 ; set to minumum (floor)
SetP   std   P
       rts

--------------------------------------------------------------------------------------
8-bit unsigned subtraction with overflow checking P=N-M on the 6812

N   ds   1   ; first 8-bit number
M   ds   1   ; second 8-bit number
P   ds   1   ; third 8-bit number
sub8  ldaa   N   ; first number
      suba   M   ; subtract second number
; C bit set if unsigned overflow
      bcc   SetP   ; skip if no overflow
      ldaa   #0    ; set at minimum (floor)
SetP  staa   P
      rts

--------------------------------------------------------------------------------------
8-bit signed subtraction with overflow checking P=N-M on the 6812

N   ds   1   ; first 8-bit number
M   ds   1   ; second 8-bit number
P   ds   1   ; third 8-bit number
sub8s ldaa   N   ; first number
      suba   M   ; subtract second number
; V bit set if signed overflow
      bvc   SetP    ; skip if no overflow
      bpl   floor   ; is positive, should be -128
ceil  ldaa  #127    ; set at maximum (ceiling)
      bra   SetP
floor ldaa  #-128   ; set to minumum (floor)
SetP  staa  P
      rts

--------------------------------------------------------------------------------------
16-bit unsigned subtraction with overflow checking P=N-M on the 6812

N   ds   2   ; first 16-bit number
M   ds   2   ; second 16-bit number
P   ds   2   ; third 16-bit number
sub16  ldd  N   ; first number
      subd  M   ; subtract second number
; C bit set if unsigned overflow
      bcc   SetP ; skip if no overflow
      ldd   #0   ; set at minimum (floor)
SetP  std   P
      rts

--------------------------------------------------------------------------------------
16-bit signed subtraction with overflow checking P=N-M on the 6812

N   ds   2   ; first 16-bit number
M   ds   2   ; second 16-bit number
P   ds   2   ; third 16-bit number
sub16s ldd   N   ; first number
       subd  M   ; subtract second number
; V bit set if signed overflow
       bvc   SetP   ; skip if no overflow
       bpl   floor  ; is positive, should be -32768
ceil   ldd   #32767 ; set at maximum (ceiling)
       bra   SetP
floor  ldd   #-32768 ; set to minumum (floor)
SetP   std   P
       rts

--------------------------------------------------------------------------------------
High Q high pass digital filter on the 6812

; y(n)=0.9025x(n)-1.805x(n-1)+0.9025x(n-2)+1.8y(n-1)-0.81y(n-2)
; first we can convert this filter to fixed point
; without introducing any error:
; y(n)=(9025x(n)-18050x(n-1)+9025x(n-2)+18000y(n-1)-8100y(n-2))/10000
      org   $0800
XN    ds   2   ; x(n) current 16-bit data point
XN1   ds   2   ; x(n-1) previous data point
XN2   ds   2   ; x(n-2) data point two samples ago
YN1   ds   2   ; y(n-1) previous filter output
YN2   ds   2   ; y(n-2) filter output two samples ago
YN    ds   2   ; y(n) current 16-bit filter output
acc   ds   4   ; temporary 32-bit result
      org   $F000
COEF  dc.w  9025,-18050,9025,18000,-8100
DF    ldx   #XN     ; data
      ldy   #COEF   ; coef
      ldd   #0
      std   acc   ; initially clear temporary result
      std   acc+2
      ldaa  #5    ; number of terms
loop  emacs acc   ;acc=acc+{X}*{Y}
      leax  2,x
      leay  2,y
      dbne  A,loop
      ldy   acc
      ldd   acc+2
;Y:D=9025x(n)-18050x(n-1)+9025x(n-2)+18000y(n-1)-8100y(n-2)
      ldx   #10000
      edivs
      sty   YN
      rts
      
      

--------------------------------------------------------------------------------------
16-bit unsigned multiply by 10 on the 6812

; Input: Reg D is an unsigned 16-bit input
; Output: Reg D = 10*input
; without overflow checking
umul10 lsld       ; multiply by 2
       pshd       ; save 2*D
       lsld       ; 4*D
       lsld       ; 8*D
       addd 2,sp+ ; 8*D+2*D=10*D
       rts

; Input: Reg D is an unsigned 16-bit input
; Output: Reg D = 10*input
; with overflow checking
d2     equ   0       ; 2*D
umul10 leas  -2,sp   ; allocate space for d2
       lsld          ; multiply by 2
       bcs   over    ; bigger than 65535
       std   d2,sp   ; d2=2*D
       lsld          ; 4*D
       bcs   over    ; bigger than 65535
       lsld          ; 8*D
       bcs   over    ; bigger than 65535
       addd  d2,sp   ; 8*D+2*D=10*D
       bcc   done
over   ldd   #65535
done   leas  2,sp    ; deallocate
       rts

--------------------------------------------------------------------------------------
8-bit unsigned multiply by 10 on the 6812

; Input: Reg A is an unsigned 8-bit input
; Output: Reg A = 10*input
; without overflow checking
mul10 lsla         ; multiply by 2
      psha         ; save 2*A
      lsla         ; 4*A
      lsla         ; 8*A
      adda 1,sp+   ; 8*A+2*A=10*A
      rts

; Input: Reg A is an unsigned 8-bit input
; Output: Reg A = 10*input
; with overflow checking
d2    equ   0       ; 2*A
mul10 leas  -1,sp   ; allocate space for d2
      lsla          ; multiply by 2
      bcs   over    ; bigger than 255
      staa  d2,sp   ; d2=2*A
      lsla          ; 4*A
      bcs   over    ; bigger than 255
      lsla          ; 8*A
      bcs   over    ; bigger than 255
      adda  d2,sp   ; 8*A+2*A=10*A
      bcc   done
over  ldaa  #255
done  leas  1,sp    ; deallocate
      rts

--------------------------------------------------------------------------------------
8-bit table access on the 6812

      Many applications require the representation of complex waveforms in digital form. A typical application is a calibration curves which describe the input/output behavior of the system. The actual hardware takes the measurand (y= position, pressure, temperature etc.) as input and has the A/D conversion (x= 0 to 255) as output. In this situation, the software algorithm is asked to reverse the process, taking as input (x) the A/D measurement and giving as output (y) is the measurand. One of the most efficient, yet simple, techniques for describing nonlinear equations is to provide a small table of (x,y) points then use linear interpolation between the points. In this way the response is piece-wise linear. This technique only works for any single-valued data set (a unique y for each x). There is a clear tradeoff between accuracy and software efficiency (static and dynamic). E.g., you can add more points to improve accuracy, but it requires more memory and runs slower.

      org   $800
in    ds    1    ; 8-bit input
out   ds    1    ; 8-bit output
      org   $F000
; The table consists of multiple unsigned (x,y)
; which define a piece-wise linear function
; first X entry must be less than or equal to minimum input
; last X entry must be bigger than maximum input
Xtable dc.b 0,10,100,150,255 ; must be monotonic
Ytable dc.b 20,0,200,100,150
Main   lds   #$0C00
       clra
loop   staa  in      ; ranges from 0 to 254
       bsr   Lookup
       staa  out
here   ldaa  in
       inca
       cmpa  #255
       bne   loop
       stop
;**********Lookup*******************
;Inputs: RegA is 0 to 254 Xdata point, xL
; RegA input must be greater than or equal to first Xdata point
; RegA input must be less than last Xdata point
;Output: RegA is 0 to 255 Ydata point
;Registers destroyed: X,Y,B,CCR
Lookup ldx   #Xtable   ; first find x1<=xL<x2
       ldy   #Ytable
lookx1 cmpa  1,x     ; check xL<x2
       blo   found   ; stops when X points to x1
       inx
       iny
       bra   lookx1
found  suba  0,x   ; xL-x1
       clrb        ; D=256*(xL-x1)
       pshd
       ldab   1,x    ; x2
       subb  0,x     ; x2-x1
       clra          ; D=x2-x1
       tfr   D,X     ; X=x2-x1
       puld          ; D=256*(xL-x1)
       idiv          ; X=(256*(xL-x1))/(x2-x1)
       tfr   X,D
; B=(256*(xL-x1))/(x2-x1)
; Y points to y1,y2
      tbl 0,y
; A=Y1+B*(Y2-Y1)
       rts

       org   $FFFE
       fdb   Main

--------------------------------------------------------------------------------------
16-bit table access on the 6812

      Many applications require the representation of complex waveforms in digital form. A typical application is a calibration curves which describe the input/output behavior of the system. The actual hardware takes the measurand (y=position, pressure, temperature etc.) as input and has the A/D conversion (x= 0 to 65535) as output. In this situation, the software algorithm is asked to reverse the process, taking as input (x) the A/D measurement and giving as output (y) is the measurand. One of the most efficient, yet simple, techniques for describing nonlinear equations is to provide a small table of (x,y) points then use linear interpolation between the points. In this way the response is piece-wise linear. This technique only works for any single-valued data set (a unique y for each x). There is a clear tradeoff between accuracy and software efficiency (static and dynamic). E.g., you can add more points to improve accuracy, but it requires more memory and runs slower.

; Examples of 16-bit table access
      org  $800
in    ds   2    ; 16-bit input
out   ds   2    ; 16-bit output
      org   $F000
; The table consists of multiple unsigned (x,y)
; which define a piece-wise linear function
; first X entry must be less than or equal to minimum input
; last X entry must be bigger than maximum input
Xtable dc.w 0,1000,10000,15000,25500 ; must be monotonic
Ytable dc.w 2000,0,20000,10000,15000
Main  lds   #$0C00
      ldd   #0
loop  std   in     ; ranges from 0 to 25400
      bsr   Lookup
      std   out
here  ldd   in
      addd  #100
      cpd   #25500
      bne   loop
      stop
;**********Lookup*******************
;Inputs: RegD is 0 to 65534 Xdata point, xL
; RegD input must be greater than or equal to first Xdata point
; RegD input must be less than last Xdata point
;Output: RegD is 0 to 65535 Ydata point
;Registers destroyed: X,Y,B,CCR
Lookup ldx   #Xtable ; first find x1<=xL<x2
       ldy   #Ytable
lookx1 cpd   2,x     ; check xL<x2
       blo   found   ; stops when X points to x1
       leax  2,x
       leay  2,y
       bra   lookx1
found  subd  0,x   ; xL-x1
       pshd
       ldd   2,x   ; x2
       subd  0,x   ; D=x2-x1
       tfr   D,X   ; X=x2-x1
       puld        ; D=(xL-x1)
       fdiv        ; X=(65536*(xL-x1))/(x2-x1)
       tfr   X,D
       tfr   A,B
; B=(256*(xL-x1))/(x2-x1)
; Y points to y1,y2
       etbl  0,y
; D=Y1+B*(Y2-Y1)
       rts

       org   $FFFE
       fdb   Main

--------------------------------------------------------------------------------------
8-bit Fuzzy logic example on the 6812


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

TCNT      equ   $0084
TSCR      equ   $0086
          org   $800
; *******8-bit fuzzy example*********
; crisp inputs
speed:        ds  1
acceleration: ds  1
fuzvar:       ds  0   ; inputs
inFast:       ds  1   ; speed too fast
inOk:         ds  1   ; speed OK
inSlow:       ds  1   ; speed too slow
inDown:       ds  1   ; speed decreasing
inSame:       ds  1   ; speed constant
inUp:         ds  1   ; speed increasing

fuzout:       ds   0   ; outputs
outAdd:       ds   1   ; add power to system
outZero:      ds   1   ; leave power as is
outSub:       ds   1    ; subtract power from system
Break:        ds   1   ; apply break
; input membership variables relative offsets
fast:         equ  0   ; speed too fast
ok:           equ  1   ; speed OK
slow:         equ  2   ; speed too slow
down:         equ  3   ; speed decreasing
same:         equ  4   ; speed constant
up:           equ  5   ; speed increasing
;output membership variables
add:          equ  6   ; add power to system
zero:         equ  7   ; leave power as is
sub:          equ  8   ; subtract power from system
break:        equ  9   ; apply break
;crisp outputs
dpower:       ds   1
              org  $F000
s_tab:        dc.b  $90,$FF,$04,$00
              dc.b  $40,$D0,$08,$04
              dc.b  $00,$60,$00,$08
a_tab:        dc.b  $90,$FF,$04,$00
              dc.b  $40,$D0,$08,$04
              dc.b  $00,$60,$00,$08
rules:        dc.b  fast,same,$FE,sub,break,$FE
              dc.b  fast,up,$FE,sub,break,$FE
              dc.b  ok,up,$FE,sub,$FE
              dc.b  fast,down,$FE,zero,$FE
              dc.b  ok,same,$FE,zero,$FE
              dc.b  ok,down,$FE,add,$FE
              dc.b  slow,up,$FE,zero,$FE
              dc.b  slow,same,$FE,add,$FE
              dc.b  slow,down,$FE,add,$FE,$FF
addsingleton: dc.b  255,128,0 ; 128 subtracted, +127,0,-128

main:    lds   #$0C00
         movb  #$80,TSCR  ; enable TCNT
         ldaa  #0         ; crisp input speed
         staa  speed
         ldaa  #128
         staa  acceleration
mloop:   ldaa  speed      ; crisp to input membership
         ldx   #s_tab
         ldy   #fuzvar
         mem
         mem
         mem

         ldaa  acceleration
         ldx   #a_tab   ; crisp to input membership
         mem
         mem
         mem

         ldab  #4
cloop:   clr   1,y+      ; input to output membership
         dbne  b,cloop
         ldx   #rules
         ldy   #fuzvar
         ldaa  #$FF
         rev             ; rule evaluation
         ldy   #fuzout
         ldx   #addsingleton
         ldab   #3
         wav
         ediv
         tfr   y,d
         subb  #128
         stab  dpower
change:  ldaa  speed
         adda  #$04
         staa  speed
         bne   mloop
         stop
         lbra  main

         org   $FFFE
         dc.w  main
         end

--------------------------------------------------------------------------------------
16-bit Fuzzy logic example on the 6812


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

TCNT        equ  $0084
TSCR        equ  $0086
            org  $900
;crisp input
position:   ds   1
;fuzzy input membership variables
veryleft:   ds   1
left:       ds   1
center:     ds   1
right:      ds   1
veryright:  ds   1
;fuzzy output membership variables
goleft:     ds   1
goright:    ds   1
morepower:  ds   1
lesspower:  ds   1
;crisp output
lr:         ds   1
power:      ds   1

                org   $F400
memtab2:        dc.b  $00,$40,$00,$04
                dc.b  $20,$80,$04,$04
                dc.b  $40,$C0,$04,$04
                dc.b  $80,$E0,$04,$04
                dc.b  $C0,$FF,$04,$00
rules2:         dc.w  veryleft,$FFFE,goright,morepower,$FFFE
                dc.w  left,$FFFE,goright,$FFFE
                dc.w  center,$FFFE,lesspower,$FFFE
                dc.w  right,$FFFE,goleft,$FFFE
                dc.w  veryright,$FFFE,goleft,morepower,$FFFE,$FFFF
weights:        dc.b  $FF,$C0,$80,$FF,$FF
lrsingleton:    dc.b  0,100
powersingleton: dc.b  0,255

main:    lds   #$0C00
         movb  #$80,TSCR  ; enable TCNT
         ldaa  #0         ; crisp input position
         staa  position
nloop:   ldaa  position
         ldx   #memtab2
         ldy   #veryleft
         mem              ; crisp to input membership
         mem
         mem
         mem
         mem

         ldab  #4
dloop:   clr   1,y+
         dbne  b,dloop
         ldx   #rules2
         ldy   #weights
         sec
         ldaa  #$FF
         revw      ; input to output membership
         ldy   #goleft
         ldx   #lrsingleton
         ldab  #2
         wav
         ediv
         tfr   y,d
         stab  lr
         ldy   #morepower
         ldx   #powersingleton
         ldab  #2
         wav
         ediv
         tfr   y,d
         subb  #128      ; convert to signed
         stab  power
         ldaa  position
         adda  #$10
         staa  position
         bne   nloop
         jmp   main

         org   $FFFE
         dc.w  main
         end

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