-mike pearce
>Does anyone have any z80 assembly code for unsigned multiplication?
>preferably 8 bit * b bit, but 16 * 16 would also be fine.
>Additionally, if you have a signed division routine, i would also be
>interested. please send it to my email in addition to this list since
>i have a poor news server.
There was a very cute trick for unsigned 8x8 multiply on 8080/z80 cpus.
Its been a really really long time since I've done this, so bear with
me.
Its three instructions in a row, repeated 8 times. One input is in A,
the other in L(? or was it in H ?)
the sequence goes -something- like
rept 8
ADD A,A
ADC L,A
ADC H,0
endm
only I don't think thats it exactly. The general idea is bits are
shifting out of A into carry, and HL is accumulating the results.
Anyways, 24 instructions later, you get your results.
Divide was MUCH harder.
-jrp
----------------------------------------------------------------------
This posting has a invalid email address to discourage bulk emailers
Due to the ever increasing volumes of spam, I do not mix mail and news
----------------------------------------------------------------------
Below are two routines for unsigned 16x16 multiply and divide. Signed
operations can use these with some wrappers to do the accounting for
the sign bits. These public domain routines will also work on the 8080
and 8085 (no Z80 specific instructions). Note that there is no error
checking for overflow, and that arguments are passed on the stack.
============================= cut here ================================
_div16u
; set up
pop hl
pop bc ; divisor to bc
ex (sp),hl ; dividend to hl
ex de,hl ; dividend to de
; initialize
ld hl,17 ; init loop counter to N + 1
push hl
ld l,h ; init quotient
push hl
; decrement counter
div_top
div_shift_ct equ 4
IF 1
push hl ; 12 (debugging comments?)
ld hl,div_shift_ct ; 10
add hl,sp ; 10
dec (hl) ; 10
pop hl ; 10 --> 52
ELSE
inc sp ; 6
ex (sp),hl ; 16
dec h ; 4
ex (sp),hl ; 16
dec sp ; 6 --> 48
ENDI
jp z,finish
; update quotient
ex (sp),hl ; get quotient
add hl,hl ; update quotient
ex (sp),hl ; and put it back
; rotate dividend into partial dividend
add hl,hl ; shift pd
ex de,hl ; get dividend
add hl,hl ; shift dividend
ex de,hl ; get back pd
jp nc,skip_03
inc hl ; "rotate" carry bit in
skip_03
; compare pd and divisor -- subtract divisor from pd if pd > divisor
ld a,h
cp b
jp c,div_top
jp nz,div_top ; not greater or equal so skip
; compare low bytes
ld a,l
cp c
jp c,div_top
; do subtraction
ld a,l ; get low byte
sub c
ld l,a ; save result
ld a,h ; get high byte
sbc a,b
ld h,a ; save result
; update quotient
ex (sp),hl
inc hl
ex (sp),hl
jp div_top
finish
pop bc ; quotient in bc, remainder in hl
inc sp
inc sp
ret
; ******************************************************************
; unsigned _mul16( int, int );
; returns hl
_mul16u
; initialize
pop hl
pop bc
ex (sp),hl
ex de,hl
ld hl,0
ld a,c
ld c,8
; do lower half
_lower_half rra
jp nc,_Lfore
add hl,de
_LL ex de,hl
add hl,hl ; shift
ex de,hl
dec c
jp nz,_lower_half
; do upper half
ld a,b
ld c,8
_upper_half rra
jp nc,_Lfore
add hl,de
_LL ex de,hl
add hl,hl ; shift
ex de,hl
dec c
jp nz,_upper_half
ret