Embedded Systems
8-bit Microcontroller
16-bit Multiplication
Algorithm Optimization
MCU Performance

Faster 16bit multiplication algorithm for 8-bit MCU

Data Structures & Algorithms practice on Codemia

Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.

Practice algorithms

Introduction

Multiplication in microcontroller units (MCUs) is a fundamental operation that underpins many computational tasks, but it can also be a performance bottleneck, especially in lower-end 8-bit MCUs lacking hardware multipliers. A typical challenge is multiplying 16-bit integers efficiently given the limited resources of these devices. In this article, we explore methods and an algorithm to speed up 16-bit multiplication on 8-bit MCUs using software-based techniques.

Basics of 16-bit Multiplication

On an 8-bit microcontroller, such as those from the AVR or PIC families, 16-bit multiplication must often be conducted in software. This typically involves combining four 8-bit multiplications to achieve a single 16-bit multiplication, due to the limited register width. A basic multiplication of two 16-bit numbers, A and B , could be represented as follows:

• A=AH×256+ALA = A_{H} \times 256 + A_{L} • B=BH×256+BLB = B_{H} \times 256 + B_{L}

Where AHA_H, ALA_L, BHB_H, and BLB_L are the high and low bytes of AA and BB, respectively. The resulting multiplication operation can be broken down into smaller segments:

Product=(A_H×256+A_L)×(B_H×256+B_L)Product = (A\_H \times 256 + A\_L) \times (B\_H \times 256 + B\_L)

Expanding this expression gives:

Product=A_H×B_H×65536+A_H×B_L×256+A_L×B_H×256+A_L×B_LProduct = A\_H \times B\_H \times 65536 + A\_H \times B\_L \times 256 + A\_L \times B\_H \times 256 + A\_L \times B\_L

Each of the terms can be calculated using an 8-bit multiplication.

Optimized Algorithm

To optimize the multiplication, a strategic approach can diminish the total number of operations by reusing partial results and minimizing additions. One such optimized method is the iterative shift-and-add processing which exploits the binary decomposition of the numbers.

Faster 16-bit Multiplication Algorithm

Here is a step-by-step explanation of an efficient method to multiply two 16-bit numbers:

  1. Initialize Registers: • Load the initial values of A and B into two pairs of 8-bit registers representing their high and low bytes.
  2. Compute Partial Products: • Compute AL×BLA_L \times B_L: This is the simplest multiplication as it directly contributes to the lower byte of the final product. • Compute AL×BHA_L \times B_H and AH×BLA_H \times B_L: These contribute mainly to the middle segment of the resulting word. Each multiplication here will need to be left-shifted by 8 bits (equivalent to multiplying by 256). • Compute AH×BHA_H \times B_H: This contributes to the higher byte and needs to be left-shifted by 16 bits in the final product assembly.
  3. Aggregate Partial Products with Shifting: • Add the results, as shown in the following combinatorial scheme, ensuring that carries from one byte are considered in the subsequent higher byte:

Low Byte: (A_L×B_L)Middle Byte: (A_L×B_H)+(A_H×B_L)+carry from low byteHigh Byte: (A_H×B_H)+carry from middle byte\begin{align*} &\text{Low Byte: } (A\_L \times B\_L) \\ &\text{Middle Byte: } (A\_L \times B\_H) + (A\_H \times B\_L) + \text{carry from low byte}\\ &\text{High Byte: } (A\_H \times B\_H) + \text{carry from middle byte} \end{align*}

  1. Optimize Carries Management: • Use assembly instructions wisely to manage carries that arise when adding 8-bit results. Adding with carry instructions (ADD /ADC in AVR assembly) efficiently manages the multi-byte aggregation.

Example Code

Below is an illustrative example in pseudocode that translates the above approach into steps suitable for a typical 8-bit AVR type MCU:

• Instruction Cycle Count: Depending on the architecture, these operations (8-bit multiplication, additions, and carries) can be significantly faster when carefully sequenced compared to calling generic multiplication routines. • Memory Use and Efficiency: This implementation is efficient in terms of memory since it mainly uses registers. This is crucial for MCUs with limited RAM. • Scalability: This method scales well for slightly larger bit-widths with the same principle applied to segments of the binary representation.


Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Data Structures & Algorithms practice on Codemia

Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.

Practice algorithms