Typical 16-bit increment
Overflow (incrementing to $0000) sets the Z flag is set (i.e. BEQ branches).
;
INC NUML
BNE LABEL
INC NUMH
LABEL
Typical 16-bit decrement
;
LDA NUML
BNE LABEL
DEC NUMH
LABEL DEC NUML
16-bit decrement, test for zero
;
LDA NUML
BNE LABEL
LDA NUMH
BEQ ZERO ; branch when NUM = $0000 (NUM is not decremented in that case)
DEC NUMH
LABEL DEC NUML
Add 255
;
LDA NUML
BEQ LABEL
INC NUMH
LABEL DEC NUML
Subtract 255
;
INC NUML
BEQ LABEL
DEC NUMH
LABEL
Constant time increment
6 cycles
A = high byte, X = low byte
Overflow (incrementing to $0000) sets the carry
CPX #$FF
INX
ADC #$00
Constant time decrement
6 cycles
A = high byte, X = low byte
Underflow (decrementing to $FFFF) clears the carry
CPX #$01
DEX
SBC #$00
Increment and stop at $00
This counts up to $FF then to $00, then stays at $00.
CMP #1
ADC #0
One advantage of a CMP before the ADC (and SBC below) is that the accumulator always contains the correct value. If it were an increment, compare, branch, and decrement (to return to the stop value), then it would briefly, but temporarily, not be at the stop value.
Decrement and stop at $FF
This counts down to $00 then to $FF, then stays at $FF.
CMP #$FF
SBC #0
Double-decrement
To subtract two from a 16-bit value, you can execute an above routine twice, but it is probably more efficient to code it as its own case:
DEC2 LDA NUML
SEC
SBC #2
STA NUML
BCS LABEL
DEC NUMH
LABEL
If for any reason you may need to preserve the accumulator or V flag, or if you need a binary decrement while D is set, you can wrap the above routine with PHP PHA CLD … and … PLA PLP, or you can sacrifice the X or Y register like so:
DEC2 LDY NUML
CPY #2
DEY
DEY
STY NUML
BCS LABEL
DEC NUMH
LABEL
If you know you're not in decimal mode, you can keep the high byte in A and the low byte in X or Y, resulting in a tidy:
DEC2 CPY #2
DEY
DEY
SBC #0