|
| 4.1
Les multiplications par retenues |
|
4.1.1
Multiplication de deux entiers non signés de 8 bits, résultat
sur 16 bits
 |
|
;***************************************************************
; Routine de multiplication de 2 entiers non signés, de 8 bits
; avec un résultat sur 16 bits
;
; En entrée :
; [SP – 1] <=> Multiplicande (A)
; [SP – 2] <=> Multiplicateur (B)
; [SP – 4] <=> Adresse de retour
; En sortie :
; DE <=> Produit de A par B
; Registres affectés
; DE, les registres spécialisés
; Remarques
; - Si A ou B = 0 => DE = 0 en sortie
; - [SP – 1] et [SP – 2] sont dépilés
; - Vous pouvez utiliser n’importe quel registre 16 bits en sortie
;
; - Exemple de méthode d’appel
;
; LD B, 5
; LD C, 2
; PUSH BC
; CALL MATH_MUL_SP_8x8
; .
;
MATH_MUL_SP_8x8:
EXX ; Sauvegarde des registres BC, DE, HL
EX AF, AF’ ; Sauvegarde de AF
; Récupération des paramètres
POP HL ; Sauvegarde l’adresse de retour
POP BC ; Récupération des deux paramètres
PUSH HL ; Sauvegarde l’adresse de retour
; Initialisation des registres pour le calcul
LD HL, 0 ; Valeur de retour
LD A, B ; Transfert du multiplicande dans A
; Le multiplicateur se trouve dans C
; Vérification des valeurs en entrée
OR A ; Test de A
; Si A = 0 on sort
JP z, _MATH_MUL_SP_8x8_END
LD L, A ; Sauvegarde de A pour le test de C
LD A, C ; C est transféré dans A pour le test
OR A ; Test de C via A
LD A, L ; On restore A
LD L, H ; On efface L via H
; Si A(C) = 0 on sort
JP z, _MATH_MUL_SP_8x8_END
; Début de code lié à la multiplication
LD D, L ; D est effacer par L
LD E, A ; Le multiplicande va dans E
LD H, C ; Le multiplicateur va dans H
LD B, 8 ; Traitement des 8 bits
_MATH_MUL_SP_8x8_1
; Multiplication par 2 de HL (décalage d'1 bit vers le haut)
ADD HL, HL
JR nc, _MATH_MUL_SP_8x8_2
; Remplacement du bit de débordement par le multiplicateur
ADD HL, DE
_MATH_MUL_SP_8x8_2
DJNZ _MATH_MUL_SP_8x8_1
_MATH_MUL_SP_8x8_END
PUSH HL ; Sauvegarde du résultat
EXX ; Restauration des registres courants
EX AF, AF’ ; Restauration de AF
POP DE ; Récupération du résultat dans DE (à changer éventuellement)
RET
|
4.1.2
Multiplication de deux entiers non signés de 16 par 8 bits, résultat
sur 16 bits
 |
|
;***************************************************************
; Routine de multiplication de 2 entiers non signés, de 16 par
; 8 bits, avec un résultat sur 16 bits
;
; En entrée
; [SP - 2] <=> Multiplicande, transféré dans DE
; [SP - 4] <=> Multiplicateur, transféré dans A (partie haute de [SP - 4])
; [SP – 6] <=> Adresse de retour
; En sortie :
; DE <=> Produit de DE par A (résultat sur 16 bits !)
; Registres affectés
; DE et les registres spécialisés
; Remarques
; - Si A ou DE = 0 => DE = 0 en sortie
; - [SP - 2] et [SP - 4] sont dépilés
; - Vous pouvez utiliser n’importe quel registre 16 bits en sortie
;
; - Méthode d’appel de la fonction
;
; LD DE, 6
; PUSH DE
; LD D, 2 ; D contient le multiplicateur
; PUSH DE
; CALL MATH_MUL_SP_16x8
; .
;
MATH_MUL_SP_16x8:
EXX ; Sauvegarde des registres BC, DE, HL
EX AF, AF' ; Sauvegarde de AF
; Récupération des paramètres
POP HL ; Récupération de l'adresse de retour
POP AF ; Récupération du multiplicateur
; Le multiplicateur va se retrouvé dans A
POP DE ; Récupération du multiplicande
PUSH HL ; Préservation de l'adresse de retour
; Initialisation des registres
LD HL, 0 ; Valeur de retour
; Vérification des valeurs d'entrée
OR A ; Si A = 0 on sort
JP z, _MATH_MUL_SP_16x8_END
ADC HL, DE ; Ajout de DE à HL de manière à vérifier si DE = 0
; Si DE = 0 => z = 1
JP z, _MATH_MUL_SP_16x8_END
; Début du code lié à la multiplication
LD HL, 0 ; Valeur de retour
LD B, 8 ; Traitement des 8 bits
_MATH_MUL_SP_16x8_1
; Multiplication par 2 de HL (décalage d'1 bit vers le haut)
ADD HL, HL
ADD A, A
JR nc, _MATH_MUL_SP_16x8_2
; Remplacement du bit de débordement par le multiplicateur
ADD HL, DE
_MATH_MUL_SP_16x8_2
DJNZ _MATH_MUL_SP_16x8_1
_MATH_MUL_SP_16x8_END
PUSH HL ; Sauvegarde du résultat
EXX ; Restauration des registres courants BC, DE, HL
EX AF, AF' ; Restauration de AF
POP DE ; Récupération du résultat dans DE
; (Au tout autre registre 16 bits)
RET
|
4.1.3
Multiplication de deux entiers non signés de 16 bits, résultat
sur 16 bits
 |
|
;***************************************************************
; Routine de multiplication de 2 entiers non signés de 16 bits,
; avec un résultat sur 16 bits
;
; En entrée
; [SP - 2] <=> Multiplicande, transféré dans BC
; [SP - 4] <=> Multiplicateur, transféré dans DE
; [SP - 6] <=> Adresse de retour
; En sortie
; DE <=> Produit de BC par DE (résultat sur 16 bits !)
; Registres affectés
; DE et les registres spécialisés
; Remarques
; - Si BC ou DE = 0 => DE = 0 en sortie
; -[SP - 2] et [SP - 4] sont dépilés
; - Vous pouvez utiliser n’importe quel registre 16 bits en sortie
;
; - Modèle d'appel de la fonction
;
; LD DE, 5
; PUSH DE
; LD DE, 3
; PUSH DE
; CALL MATH_MUL_SP_16x16
; .
;
MATH_MUL_SP_16x16 :
EXX ; Sauvegarde des registres BC’, DE’, HL’
EX AF, AF’ ; Sauvegarde de AF
; Récupération des paramètres
POP HL ; Récupération de l’adresse de retour
POP DE ; Récupération du multiplicateur
POP BC ; Récupération du multiplicande
PUSH HL ; Sauvegarde l'adresse de retour
; Initialisation des registres
LD HL, 0 ; Valeur par défaut pour le retour
; Vérification des valeurs en entrée
RL L ; Permet d'effacer Carry
ADC HL, BC ; Vérification que BC’ = 0
JP z, _MATH_MUL_SP_16x16_END
LD HL, 0
ADC HL, DE ; Vérification que DE’ = 0
JP z, _MATH_MUL_SP_16x16_END
; Début du code lié à la multiplication
LD HL, 0 ; Valeur de retour
LD A, B
LD B, 16
_MATH_MUL_SP_16x16_1
; Multiplication par 2 de HL’ (décalage d'1 bit vers le haut)
ADD HL, HL
SLA C ; SLA suivi d'un RLA permet de réaffecter les bits de C’
RLA ; dans A’ en cas de débordement de C’, donc de traiter
; les 16 bits du multiplicateur
JR nc, _MATH_MUL_SP_16x16_2
; Remplacement du bit de débordement par le multiplicateur
ADD HL, DE
_MATH_MUL_SP_16x16_2
DJNZ _MATH_MUL_SP_16x16_1
_MATH_MUL_SP_16x16_END
PUSH HL ; Stockage du résultat sur la pile
EXX ; Restauration des registres courants
EX AF, AF’ ; Restauration de AF
POP DE ; Récupération du résultat pour le retour via DE
; (Ou tout autre registre sur 16 bit)
RET
|
 |
4.2
Les Multiplications par sous-produits
 |
|
4.2.1
Multiplication de deux entiers non signés de 8 bits, résultat
sur 16 bits
 |
|
;***************************************************************
; Routine de multiplication de 2 entiers non signés de 8 bits
; avec un résultat sur 16 bits
;
; En entrée
; [SP - 1] <=> Multiplicateur, transféré dans A
; [SP - 2] <=> Multiplicande, transféré dans C
; [SP – 4] <=> Adresse de retour
; En sortie
; DE <=> Produit de C par A
; Registres affectés
; DE et les registres spécialisés
; Remarques
; - Si A ou C = 0 => DE = 0 en retour
; - [SP - 1] et [SP - 2] sont dépilés
; - Pour optimiser les calculs, vous pouvez vérifier que le
; multiplicateur est bien inférieur au multiplicande
; Plus le multiplicateur est petit plus l'opération est rapide
;
; - Méthode d’appel de la fonction
;
; LD D, 6
; LD E, 2
; PUSH DE
; CALL MATH_MUL_SP_8x8
; .
;
MATH_MUL_SP_8x8:
EXX ; Sauvegarde des registres BC, DE, HL
EX AF, AF' ; Sauvegarde de AF
POP HL ; Récupération de l'adresse de retour
POP BC ; Récupération des deux paramètres
PUSH HL ; Sauvegarde de l'adresse de retour
; Initialisation des registres pour le test en entrée
LD HL, 0 ; Valeur pour le retour
LD A, B ; Le multiplicateur dans A
; Vérification des valeurs en entrée
OR A ; Test de A
; Retour si A = 0
JP z, _MATH_MUL_SP_8x8_END
LD L, A ; Sauvegarde de A pour le test de C (le multiplicande)
LD A, C ; Transfert de B dans A pour le test
OR A ; Test de C via A
LD A, L ; On restore A
LD L, H ; On efface L via H
; Retour si A = 0
JP z, _MATH_MUL_SP_8x8_END
_MATH_MUL_SP_8x8_1
; Début du code lié à la multiplication
LD D, L ; Le multiplicande est dans DE pour calculer les sous-produits
LD E, C ;
_MATH_MUL_SP_8x8_2
BIT 0, A ; Vérification si le bit 0 = 0, si oui
; on ne cumule pas le sous-produit courant
JP Z, _MATH_MUL_SP_8x8_3
ADD HL, DE ; Cumule du sous-produit courant
_MATH_MUL_SP_8x8_3
EX HL, DE ; Décalage du sous-produit courant
ADD HL, HL ; de 1 bit vers le haut
EX HL, DE ;
SRL A ; Décalage du multiplicateur de 1 bit
; vers le bas
OR A ; Vérification que tous les bits du
; multiplicateur ont été traités
JP nz, _MATH_MUL_SP_8x8_2
_MATH_MUL_SP_8x8_END
PUSH HL ; Sauvegarde du résultat
EXX ; Restauration des registres BC, DE, HL
EX AF, AF' ; Restauration de AF
POP DE ; Récupération du résultat dans DE
; (Ou tout autre registre 16 bits)
RET
|
4.2.2
Multiplication de deux entiers non signés de 16 par 8 bits, résultat
sur 16 bits
 |
|
;***************************************************************
; Routine de multiplication de 2 entiers non signés, de 16 par
; 8 bits, avec un résultat sur 16 bits
;
; En entrée
; [SP - 2] <=> Multiplicande, transféré dans DE
; [SP - 4] <=> Multiplicateur, transféré dans A (partie haute de [SP – 4]
; [SP – 6] <=> Adresse de retour
; En sortie
; DE <=> Produit de DE par A (résultat sur 16 bits !)
; Registres affectés
; DE et les registres spécialisés
; Remarques
; - Si le multiplicande ou le diviseur = 0 => DE = 0 en retour
; - [SP - 2], [SP - 4] et [SP - 6] sont dépilés
; - Pour optimiser les calculs, vous pouvez vérifier que le
; multiplicateur est bien inférieur au multiplicande
;
; - Méthode d’appel de la fonction
;
; LD DE, 6
; PUSH DE
; LD D, 2 ; D contient le multiplicateur
; PUSH DE
; CALL MATH_MUL_SP_16x8
; .
;
MATH_MUL_SP_16x8:
EXX ; Sauvegarde des registres BC, DE, HL
EX AF, AF' ; Sauvegarde du registre AF
POP HL ; Récupération de l'adresse de retour
POP AF ; Récupération du multiplicateur 8 bits dans A
POP DE ; Récupération du multiplicande sur 16 bits
PUSH HL ; Sauvegarde de l'adresse de retour
LD HL, 0 ; Mise à blanc de HL pour le retour
; Vérification des valeurs en entrée
OR A ; Si A = 0 on sort
JP z, _MATH_MUL_SP_16x8_END
ADC HL, DE ; Si DE = 0 on sort
JP z, _MATH_MUL_SP_16x8_END
; Début du code lié à la multiplication
LD HL, 0
_MATH_MUL_SP_16x8_1
BIT 0, A ; Vérification si le bit 0 = 0, si oui
; on ne cumule pas le sous-produit courant
JP z, _MATH_MUL_SP_16x8_3
ADD HL, DE ; Cumule du sous-produit courant
_MATH_MUL_SP_16x8_3
EX HL, DE ; Décalage du sous-produit courant
ADD HL, HL ; de 1 bit vers le haut
EX HL, DE ;
SRL A ; Décalage du multiplicateur de 1 bit
; vers le bas
OR A ; Vérification que tous les bits du
; multiplicateur ont été traités
JP nz, _MATH_MUL_SP_16x8_1
_MATH_MUL_SP_16x8_END
PUSH HL ; Préservation du résultat
EXX ; Restauration des registres courants BC, DE, HL
EX AF, AF' ; Restauration de AF
POP DE ; Récupération du résultat dans DE
; (ou tout autre registre sur 16 bits)
RET
|
 |
| 4.3
La division par utilisation de sous-dividendes |
|
4.3.1
Division de deux entiers non signés de 8 bits, résultat sur
8 bits
 |
|
;***************************************************************
; Routine de division de 2 entiers non signés de 8 bits, avec un
; résultat sur 8 bits pour le quotient et 8 bits pour le reste
;
; En entrée
; [SP - 2] <=> Les deux paramètres le dividende (transféré dans B)
; et le diviseur (transféré dans C)
; En sortie
; D <=> Quotient
; E <=> Reste de la division entière
; Registres affectés
; DE et les registres spécialisés
; Remarques
; - Si le dividende ou le diviseur = 0 en entrée => D = 0 et E = 0 en retour
; - D et E peuvent être remplacés par n’importe quels registres 8 bits en retour
;
MATH_DIV_SP_8x8:
EXX ; Sauvegarde des registres BC, DE, HL
EX AF, AF' ; Sauvegarde de registre AF
POP HL ; Récupération des l'adresse de retour
POP DE ; Récupération des deux paramètres D et E
PUSH HL ; Préservation de l'adresse de retour
; Initialisation des registres
LD B, 8 ; Les 8 bits du dividende sont traités
XOR A, A
_MATH_DIV_SP_8x8_1
SLA D ; Décalage du bit le plus haut, du dividende dans Carry
RLA ; Récupération de Carry dans le sous-dividende (A)
; (création du sous dividende)
CP E ; Vérification si le sous-dividende est >= au diviseur.
; Si oui le quotient = + 1, sinon on traite le bit suivant, du dividende
JR c, _MATH_DIV_SP_8x8_2
INC D ; Incrémentation du quotient. Sachant que les bits de D
; sortent vers le haut (la gauche), les bits du bas vont
; servir pour stocker le quotient
SUB E ; On soustrait le diviseur du dividende
_MATH_DIV_SP_8x8_2
DJNZ _MATH_DIV_SP_8x8_1 ; Décrémentation de B de manière à
; traiter les 8 bits du dividende
LD E, A ; Récupération du reste dans E
; Le quotient se trouve dans D
PUSH DE ; Préservation du résultat dans DE
EXX ; Restauration des registres BC, DE, HL
EX AF, AF' ; Restauration du registre AF
POP DE ; Récupération du quotient et du reste dans DE
; (ou tout autre registre 16 bits)
RET
|
4.3.2
Division de deux entiers non signé de 16 par 8 bits, résultat
sur 16 bits
 |
|
;***************************************************************
; Routine de division d'un entier non signé de 16 bits par un
; entier non signé de 8 bits, avec un résultat sur 16 bits
;
; En entrée
; [SP - 2] <=> Dividende, transféré dans HL
; [SP - 4] <=> Diviseur, transféré dans B (8 bits de la partie haute de [SP - 4])
; [SP – 6] <=> Adresse de retour
; En sortie
; DE <=> Quotient (sur 16 bits)
; A <=> Reste de la division entière (8 bits)
; Registres affectés
; A, DE et les registres spécialisés
; Remarques
; - [SP - 2], [SP - 4] et [SP – 6] sont dépilés
; - Si le dividende ou le diviseur = 0 => DE = 0 et A = 0 en retour
; - DE peut être remplacé par n’importe quel registre 16 bits pour le retour
;
MATH_DIV_SP_16x8:
EXX ; Préservation des registre BC, DE, HL
EX AF, AF' ; Préservation de AF
POP DE ; Récupération de l'adresse de retour
POP BC ; Récupération du diviseur dans B
; (partie haute à l'adresse [SP - 3])
POP HL ; Récupération du dividende
PUSH DE ; Sauvegarde de l'adresse de retour
; Test des valeurs en entrée
LD A, B
OR A
JP nz, _MATH_DIV_SP_16x8_1
LD H, A
LD L, A
JP _MATH_DIV_SP_16x8_END
_MATH_DIV_SP_16x8_1
LD C, B ; Stockage du diviseur dans C
LD B, 16 ; Les 16 bits de HL (le dividende) vont être traités
XOR A, A ; On efface A pour initialiser le sous-dividende
_MATH_DIV_SP_16x8_2
SLA L ; Décalage du bit le plus haut, du dividende dans Carry
RL H
RLA ; Récupération de Carry dans le sous-dividende (A)
; (création du sous dividende)
CP C ; Vérification si le sous-dividende est supérieur ou
; égal au diviseur. Si oui le quotient = + 1, sinon on
; traite le bit suivant, du dividende
JR c, _MATH_DIV_SP_16x8_3
INC HL ; Incrémentation du quotient (sachant que tous les bits
; de HL sont décalé vers le haut (la gauche), les bits
; venant du bas vont servir pour stocker le quotient
SUB C ; On soustrait le diviseur du dividende
_MATH_DIV_SP_16x8_3
DJNZ _MATH_DIV_SP_16x8_2 ; Décrémentation de B de manière à
; traiter les 16 bits du dividende
_MATH_DIV_SP_16x8_END
PUSH HL ; Sauvegarde du quotient sur la pile, le reste se trouve dans A
EXX ; Restauration des registres BC, DE, HL
LD D, A ; Sauvegarde du reste de l'opération dans A
EX AF, AF' ; Restauration de F
LD A, D ; A contient le reste de la division entière
POP DE ; Récupération du résultat dans DE
; (ou tout autre registre 16 bits)
RET
|
4.3.3
Division de deux entiers non signé de 16 bits, résultat sur
16 bits
 |
|
;***************************************************************
; Routine de division d'un entier non signé de 16 bits par un
; entier non signé de 16 bits, avec un résultat sur 16 bits
;
;En entrée
; [SP - 2] <=> Dividende, transféré dans BC
; [SP - 4] <=> Diviseur, transféré dans DE
;En sortie
; DE <=> Quotient
; BC <=> Reste de la division entière (sur 16 bits)
;Registres affectés
; BC, DE et les registres spécialisés
; Remarques
; - [SP - 2] et [SP - 4] sont dépilés
; - Les registres DE et BC en sortie peuvent être remplacés par
; d'autres registres 16 bits
; - Si le diviseur ou le dividende = 0 => DE = 0 et BC = 0 en retour
; - DE peut être remplacé par n’importe quel registre 16 bits pour le retour
;
MATH_DIV_SP_16x16:
EXX ; Sauvegarde des registres BC, DE, HL
EX AF, AF' ; Sauvegarde de AF
POP HL ; Récupération de l'adresse de retour
POP DE ; Récupération du diviseur
POP BC ; Récupération du dividende
PUSH HL ; Préservation de l'adresse de retour
; Vérification des valeurs en entrée
LD HL, 0
ADC HL, DE ; Si DE = 0 on sort
JP nz, _MATH_DIV_SP_16x16_1
XOR A, A ; On efface A pour le retour
LD C, A ; On efface C pour le retour
JP _MATH_DIV_SP_16x16_END
_MATH_DIV_SP_16x16_1
LD HL, 0 ; Servira de sous-dividende
LD A, B ; Stockage de la partie haute du dividende dans B
LD B, 16 ; Les 16 bits de HL (le dividende) vont être traités
_MATH_DIV_SP_16x16_2
SLA C ; Décalage du bit le plus haut de la partie basse du
; dividende, dans Carry
RLA ; Récupération de Carry dans la partie haute du dividende
; Et décalage de la partie haute du dividende dans Carry
ADC HL, HL ; Récupération éventuelle de Carry et création par la
; même occasion du sous-dividende
SBC HL, DE ; On enlève le diviseur du sous-dividende, si Carry est
; allumé c'est que le sous-dividende est inférieur
JR c, _MATH_DIV_SP_16x16_3
INC C ; Incrémentation de C de manière à crée le quotient
; (Remplacement des bits du dividende par le quotient)
DJNZ _MATH_DIV_SP_16x16_2 ; Décrémentation de B de manière à
; traiter les 16 bits du dividende
JP _MATH_DIV_SP_16x16_END
_MATH_DIV_SP_16x16_3
ADD HL, DE ; Restauration du sous-dividende car celui-ci est
; inférieur au diviseur
DJNZ _MATH_DIV_SP_16x16_2 ; Décrémentation de B de manière à
; traiter les 16 bits du dividende
_MATH_DIV_SP_16x16_END
LD B, A ; Partie haute du quotient dans B
; La partie basse se trouve déjà dans C
PUSH BC ; Préservation du quotient
PUSH HL ; Préservation du reste de la division
EXX ; Restauration des registres BC, DE, HL
EX AF, AF' ; Restauration de AF
POP BC ; Récupération du reste dans BC
POP DE ; Récupération du quotient dans DE
RET
|
 |
 |