Saturday, August 14, 2021

0000 0000 0110 1110

16-bit assembly multiplication

When 8-bit microcontrollers have 11-bit PWM output, some 16-bit arithmetic may be required. The ATTiny13 and the PFS-154 do not have hardware multiplication (MUL or MULS) and so these operations need to be done in software.

Although there are a few different algorithms (both manual and automated) to multiply two numbers together, I have chosen to do the typical "shift and add" method that we are all taught in primary school.

In assembly, and for 16 bit multiplication, this means a code section on shifting the data to the right (multiplication by 10 for decimal, and 2 for binary):

  rol r21            ; multiply by 2
  rol r20            ; for next iteration

There is also a code section for adding two sixteen bit numbers:

  add r23, r21       ; no so add lower
  adc r22, r20       ; and upper bytes

The complete code is below, which runs great on Gerd's excellent AVR-SIM

.nolist
.include "tn13adef.inc"
.list

.dseg
.org SRAM_START

.cseg
.org 000000

rjmp Main    ; Reset vector

Main:
  ; initialise stack
  ldi r16,Low(RAMEND)
	out SPL,r16  ; Init LSB stack pointer
  .equ mult1 = 27   ; 0x1B
  .equ mult2 = 58   ; 0x3A

Loop:
  ; clear working registers
  clr r16
  clr r17
  clr r18
  clr r20
  clr r21
  clr r22
  clr r23

  ; load numbers and counter
  ldi r17, mult1
  ldi r21, mult2
  ldi r18, 8

testbits:            ; test each bit
  ror r17
  brcc zero_partial  ; is it a zero?
  add r23, r21       ; no so add lower
  adc r22, r20       ; and upper bytes

zero_partial:
  rol r21            ; multiply by 2
  rol r20            ; for next iteration

  subi r18, 1        ; decrement counter
  brne testbits      ; any more left?
  rjmp loop          ; start again

Next time in this series I'll do a program that makes 16-bit random numbers, and then maybe we'll start looking to program the PFS-154 in assembly - gulp!




No comments:

Post a Comment