Skip to main content
title (division of 16 by 8 can be accomplished with a bit shift…), tags
Source Link
user3840170
  • 25.5k
  • 4
  • 101
  • 162

Is there a mistake in the 16-by-8 division code sample in "Programming“Programming the Z80"Z80” performing 16-bit by 8-bit division?

Programming the Z80 (3rd edition) has the following code sample (section 3 p.135) for division of a 16-bybit dividend by an 8-8 divisionbit divisor returning an 8 bit-bit quotient in L and an 8 bit remainder in H:

DIV168  LD     A, (DVSAD)  LOAD DIVISOR
        LD     D, A        INTO D
        LD     E, 0
        LD     HL, (DVDAD) LOAD 16-BIT DIVIDEND
        LD     B, 8        INITIALIZE COUNTER
DIV     XOR    A           CLEAR C BIT
        SBC    HL, DE      DIVIDEND - DIVISOR
        INC    HL          QUOTIENT = QUOTIENT + 1
        JP     P, NOADD    TEST IF REMAINDER
                           POSITIVE
        ADD    HL, DE      RESTORE IF NECESSARY
        DEC    HL          QUOTIENT = QUOTIENT - 1

NOADD   ADD    HL, HL      SHIFT DIVIDEND LEFT
        DJNZ   DIV         LOOP UNTIL B = 0
        RET

For 6/2 this seems to return 6/2 = 2 remainder 2. I think this is because it ends on a shift (ADD HL, HL) when it should end with a subtract/test.

Moving ADD HL, HL inside the loop just before XOR A seems to fix the program.

My question: does the original code have a bug and is my proposed fix valid? Or is there another/better way to modify the program?

Is there a mistake in the 16-by-8 division code sample in "Programming the Z80"

Programming the Z80 (3rd edition) has the following code sample (section 3 p.135) for 16-by-8 division returning an 8 bit quotient in L and an 8 bit remainder in H:

DIV168  LD     A, (DVSAD)  LOAD DIVISOR
        LD     D, A        INTO D
        LD     E, 0
        LD     HL, (DVDAD) LOAD 16-BIT DIVIDEND
        LD     B, 8        INITIALIZE COUNTER
DIV     XOR    A           CLEAR C BIT
        SBC    HL, DE      DIVIDEND - DIVISOR
        INC    HL          QUOTIENT = QUOTIENT + 1
        JP     P, NOADD    TEST IF REMAINDER
                           POSITIVE
        ADD    HL, DE      RESTORE IF NECESSARY
        DEC    HL          QUOTIENT = QUOTIENT - 1

NOADD   ADD    HL, HL      SHIFT DIVIDEND LEFT
        DJNZ   DIV         LOOP UNTIL B = 0
        RET

For 6/2 this seems to return 6/2 = 2 remainder 2. I think this is because it ends on a shift (ADD HL, HL) when it should end with a subtract/test.

Moving ADD HL, HL inside the loop just before XOR A seems to fix the program.

My question: does the original code have a bug and is my proposed fix valid? Or is there another/better way to modify the program?

Is there a mistake in the code sample in “Programming the Z80” performing 16-bit by 8-bit division?

Programming the Z80 (3rd edition) has the following code sample (section 3 p.135) for division of a 16-bit dividend by an 8-bit divisor returning an 8-bit quotient in L and an 8 bit remainder in H:

DIV168  LD     A, (DVSAD)  LOAD DIVISOR
        LD     D, A        INTO D
        LD     E, 0
        LD     HL, (DVDAD) LOAD 16-BIT DIVIDEND
        LD     B, 8        INITIALIZE COUNTER
DIV     XOR    A           CLEAR C BIT
        SBC    HL, DE      DIVIDEND - DIVISOR
        INC    HL          QUOTIENT = QUOTIENT + 1
        JP     P, NOADD    TEST IF REMAINDER
                           POSITIVE
        ADD    HL, DE      RESTORE IF NECESSARY
        DEC    HL          QUOTIENT = QUOTIENT - 1

NOADD   ADD    HL, HL      SHIFT DIVIDEND LEFT
        DJNZ   DIV         LOOP UNTIL B = 0
        RET

For 6/2 this seems to return 6/2 = 2 remainder 2. I think this is because it ends on a shift (ADD HL, HL) when it should end with a subtract/test.

Moving ADD HL, HL inside the loop just before XOR A seems to fix the program.

My question: does the original code have a bug and is my proposed fix valid? Or is there another/better way to modify the program?

added 73 characters in body
Source Link
Raffzahn
  • 236.2k
  • 23
  • 682
  • 976

Programming the Z80 (3rd edition)Programming the Z80 (3rd edition) has the following code sample (section 3 p.135) for 16-by-8 division returning an 8 bit quotient in L and an 8 bit remainder in H:

DIV168  LD     A, (DVSAD)  LOAD DIVISOR
        LD     D, A        INTO D
        LD     E, 0
        LD     HL, (DVDAD) LOAD 16-BIT DIVIDEND
        LD     B, 8        INITIALIZE COUNTER
