16-bit multiplication is the multiplication of two 16-bit value from another. Such a multiplication results in a 32-bit value.
Programming Tip: In fact, any multiplication results in an answer which is the sum of the bits in the two multiplicands. For example, multiplying an 8-bit value by a 16-bit value results in a 24-bit value (8 + 16). A 16-bit value multiplied by another 16-bit value results in a 32-bit value (16 + 16), etc.
For the sake of example, let's multiply 25,136 by 17,198. The answer is 432,288,928. As with both addition and subtraction, let's first convert the expression into hexadecimal: 6230h x 432Eh.
Once again, let's arrange the numbers in columns as we did in primary school to multiply numbers, although now the grid becomes more complicated. The green section represents the original two values. The yellow section represents the intermediate calculations obtained by multipying each byte of the original values. The red section of the grid indicates our final answer, obtained by summing the columns in the yellow area.
. | Byte 4 | Byte 3 | Byte 2 | Byte 1 |
. | . | . | 62 | 30 |
* | . | . | 43 | 2E |
= | . | . | 08 | A0 |
. | . | 11 | 9C | . |
. | . | 0C | 90 | . |
. | 19 | A6 | . | . |
= | 19 | C4 | 34 | A0 |
Our process in assembly language will be identical. Let's use our now-familiar grid to help us get an idea of what we're doing:
. | Byte 4 | Byte 3 | Byte 2 | Byte 1 |
* | R6 | R7 | ||
* | R4 | R5 | ||
= | R0 | R1 | R2 | R3 |
- Multiply R5 by R7, leaving the 16-bit result in R2 and R3.
- Multiply R5 by R6, adding the 16-bit result to R1 and R2.
- Multiply R4 by R7, adding the 16-bit result to R1 and R2.
- Multiply R4 by R6, adding the 16-bit result to R0 and R1.
Step 1. Multiply R5 by R7, leaving the 16-bit result in R2 and R3.
MOV A,R5 ;Move the R5 into the Accumulator MOV B,R7 ;Move R7 into B MUL AB ;Multiply the two values MOV R2,B ;Move B (the high-byte) into R2 MOV R3,A ;Move A (the low-byte) into R3 |
Step 2. Multiply R5 by R6, adding the 16-bit result to R1 and R2.
MOV A,R5 ;Move R5 back into the Accumulator MOV B,R6 ;Move R6 into B MUL AB ;Multiply the two values ADD A,R2 ;Add the low-byte into the value already in R2 MOV R2,A ;Move the resulting value back into R2 MOV A,B ;Move the high-byte into the accumulator ADDC A,#00h ;Add zero (plus the carry, if any) MOV R1,A ;Move the resulting answer into R1 MOV A,#00h ;Load the accumulator with zero ADDC A,#00h ;Add zero (plus the carry, if any) MOV R0,A ;Move the resulting answer to R0. |
Step 3. Multiply R4 by R7, adding the 16-bit result to R1 and R2.
MOV A,R4 ;Move R4 into the Accumulator MOV B,R7 ;Move R7 into B MUL AB ;Multiply the two values ADD A,R2 ;Add the low-byte into the value already in R2 MOV R2,A ;Move the resulting value back into R2 MOV A,B ;Move the high-byte into the accumulator ADDC A,R1 ;Add the current value of R1 (plus any carry) MOV R1,A ;Move the resulting answer into R1. MOV A,#00h ;Load the accumulator with zero ADDC A,R0 ;Add the current value of R0 (plus any carry) MOV R0,A ;Move the resulting answer to R1. |
Step 4. Multiply R4 by R6, adding the 16-bit result to R0 and R1.
MOV A,R4 ;Move R4 back into the Accumulator MOV B,R6 ;Move R6 into B MUL AB ;Multiply the two values ADD A,R1 ;Add the low-byte into the value already in R1 MOV R1,A ;Move the resulting value back into R1 MOV A,B ;Move the high-byte into the accumulator ADDC A,R0 ;Add it to the value already in R0 (plus any carry) MOV R0,A ;Move the resulting answer back to R0 |
Combining the code from the two steps above, we come up with the following subroutine:
MUL16_16: ;Multiply R5 by R7 MOV A,R5 ;Move the R5 into the Accumulator MOV B,R7 ;Move R7 into B MUL AB ;Multiply the two values MOV R2,B ;Move B (the high-byte) into R2 MOV R3,A ;Move A (the low-byte) into R3 ;Multiply R5 by R6 MOV A,R5 ;Move R5 back into the Accumulator MOV B,R6 ;Move R6 into B MUL AB ;Multiply the two values ADD A,R2 ;Add the low-byte into the value already in R2 MOV R2,A ;Move the resulting value back into R2 MOV A,B ;Move the high-byte into the accumulator ADDC A,#00h ;Add zero (plus the carry, if any) MOV R1,A ;Move the resulting answer into R1 MOV A,#00h ;Load the accumulator with zero ADDC A,#00h ;Add zero (plus the carry, if any) MOV R0,A ;Move the resulting answer to R0. ;Multiply R4 by R7 MOV A,R4 ;Move R4 into the Accumulator MOV B,R7 ;Move R7 into B MUL AB ;Multiply the two values ADD A,R2 ;Add the low-byte into the value already in R2 MOV R2,A ;Move the resulting value back into R2 MOV A,B ;Move the high-byte into the accumulator ADDC A,R1 ;Add the current value of R1 (plus any carry) MOV R1,A ;Move the resulting answer into R1. MOV A,#00h ;Load the accumulator with zero ADDC A,R0 ;Add the current value of R0 (plus any carry) MOV R0,A ;Move the resulting answer to R1. ;Multiply R4 by R6 MOV A,R4 ;Move R4 back into the Accumulator MOV B,R6 ;Move R6 into B MUL AB ;Multiply the two values ADD A,R1 ;Add the low-byte into the value already in R1 MOV R1,A ;Move the resulting value back into R1 MOV A,B ;Move the high-byte into the accumulator ADDC A,R0 ;Add it to the value already in R0 (plus any carry) MOV R0,A ;Move the resulting answer back to R0 ;Return - answer is now in R0, R1, R2, and R3 RET |
And to call our routine to multiply the two values we used in the example above, we'd use the code:
;Load the first value into R6 and R7 MOV R6,#62h MOV R7,#30h ;Load the first value into R4 and R5 MOV R4,#43h MOV R5,#2Eh ;Call the 16-bit subtraction routine LCALL MUL16_16 |
Previous: 16-Bit Subtraction | Tutorial Contents | Next: 16-Bit Division |