Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Z80 assembly: How to add signed 8-bit value to 16-bit register?

Tags:

math

assembly

z80

I've written a Z80 disassembler that runs from the ROM in my SBC. One of the last things I need to do (as-yet-unspotted bugs aside) is to translate relative addresses and output them as absolute addresses, so that when the disassembler hits one of the five JR opcode variants, it displays the absolute address the JR opcode is pointing to.

The JR opcode variants use an 8-bit offset value to tell the Z80 where in memory to jump to. The offset is a single, signed (-128 <-> 127) byte which I need to add to the current memory location in the HL register to get the absolute address.

My brain seems to be suffering a serious syntax error though, perhaps even a division by zero, as I can't for the life of me work out how to add an 8-bit signed (or 2's complement) byte to a 16-bit register to get the absolute address. Have searched the interweb and no answers are forthcoming.

Can anyone suggest a solution or point me in the right direction?

like image 861
nockieboy Avatar asked Mar 02 '18 14:03

nockieboy


1 Answers

Easiest way is to sign extend the 8 bit value to 16 bits and then use a 16 bit add. Here's some code that does it. A is the 8 bit signed value and HL is the 16 bit base address that the 8 bit signed value will be added to. Result in HL

   LD  E,A
   ADD A,A      ; sign bit of A into carry
   SBC A,A      ; A = 0 if carry == 0, $FF otherwise
   LD  D,A      ; now DE is sign extended A
   ADD HL,DE

Also keep in mind that for JR the offset is relative to the address just after the instruction, not the address of the JR instruction itself.

like image 85
George Phillips Avatar answered Oct 09 '22 02:10

George Phillips