1. Predict the flags
A CMP subtracts B from A at 8 bits and keeps only the flags. Work out N, Z, C and V on paper before you press check. ARM's rule: C is 1 when no borrow was needed.
2. Which branches fire
No numbers this time, only the four flags a CMP left behind. Press every branch that would be taken. The unsigned family reads C and Z, the signed family reads N, V and Z, and BEQ and BNE read Z alone.
3. Recover the type
Here is a compiled if. Say whether the variables were declared unsigned or signed, and which comparison the C source used. There are two clues to the type, the load and the branch, and one trap: a compiler often branches over the body when the test fails, so read where the branch goes before you read its condition.
4. Widen by hand
A byte is loaded into a 32-bit register. Write the register's contents as eight hex digits, and its value as a decimal number, read the way the load intended. LDRB zero-extends; LDRSB sign-extends.
How to use these
- Answer on paper first, every time. The point is to make the prediction, not to recognise the answer once it is shown.
- Do a few of one drill until it feels mechanical, then move on. Ten of drill 1 is usually enough for the borrow rule to stop needing thought.
- When a reveal surprises you, load the same pair into the Bit Lab and watch the carries move; the worked bits here are the lab's SUB, drawn the same way.
- Drill 3 is the one that transfers to real debugging. To see real compiler output for your own snippets, paste a C function into Compiler Explorer with an ARM GCC and
-O1. - Scores are kept only in this browser. Reset them whenever you like.