DIV     XOR    A           CLEAR C BIT
        SBC    HL, DE      DIVIDEND - DIVISOR
        INC    HL          QUOTIENT = QUOTIENT + 1
        JP     P, NOADD    TEST IF REMAINDER
                           POSITIVE
        ADD    HL, DE      RESTORE IF NECESSARY
        DEC    HL          QUOTIENT = QUOTIENT - 1

NOADD   ADD    HL, HL      SHIFT DIVIDEND LEFT
        DJNZ   DIV         LOOP UNTIL B = 0
        RET

For 6/2 this seems to return 6/2 = 2 remainder 2. I think this is because it ends on a shift (ADD HL, HL) when it should end with a subtract/test.

Moving ADD HL, HL inside the loop just before XOR A seems to fix the program.

My question: does the original code have a bug and is my proposed fix valid? Or is there another/better way to modify the program?

Programming the Z80 (3rd edition) has the following code sample for 16-by-8 division returning an 8 bit quotient in L and an 8 bit remainder in H:

DIV168  LD     A, (DVSAD)  LOAD DIVISOR
        LD     D, A        INTO D
        LD     E, 0
        LD     HL, (DVDAD) LOAD 16-BIT DIVIDEND
        LD     B, 8        INITIALIZE COUNTER
DIV     XOR    A           CLEAR C BIT
        SBC    HL, DE      DIVIDEND - DIVISOR
        INC    HL          QUOTIENT = QUOTIENT + 1
        JP     P, NOADD    TEST IF REMAINDER
                           POSITIVE
        ADD    HL, DE      RESTORE IF NECESSARY
        DEC    HL          QUOTIENT = QUOTIENT - 1

NOADD   ADD    HL, HL      SHIFT DIVIDEND LEFT
        DJNZ   DIV         LOOP UNTIL B = 0
        RET

For 6/2 this seems to return 6/2 = 2 remainder 2. I think this is because it ends on a shift (ADD HL, HL) when it should end with a subtract/test.

Moving ADD HL, HL inside the loop just before XOR A seems to fix the program.

My question: does the original code have a bug and is my proposed fix valid? Or is there another/better way to modify the program?

Programming the Z80 (3rd edition) has the following code sample (section 3 p.135) for 16-by-8 division returning an 8 bit quotient in L and an 8 bit remainder in H:

DIV168  LD     A, (DVSAD)  LOAD DIVISOR
        LD     D, A        INTO D
        LD     E, 0
        LD     HL, (DVDAD) LOAD 16-BIT DIVIDEND
        LD     B, 8        INITIALIZE COUNTER
DIV     XOR    A           CLEAR C BIT
        SBC    HL, DE      DIVIDEND - DIVISOR
        INC    HL          QUOTIENT = QUOTIENT + 1
        JP     P, NOADD    TEST IF REMAINDER
                           POSITIVE
        ADD    HL, DE      RESTORE IF NECESSARY
        DEC    HL          QUOTIENT = QUOTIENT - 1

NOADD   ADD    HL, HL      SHIFT DIVIDEND LEFT
        DJNZ   DIV         LOOP UNTIL B = 0
        RET

For 6/2 this seems to return 6/2 = 2 remainder 2. I think this is because it ends on a shift (ADD HL, HL) when it should end with a subtract/test.

Moving ADD HL, HL inside the loop just before XOR A seems to fix the program.

My question: does the original code have a bug and is my proposed fix valid? Or is there another/better way to modify the program?

Source Link

Is there a mistake in the 16-by-8 division code sample in "Programming the Z80"

Programming the Z80 (3rd edition) has the following code sample for 16-by-8 division returning an 8 bit quotient in L and an 8 bit remainder in H:

DIV168  LD     A, (DVSAD)  LOAD DIVISOR
        LD     D, A        INTO D
        LD     E, 0
        LD     HL, (DVDAD) LOAD 16-BIT DIVIDEND
        LD     B, 8        INITIALIZE COUNTER
DIV     XOR    A           CLEAR C BIT
        SBC    HL, DE      DIVIDEND - DIVISOR
        INC    HL          QUOTIENT = QUOTIENT + 1
        JP     P, NOADD    TEST IF REMAINDER
                           POSITIVE
        ADD    HL, DE      RESTORE IF NECESSARY
        DEC    HL          QUOTIENT = QUOTIENT - 1

NOADD   ADD    HL, HL      SHIFT DIVIDEND LEFT
        DJNZ   DIV         LOOP UNTIL B = 0
        RET

For 6/2 this seems to return 6/2 = 2 remainder 2. I think this is because it ends on a shift (ADD HL, HL) when it should end with a subtract/test.

Moving ADD HL, HL inside the loop just before XOR A seems to fix the program.

My question: does the original code have a bug and is my proposed fix valid? Or is there another/better way to modify the program?