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:

• if d0 started with 00000010, after the instruction d0 will contain 00000000
• if d0 started with 0000002E, after the instruction d0 will contain 0000001E
• if d0 started with 000000E4, after the instruction d0 will contain 000000D4
• if d0 started with 00000008, after the instruction d0 will contain 000000F8

Of course, let’s not forget, we’re only subtracting a byte so:

• if d0 started with 00001014, after the instruction d0 will contain 00001004
• if d0 started with 222222FC, after the instruction d0 will contain 222222EC
• if d0 started with 33333301, after the instruction d0 will contain 333333F1

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:

• if d0 started with 00000500, after the instruction d0 will contain 00000300
• if d0 started with 00004B20, after the instruction d0 will contain 00004920
• if d0 started with 4444310F, after the instruction d0 will contain 44442F0F

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.

• If d0 contains 010000F0, and d1 contains 02000100, after the instruction d1 will contain 01000010.

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.