😸

Z80符号付き16ビット除算ルーチン

に公開

Z80の符号付き16ビット除算ルーチンです。ゼロ除算の場合はZ=1、それ以外の場合はZ=0を返します。
HL=HL/DE、DE=HL%DEです。
デザイン、僕。コーディング、ChatGPT。

; =================================================
; Z80 Signed 16-bit Division
; =================================================
;
; HL = HL / DE
; DE = HL % DE
;
; Z = 1 : divide by zero
; Z = 0 : normal end
;
; destroys:
;   AF, BC
; =================================================


; -------------------------------------------------
; Signed 16-bit Division Entry
; -------------------------------------------------
DIV16S_Z:
        ; ---- divide by zero check ----
        ld      A,D
        or      E
        ret     z               ; Z=1

        ; ---- save signs ----
        ld      A,H
        xor     D
        and     80h
        push    AF              ; 商の符号

        ld      A,H
        and     80h
        push    AF              ; 余りの符号(被除数)

        ; ---- HL = abs(HL) ----
        bit     7,H
        jr      z,HL_POS
        xor     A
        sub     L
        ld      L,A
        sbc     A,A
        sub     H
        ld      H,A
HL_POS:

        ; ---- DE = abs(DE) ----
        bit     7,D
        jr      z,DE_POS
        xor     A
        sub     E
        ld      E,A
        sbc     A,A
        sub     D
        ld      D,A
DE_POS:

        ; ---- unsigned division ----
        ; input : HL / DE
        ; output: HL=quotient, DE=remainder
        call    DIV16U

        ; ---- remainder sign restore ----
        pop     AF
        jr      z,REM_POS
        xor     A
        sub     E
        ld      E,A
        sbc     A,A
        sub     D
        ld      D,A
REM_POS:

        ; ---- quotient sign restore ----
        pop     AF
        jr      z,QUO_POS
        xor     A
        sub     L
        ld      L,A
        sbc     A,A
        sub     H
        ld      H,A
QUO_POS:

        or      1               ; Z=0
        ret


; -------------------------------------------------
; Unsigned 16-bit Division
; HL = HL / DE
; DE = HL % DE
; -------------------------------------------------
; input :
;   HL = dividend
;   DE = divisor (≠0)
;
; output:
;   HL = quotient
;   DE = remainder
;
; destroys:
;   AF, BC
; -------------------------------------------------

DIV16U:
        ld      BC,0            ; BC = remainder
        ld      A,16

DIV16U_LOOP:
        add     HL,HL           ; shift dividend
        rl      C
        rl      B

        ld      A,C
        sub     E
        ld      A,B
        sbc     A,D
        jr      c,DIV16U_SKIP

        ld      B,A
        ld      A,C
        sub     E
        ld      C,A
        inc     L               ; quotient bit = 1

DIV16U_SKIP:
        dec     A
        jr      nz,DIV16U_LOOP

        ld      D,B
        ld      E,C
        ret

Discussion