Assembly is Too High Level: Subtracting by Comparing (Propeller)

If you’re familiar with x86, you’d know that a CMP (compare) instruction is the same as a SUB (subtract) instruction, with exception to the destination operand being written to. In other words, CMP is like a subtract, it just doesn’t write the value when done (but it does set all of the flags that a subtract would. so CMP is used preceding conditional jmps; as conditional jumps base their conditions on the flags. Although this post will focus on CMP and SUB, the same tricks apply to TEST and AND (this goes for both x86 and Propeller). The main difference with x86 and Propeller in this respect is that x86 has completely different machine-code for these instructions. Not the case for Propeller.

In my previous blog entry on Propeller NOPs, I went into some detail on the instruction format of the Propeller micro-controller. The main parts that are important for this entry are the 6-bit op-code part, and the ZCRI flag section (mostly just the R part of it).

Let’s compare the CMP and SUB instructions

CMP:

SUB:

So the op-code (100001) part is the same for both. Really, the only actual difference in the binary that makes up these two instructions is the R field. The R field specifies whether the value/pointer in the -DEST- field will get modified. However, we can override this default behavior within the Propeller assembly language with nr/wr (don’t write/do write, respectively). This means we can over-ride a CMP into being a SUB and a SUB into becoming a neutered CMP. So obviously we will do that:

And to see the Machine Code:

Our encoded instruction is 0x0204FC84. You will see that value repeat twice in a row, because the ‘sub’ and ‘cmp’ instructions seen in the assembly are identical in machine code. If you are skeptical that the cmp actually subtracts (because you all are), let’s debug (with my favorite debugger/emulator: GEAR):

It is shown as 2 SUBs. The last byte of the 3rd line is our 1-byte “AVariable” (Propeller is far from Harvard architecture). So if we subtract 2 from $55, we should have $53:

And we run the 2nd SUB (the assembly CMP) and we get our expected $51 from subtracting 2 again: