TL;DR:
Simply because SRA C
doesn't shift A by the content of C, but shifts C right by one with keeping bit 7 (sign) static.
Z80 and shifting:
While the Z80 did add some nice new shifts and rotates, like the mentioned Shift Left Arithmetic for all 7 registers and memory, it still only shifts by one bit position per execution. So any shift by more than one position will, like with many other 8-bit CPUs, require repetition - as loop or unrolled, as in:
LD A,11110000b ;(*1)
SRA A
SRA A
SRA A
SRA A
OUT (0),A
Why not?
Well, doing multi position shift would either
require a barrel shifter - not really cool as that needs quite a lot of real estate, whereas a single bit shifter comes almost free with regular ALU design.
Or need a micro program loop to handle that case - again rather costly.
Keep in mind, (classic) 8 bit CPUs are not about making life comfortable, but getting work done at all - they are only one step above no CPU.
So is there a better way?
Yes, use RRA
. It takes only 4 T-states while SRA
takes 8.
LD A,11110000b
RRA
RRA
RRA
RRA
OUT (0),A
This is due the fact that SRA
is an Z80 enhancement which needs, while doing essentially the same operation, a prefix byte (0CBh), which in itself eats up 4 T-states.
RRA
is a basic 8080 instruction (*2), encoded in a single byte (01Fh) and thus able to be executed in 4 T-states. In 8080 assembly it's called RAR
.
Using RRA
thus brings 3 advantages at once:
- More compact code
- Faster execution
- Compatibility with other 8080 compatible CPUs
Yes but ...
As Supercat reminds us, there's an odd pair of instructions rotating nibble wise:
- RLD - Rotate Left Digit and
- RRD - Rotate Right Digit
They rotate a byte pointed to by HL thru the lower 4 bits of A.
RLD moves the top 4 bit of a memory location into the lower 4 bit of A, moves the lower 4 bit of that location into the higher 4 and stores the lower 4 of the original content of A into the lower 4. Confusing? Lake a look here:
RRD does the same just the other way around:
Sounds great, especially when considering that output is more often than not multiple bytes from memory, which are pointed to by HL anyway. To output both nibbles of a byte pointed to by HL code might look like this:
LD A,(HL)
AND 0Fh
OUT (0),A
RLD
AND 0Fh
OUT (0),A
(Outputting the lower 4 first)
The whole works has just two tiny disadvantages:
- it destroys the input byte and
- it isn't much faster at all
While the 4 SRA take 16 T-states, RLD takes 18 - but saves an additional LD - which in turn may or may not be needed depending on the over all program structure.
This two, plus the fact that the vast majority of Z80 programmers will need to look at the manual when encountering an RLD/RRD, make a good reason to stay with the classic 8080 compatible RRA sequence.
*1 - It's bad practice to add spaces in assembler parameters, as that's not portable -especially not if one wants to use tools contemporary to that CPUs.
*2 - Not to be confused with RR A
, which is the same but in Z80 encoding, like SRA
, with a 0CBh prefix and 8 T-states.
sra x
isx >>= 1
, nota >>= x
. It stands for ‘shift right, arithmetic’, not ‘shift right the accumulator’.rra
(other than it being a bit rotation instruction instead of a bit shift)?