mathassemblyz80

Z80 division algorithm not functioning properly


I am attempting to run the following code:

HLDIVC: 
    LD B,16
D0: XOR A
    ADD HL,HL
    RLA
    CP C
    JR C, D1
    INC L
    SUB C
    DJNZ D0
D1: RET

It's an adaptation of the original code: (found here)

HL_Div_C:
;Inputs:
;     HL is the numerator
;     C is the denominator
;Outputs:
;     A is the remainder
;     B is 0
;     C is not changed
;     DE is not changed
;     HL is the quotient
;
       ld b,16
       xor a
         add hl,hl
         rla
         cp c
         jr c,$+4
           inc l
           sub c
         djnz $-7
       ret

On an old pocket computer I have. I had to edit the code a little bit, namely because it would seem the assembler on this pocket computer simply does not support the "jr c,$+4" syntax and rather must use labels or absolute addresses. It would seem this may be causing issues, however, because the algorithm does not seem to be working properly. I am calling the function with the following code:

ORG O100H
LD HL,20
LD C,10
CALL REGOUT; Display all register values
CALL HLDIVC
CALL REGOUT
RET

With this I am trying to divide 20 by 10, so after calling the function the correct value in HL should be 2, and the value in A (The remainder) should be 0, from my understanding. This is not the case, however. Before running the HLDIVC program, these are the register values:

| PC = 0107 | AF = 00 44 |
| SP = 7FE8 | BC = 00 0A |    
| IX = 7C06 | DE = 00 14 |    
| IY = 7C0C | HL = 00 14 |

(All values are hexadecimal)

After running the program, these are the register values:

| PC = 010D | AF = 00 9B | <- A is correct
| SP = 7FE8 | BC = 10 0A | <- B is supposed to be 0
| IX = 7C06 | DE = 00 14 | <- DE is correct
| IY = 7C0C | HL = 00 14 | <- HL should be 2(?)

What's going on? Any help would be much appreciated, thank you for your time.


Solution

  • The problem with your code is that $+4 and $-7 are both referring to byte counts, not instruction counts, and the JR instruction is 2 bytes. The indentation gives you a clue. You need to move your labels:

    HLDIVC: 
        LD B,16
        XOR A
    D0: ADD HL,HL
        RLA
        CP C
        JR C, D1
        INC L
        SUB C
    D1: DJNZ D0
        RET