# Z80 adding 8-bit to 16-bit

Sometimes you need to add an 8-bit value (in A) to a 16-bit one (in either HL, BC or DE). You can extend the value to 16-bit, but it can get cumbersome as you may need to clobber registers you're using and possibly move values around (since only HL can be a destination).

Here we show how to do this without resorting to using 16-bit operations (which can avoid all those issues). Note that here "unsigned" and "signed" refers to the 8-bit value in A.

Some notes:

- In all these cases, only A gets clobbered.
- In all these cases, you can replace HL with BC or DE.
- You really should consider wrapping these into macros.

## Unsigned addition

Adding A to HL is kind of tricky (you'll probably understand it better
from the comments in the code snippet below). We first add the low byte.
Then we add the high byte with carry *and* substract the low byte
to get the high byte's result (which is high byte + carry).

We'll build on the code below for the other methods.

` `**add** a, l ; A = A+L
**ld** l, a ; L = A+L
**adc** a, h ; A = A+L+H+carry
**sub** l ; A = H+carry
**ld** h, a ; H = H+carry

## Signed addition

Signed addition is similar, except we "extend" A to 16-bit. The "high byte" of A is always either 0 (if positive) or -1 (if negative), so we check A's sign and adjust H accordingly. After this we add the lower byte as with unsigned addition.

```
; If A is negative, we need
; to substract $100 from HL
; (since A's "upper byte" is
; $FF00)
```**or** a
**jp** p, Positive
**dec** h
Positive:
; Then do addition as usual
; (to handle the "lower byte")
**add** a, l
**ld** l, a
**adc** a, h
**sub** l
**ld** h, a

## Unsigned substraction

The idea behind this is that HL - A is the same thing as HL + (-A), so we flip A's sign then perform an addition. The catch is that A's "upper byte" becomes -1, so we need to substract 1 from HL's upper byte to account for this. Think of this as a specialized variant of signed addition.

The exception is when A is 0 (which when negated is still 0). Substracting 0 is the same as doing nothing, so we just skip the whole ordeal in that case.

```
; If A=0 do nothing
; Otherwise flip A's sign. Since
; the upper byte becomes -1, also
; substract 1 from H.
```**neg**
**jp** z, Skip
**dec** h
; Now add the low byte as usual
; Two's complement takes care of
; ensuring the result is correct
**add** a, l
**ld** l, a
**adc** a, h
**sub** l
**ld** h, a
Skip:

## Signed substraction

Signed substraction is trivial to build on top of signed addition: flip A's sign then do the addition. The only catch
is that we need to handle that `-$80`

should become
`+$80`

(thankfully, the overflow flag gets set when trying to
flip its sign, so we can handle that particular case easily).

```
; We negate A (since HL - A
; is the same as HL + -A)
```**neg**
; Now add the "upper byte"
; The flags are already set by NEG
; The JP PE is because -$80 becomes
; +$80 so we need to handle it too
**jp** p, Positive
**jp** pe, Positive
**dec** h
Positive:
; Then add the low byte
**add** a, l
**ld** l, a
**adc** a, h
**sub** l
**ld** h, a

## With 16-bit operations

For the sake of completeness, since if the stars align right somehow (i.e. values happen to be in the right registers) these may be more useful. Also they're more compact, if space usage matters more than speed in a particular case.

Remarks (or "why I don't like this"):

- Destination must be HL
- You must clobber BC or DE
- For whatever reason there's no 16-bit
`sub`

, only`sbc`

(hence why we need to clear carry when doing substraction) - You'll want to learn how to extend 8-bit values to 16-bit, since the code below uses those techniques to turn A into 16-bit.

Unsigned addition:

` `**ld** e, a ; DE = A
**ld** d, 0
**add** hl, de ; HL = HL+DE

Signed addition:

` `**ld** e, a ; DE = A
**add** a, a
**sbc** a
**ld** d, a
**add** hl, de ; HL = HL+DE

Unsigned substraction:

` `**ld** e, a ; DE = A
**ld** d, 0
**or** a ; Clear carry
**sbc** hl, de ; HL = HL-DE

Signed substraction:

` `**ld** e, a ; DE = A
**add** a, a
**sbc** a
**ld** d, a
**or** a ; Clear carry
**sbc** hl, de ; HL = HL-DE