A = 0
A common test is to see if A is 0, so you would expect to use CP 0
to test for it.
Just like setting A to 0 we can compare quicker.
In this case, instead of CP 0
we can just use either OR A
or AND A
instead.
Just 1 byte and 3 T-states faster.
For example, take this simple routine which writes a NULL terminated string pointed to by HL to the screen of the Sinclair ZX Spectrum:
The optimisation here is to replace CP 0
with OR A
A = 1
Comparing A to 1 can also be done using DEC A
instead of CP 1
.
By decrementing A, the Z flag will be set if A is now 0.
Like above its faster and 1 byte, but it also alters A, so it's not really of any use unless you don't care about
the value of A after the test.
Internally, CP 1
just does A-1 but discards the result which is why DEC A
works in this instance.
Compare number
With CP
it's easy to test for less than (<), equals (=), not equals (!=) or
greater-than-equals (>=) because of how the C and Z flags are used:
The following shows how to get the other two tests, Less-Than-Equals (<=) and Greater-Than(>):
A <= n
This is a simple one. As CP
tests against A-n then if A=N then Z is set but if A < n then C is
set.
To optimise this we should test against n+1 instead. Doing this means we can just use the Carry flag as it would be set when A < n+1:
A > n
This is the opposite problem. Here Carry is clear when A>=n, so to get A>n we first need to test for equals using the Z flag and if that's not set then check for the Carry flag to be clear:
Like the previous example, this can be optimised simply by adding 1 and then testing for A >= (n+1) instead:
Wasteful use of CP
It's easy to forget that some instructions set the flags based on the result so frequently
you do not need to use CP
to test for a condition when the result is already known:
Here we check for bit 1 of A is set and if it is we exit the subroutine:
Here the CP
isn't required as AND
will set Z if A=0,
so we can remove the CP
and use NZ
instead saving 2 bytes:
Testing bits
Testing Bit 0 of A
The standard method of testing if bit 0 of A is set is to use BIT 0,A
:
If we don't need A afterwards then we can optimise this by using a right shift instead:
This works as we just shifted bit 0 into the Carry Flag and we save an additional byte in the process.
Using RRA
would be faster & saves 1 byte, but it destroys A.
If you need to keep A intact then keep the BIT instruction.
Testing Bit 7 of A
Just like testing bit 0, with bit 7 we can do the same but shifting right instead.
So rather than using BIT 7,A
like:
We can just use RLA
and test the Carry flag:
The downside of this is it destroys the contents of A.