Date : Tue, 15 May 1990 08:00:17 GMT
From : eru!luth!sunic!mcsun!hp4nl!kunivv1!root@BLOOM-BEACON.MIT.EDU (Privileged Account)
Subject: a<b on Z80
wittig@gmdzi.UUCP (Georg Wittig) writes:
>How to write a signed compare of two 16 bit integers in Z80 assembler? The
>obvious solution doesn't work:
> [deleted]
>The only compact and correct solution I could find was the following one:
> LD HL,a
> LD DE,b
> AND A
> SBC HL,DE
> JP PO,LABEL
> JP P,IS_LESS
> JP IS_GREATER_OR_EQUAL
>LABEL: JP P,IS_GREATER_OR_EQUAL
>IS_LESS:...
>But this one looks very ugly to me. Does someone know of a shorter and/or
>faster solution?
Let's see. The easiest solution I could think of was something like this:
LD HL,a
LD DE,b
;Remove 8000H bias from signed numbers
LD BC,8000H
ADD HL,BC
EX DE,HL
ADD HL,BC
EX DE,HL
;Now we can do an unsigned compare
AND A ;Clear carry
SBC HL,DE
DONE: ;Carry flag set if a<b
;Zero flag set if a=b
This removes the 8000H bias on signed numbers to make them comparable as
unsigned numbers. However, it is not the shortest/fastest one, and
clobbers BC.
A little thought reveals the removing the bias is not needed if both
numbers have the same sign. And luckily, if they don't, we do already
know the answer (or can find out easily). This leads to
LD HL,a
LD DE,b
;Test signs
LD A,H
XOR D
JP M,DIFSGN
;Equal signs, do an unsigned compare (carry already clear)
SBC HL,DE
JR DONE
DIFSGN: ;Different signs, set up the carry (zero already clear)
LD A,H
RLCA ;Does not modify zero flag
DONE: ;Carry flag set if a<b
;Zero flag set if a=b
But this still does not satisfy me. However, we can employ a trick to
get the carry and zero flags right in case of different signs. If HL has
the negative signed number, it has the greater unsigned number, and the
unsigned subtraction will thus result in a carry set the wrong way.
The same thing happens when DE has the negative signed number. Thus,
in the case of different signs, we just have to reverse the operands to
the compare to get everything right. Or:
LD HL,a
LD DE,b
;Test signs
LD A,H
XOR D
JP P,EQUSGN
;Different signs, have to reverse the operands
EX DE,HL
EQUSGN: ;We can not do an unsigned compare (carry already clear)
SBC HL,DE
DONE: ;Carry flag set if a<b
;Zero flag set if a=b
This is the best I could think of; it uses only 5 instructions for the
actual compare (8 bytes). If anyone knows better, please mail (or post).
--
Luc Rooijakkers Internet: lwj@cs.kun.nl
Faculty of Mathematics and Computer Science UUCP: uunet!cs.kun.nl!lwj
University of Nijmegen, the Netherlands tel. +3180612271