lh 8
lq on
ps off
cw 12
                 Z-80 Instructions RLD and RRD
po 8

    The Z-80 instructions RLD and RRD are a pair of instructions �
that  a  poorly understood by most  programmers.   Although  they �
appear  a  little  strange and perhaps rather  useless  at  first �
glance, they are particularly useful for the manipulation of  BCD �
numbers.   A single RLD or RRD instruction will  usually  replace �
several lines of 8080 code.

    Let  me  give  you  some  examples  of  the  use  of   these �
instructions.  Suppose that we have a large packed BCD number  (2 �
digits  per  byte)  stored in memory at BCDNUM.   The  number  is �
BCDLEN  long, so the last 2 digits are stored at BCDNUM +  BCDLEN �
-1.  If we wish to print this number, we must first convert it to �
ASCII.   The following code would accomplish this, assuming  that �
ECHO is a subroutine which sends the contents of the accumulator, �
A, to the screen while preserving all registers, including A:

         LD   HL,BCDNUM      ; Point to the the start of the number
         LD   B,BCDLEN       ; Set up a counter
         LD   A,30H          ; Prepare A for ASCII print

BCDLP:    RLD                 ; Shift the high nibble of (HL) to
                             ;  the low nibble of A and the low
                             ;   nibble of (HL) to the high nibble
                             ;    of (HL)
         CALL ECHO           ; Print the digit
         RLD                 ; Now shift the high nibble (the previous
                             ;  low nibble) of (HL) to A
         CALL ECHO           ; Print that one
         RLD                 ; Restore the original packed number
         INC  HL             ; Point the the next two digits
         DJNZ BCDLP          ; Loop until done

    These  instructions can also be used to align  operands  for �
BCD  floating  point arithmatic (and are much  faster  than  code �
using  single  bit shifts).  Suppose that you wish to  shift  the �
number  in the previous example right by one nibble and insert  a �
zero  in the high order nibble.  Following will  accomplish  this �
quite easily:

         XOR  A              ; Clear accumulator
         LD   HL,BCDNUM      ; Point to the number
         LD   B,BCDLEN       ; Our counter again

SHIFTLP:  RRD                 ; Shift low nibble of A to high nibble
                             ;  of (HL), high nibble of (HL) to low
                             ;    nibble of (HL) and low  nibble of
                             ;     (HL) to A
         INC  HL             ; Point to next byte
         DJNZ SHIFTLP        ; Loop til done

This routine effectively divides our BCD number by 10.
pa
Actually, a more useful (though slightly more complex) example is �
a  routine to allow keyboard input of a decimal number  which  is �
then converted to BCD format:

         XOR  A              ; Clear accumulator
         LD   HL,BCDNUM      ; Point to storage for number
         LD   B,BCDLEN       ; Our ubiquitous counter!

CLEARLP:  LD   (HL),A         ; Clear entire buffer to 0
         INC  HL
         DJNZ CLEARLP
         LD   B,BCDLEN       ; Reset counter
         LD   C,2            ; Need 2 ASCII per BCD digit
         LD   HL,BCDNUM+BCDLEN ; Point to least significant

NXTDIGIT: CALL GETCH          ; Routine to get 1 ASCII char
                             ;  from keyboard (preserves
                             ;   HL and BC)
         CP   CR             ; Carriage return?
         RET  Z              ; If so, all done

ADDLP:    RLD                 ; Shift digit
         DEC  C              ; Done 2 digist?
         JR   NZ,NXTDIGIT    ; If not, go get another
         LD   C,2            ; Else, reset digit counter
         DEC  HL             ;  adjust pointer
         DJNZ NXTDIGIT       ;   and loop til buffer is full

    This  routine is somewhat flawed in that it only allows  the �
input  of an even number of digits, but I think that you get  the �
idea.

    The   ability   to   do  decimal   shifts   allows   decimal �
multiplication  and  division to be done fairly  easily.   Multi-�
plication  is done similar to the way that it is done  on  paper.  �
Multiplier digits are tested from right to left and the multipli-�
cand  added  to  a product (which is zeroed  before  the  process �
starts).   At the end of each multiply step, the multiplicand  is �
shifted  left,  like the indentation of  the  successive  product �
lines when multiplying with pencil and paper (some of us old guys �
still  remember  the time before computers and  calculators  were �
readily available!).  Of course, decimal multiplication done this �
way  is quite slow (each RLD or RRD instruction takes 5 M  cycles �
and  18  T states), so if a lot of it is needed, it  is  probably �
faster  to convert to binary, multiply with a binary routine  and �
then convert the answer back to BCD.  Readers are left to  figure �
the  details  out  for themselves (it's too  long  for  inclusion �
here).   If  you  are really interested, contact  me  and  I  can �
probably supply an example.

                                   Ian Cottrell, Sysop
                                   The Information Centre RCP/M+
                                   Ottawa, ON, Canada
                                   (613) 952-2289