Revenir au plan du site


Multiplication en assembleur Z80


Le Z80 est un processeur 8 bits, il n'est pas capable de réaliser nativement des divisions ou des multiplications. Voici une compilation de routines de multiplications (wikiti, Z80 heaven, grauw, cpcwiki)


8 x 8 multiplication non signée => HL
multiply_h_e
ld d,0
sla h
sbc a
and e
ld l,a
ld b,7
.loop
add hl,hl
jr nc,$+3 ; si le bit est présent, ajouter la puissance
add hl,de
djnz .loop
ret

Version déroulée plus rapide :
multiply_h_e
ld d,0
ld l,d

sla h ; injecter le premier bit
jr nc,$+3
ld l,e

repeat 6
  add hl,hl
  jr nc,$+3 ; si le bit est présent, ajouter la puissance
  add hl,de
rend

add hl,hl
ret nc
add hl,de
ret

16 x 8 multiplication non signée => A:HL
multiply_de_a
ld bc,#700 ; B=7 init C=0
ld h,c
ld l,c

add a ; première itération optimisée
jr nc,.loop
ld h,d
ld l,e

.loop
add hl,hl
rla
jr nc,.skip
add hl,de
adc c ; comme C vaut zéro, ici on propage simplement la retenue dans A
.skip
djnz .loop
ret

Version déroulée plus rapide :
multiply_de_a
ld c,0
ld h,c
ld l,c

add a ; première itération optimisée
jr nc,.loop
ld h,d
ld l,e

repeat 6
  add hl,hl
  rla
  jr nc,@skip ; le @ pour un label local dans une boucle REPEAT
  add hl,de
  adc c ; comme C vaut zéro, ici on propage simplement la retenue dans A
  @skip
rend
; dernière itération
add hl,hl
rla
ret nc
add hl,de
adc c
ret

16 x 16 multiplication non signée => A:HL
multiply_de_bc
ld hl,0
; première itération
sla e
rl d
jr nc,.skipFirst
ld h,b
ld l,c
.skipFirst

ld a,15
.loop
add hl,hl
rl e
rl d
jr nc,.skipNext
add hl,bc
jr nc,.skipNext
inc de
.skipNext
dec a
jr nz,.loop
ret

Je vous laisse dérouler hein ;)

16 x 16 multiplication signée => DE:HL
multiply_de_bc ; résultat dans DE:HL
xor a
ld h,a : ld l,a ; HL = A = 0

bit 7,d
jr z,muldpos
sbc hl,bc
muldpos

or b
jp p,mulbpos
sbc hl,de
mulbpos

ld a,16
.loop
add hl,hl
rl e
rl d
jr nc,mul0bit
add hl,bc
jr nc,mul0bit
inc de
mul0bit
dec a
jr nz,.loop
ret