# How to subtract a negative 8bit number from a 16bit one?

hi all, I'm doing it in a not elegant way, for sure, and maybe using too much cpu...

here's the problem:
I have on hl a coordinate in a 16bit range
and in the accumulator I have an offset that could be positive or negative.
I need often to adjust coordinates subtracting the offset value (subtracting a positive offset the coordinate decreases and subtracting a negative value the coordinate increases)

This is to determinate the respawn location in my Turrican code.
Here's how I'm doing it:

```	ld	d,a                  ;a is 0 from previous code, so it is like ld d,0
ld	hl,(map_pos)        ;actual position inside the tilemap
ld	(restart_point),hl  ;store it
ld	hl,(x_coord)        ;actual x coordinate
ld	a,(dx)                ;actual x offset. dx (and dy) are used on scrolling routine to determine if we are moving left or right (or up or down) relatively to the actual tile (tiles are 4x4 chars, so dx and dy values vary from 0 to 3 and are the values you can see in Turrican videos)
and	a
jp	m,dx_negative_fix    ;check if dx has negative value
ld	e,a                           ;copy dx value in e (so we have de= dx
sbc	hl,de             ;subtract dx from x coordinate (so when respawning to actual tile we can restore also x position to starting char without messing relation between map and coordinates
set_restart_x:
ld	(restart_x),hl    ;store obtained value to be used in case of respawn
ld	hl,(y_coord)
ld	a,(dy)
and	a
jp	m,dy_negative_fix
ld	e,a
sbc	hl,de
set_restart_y:
ld	(restart_y),hl
ret
dx_negative_fix:
inc	hl                ;subtracting a negative value is like adding its positive value so increase hl
inc	a                 ;using dx as counter increasing it until 0
jp	nz,dx_negative_fix
jp	set_restart_x
dy_negative_fix:
inc	hl
inc	a
jp	nz,dy_negative_fix
jp	set_restart_y
```
Login sesión o register para postear comentarios

Oh, I forgot: before jp m,dx_negative_fix there is a jp z,set_restart_x (same for dy part)

If I have not misunderstood, you are trying to achieve `HL (unsigned) -= A (signed)`, aren't you ?

```	ld	hl, (unsigned16bit)
ld	a, (signed8bit)
; bc = a
ld	c, a
sbc	a	; (high byte 0 or -1)
ld	b, a
; hl -= bc
or	a	; (clears carry flag)
sbc	hl, bc
```

(note: untested code)

Exactly as theNestruo mentions. The idea is to "extend the sign" of the 8 bit number into a 16 bit register ( https://plutiedev.com/z80-extend-8bit-to-16bit ), which is exactly what the first 4 ops in the code theNestruo shared above do, and then you can just subtract/add with your other 16 bit number.

It is exactly what I need. I didn't know how to extend the sign. Thank you!

Maybe it could be optimized like this (untested)

ld hl, (unsigned16bit)
ld a, (signed8bit)
neg ; (sign of -a in carry flag)
; bc = -a
ld c, a
sbc a ; (high byte 0 or -1)
ld b, a
; hl += bc

ARTRAG wrote:

Maybe it could be optimized like this (untested)

I'm not sure, but I'd say that NEG subtracts A from 0, so carry flag will be always set regardless the sign of A/-A (unless A=0).

ah! If this is the case my version will not work

I've been using variants of these, but added improvements here and there (when you find something that fits your code better): https://plutiedev.com/z80-add-8bit-to-16bit (same site as santi pointed out, but different link)

Nice site! There are two options for the requested case
This is 14 bytes and 62 cycles:

```    ; 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
ld    l, a
sub   l
ld    h, a
```

This other is 7 bytes and 42 cycles

```    ld    e, a    ; DE = A
Really good site, added to favorites 