Section
02 Part 02 – The SUB Instruction |
“If people do not believe that mathematics is simple, it is only because they do not realize how complicated life is.” ~John Louis von Neumann |
Introduction
SUB – SUBtract
binary
This
instruction will subtract the number of the source operand from the destination operand; the source
operand will
remain unchanged.
Examples
This
here is obviously the exact opposite of ADD, and here’s an example of the SUB
instruction in use:
subi.b #$10,d0 |
This
will subtract the byte 10 from the byte in data register d0:
Of
course, let’s not forget, we’re only subtracting a byte so:
Just
about every instruction has the same principle, only the right byte is
affected.
Let’s
have an example using word:
subi.w #$0200,d0 |
This
will subtract the word 0200 from the word in data register d0:
Once
again, only the right words are affected.
Other
Examples
You
can subtract numbers of one register from another, for example:
sub.l d0,d1 |
This
will subtract a long-word of data in d0
from d1.
You
can subtract data from memory:
sub.w d0,$0000102E |
This will
copy the word in d0, and subtract it from memory
at offset $0000102E. If d0
contains 09920022, and the bytes at memory $0000102E and
$0000102F are 00
and 2E, then 002E – 0022 = 000C. 00 0C
are therefore moved into memory at offsets 0000102E and 0000102F:
Offset |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
A |
B |
C |
D |
E |
F |
etc |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
00001000 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00001010 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00001020 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
0C |
00001030 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
etc |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
You
can subtract data in memory from a data register:
sub.b $00001040,d0 |
If d0 contains 00121080, and the
data in memory is:
Offset |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
A |
B |
C |
D |
E |
F |
etc |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
00001030 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00001040 |
70 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00001050 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00001060 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
00 |
etc |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 is copied out of memory and
subtracted from the byte 80 inside d0. d0 will then contain 00121010.
Unfortunately,
you cannot subtract data in
memory location from another memory location:
sub.b $00000120,$00000124 |
However,
just like the add instruction, the same methods of getting around work just as
well:
move.b $00000120,d0 sub.b d0,$00000124 |
As
you can see, we copied the data from memory at offset 00000120 to a data
register first, and then subtracted the data register from the other memory at
offset 00000124.
You
can use the address registers too:
sub.w d1,$72(a0) sub.l $40(a0),d4 sub.w d5,(a1) subi.b #$98,(a0)+ sub.w a1,d0 |
However,
you cannot subtract from memory
to memory using the address registers:
sub.w (a0),(a1) sub.l (a0)+,$10(a2) sub.w $9E(a4),-(a3) sub.b $10(a0),$10(a6) |
Sub
Immediate
Just
like the add instruction, if the source operand is “immediate”, you must use the instruction “subi”
instead of “sub” (where the “i” stands for
immediate):
subi.b #$20,d0 |
Again,
don’t worry if you use just plain old “sub” instead, as the assembler will turn
it into subi for you, when it assembles your code.