Assembly 8085: moltiplicare due numeri firmati a 8 bit (algoritmo corretto)
Il codice originale era errato (usava `SBB`/`ADD` in un ciclo senza corretta gestione del moltiplicando/moltiplicatore). Di seguito una routine standard funzionante in assembly 8085 per la moltiplicazione firmata 8-bit usando l'algoritmo add-shift (l'algoritmo di Booth è eccessivo per 8 bit). Il risultato è a 16 bit in HL.
; 8085 Moltiplicazione firmata 8-bit (Metodo Add-Shift) ; Input: Moltiplicando in memoria 2000H, Moltiplicatore in 2001H (entrambi firmati 8-bit) ; Output: Prodotto firmato 16-bit in HL (H=alto, L=basso) ; Registri usati: A, B, C, D, E, H, L, PSW ; Distrugge: A, B, C, D, E ORG 1000H ; Indirizzo di inizio esempio LXI H, 2000H ; HL punta al moltiplicando MOV D, M ; D = Moltiplicando (firmato) INX H MOV E, M ; E = Moltiplicatore (firmato) CALL MUL8S ; Chiama moltiplicazione firmata SHLD 2002H ; Memorizza risultato 16-bit a 2002H (L=basso, H=alto) HLT ;---------------------------------------------------------- ; Sottoruttina Moltiplicazione 8x8 firmata → 16 ; Input: D = Moltiplicando, E = Moltiplicatore (entrambi complemento a 2) ; Output: HL = Prodotto firmato 16-bit ; Usa: A, B, C (contatore), D, E, H, L ;---------------------------------------------------------- MUL8S: MOV A, D ; Ottieni moltiplicando ORA A ; Controlla segno JM NEG_MCAND ; Se negativo, vai a complemento a 2 MOV A, E ; Controlla segno moltiplicatore ORA A JM NEG_MPLIER ; Entrambi positivi: usa moltiplicazione senza segno JMP MUL_UNSIGNED NEG_MCAND: MOV A, D CMA ; Complemento a 1 ADI 01H ; Complemento a 2 (valore assoluto) MOV D, A ; D = |Moltiplicando| MOV A, E ORA A JM BOTH_NEG ; Moltiplicatore anche negativo? ; Moltiplicando neg, Moltiplicatore pos CALL MUL_UNSIGNED ; Moltiplica |MCAND| × MPLIER ; Risultato in HL è negativo → complemento a 2 16-bit MOV A, H CMA MOV H, A MOV A, L CMA ADI 01H MOV L, A ; Propaga riporto su H se L va in overflow JNC MUL_EXIT INR H JMP MUL_EXIT NEG_MPLIER: MOV A, E CMA ADI 01H MOV E, A ; E = |Moltiplicatore| ; Moltiplicando pos, Moltiplicatore neg CALL MUL_UNSIGNED ; Moltiplica MCAND × |MPLIER| ; Negazione risultato 16-bit (come sopra) MOV A, H CMA MOV H, A MOV A, L CMA ADI 01H MOV L, A JNC MUL_EXIT INR H JMP MUL_EXIT BOTH_NEG: MOV A, E CMA ADI 01H MOV E, A ; E = |Moltiplicatore| CALL MUL_UNSIGNED ; Moltiplica |MCAND| × |MPLIER| ; Risultato positivo (neg × neg = pos) → fatto JMP MUL_EXIT ;---------------------------------------------------------- ; Moltiplicazione senza segno 8x8 → 16 (Add-Shift) ; Input: D = Moltiplicando, E = Moltiplicatore (entrambi positivi) ; Output: HL = Prodotto ;---------------------------------------------------------- MUL_UNSIGNED_CORRECT: MVI H, 00H MVI L, 00H MVI C, 08H MOV B, D ; B = Moltiplicando (8-bit), D libero MUL_LOOP2: DAD H ; HL = HL * 2 (shift sinistra) MOV A, E RAL ; Moltiplicatore MSB → Carry (shift sinistra) MOV E, A JNC NO_ADD2 MOV A, L ADD B MOV L, A MOV A, H ACI 00H MOV H, A NO_ADD2: DCR C JNZ MUL_LOOP2 RET MUL_EXIT: RET END
Come funziona
- Gestione segni: Converte gli operandi in positivi, chiama la moltiplicazione senza segno, poi nega il risultato 16-bit se esattamente un operando era negativo.
- Moltiplicazione senza segno (MUL_UNSIGNED_CORRECT): Classico shift-and-add. HL accumula il prodotto. Moltiplicatore in E shiftato a sinistra (MSB prima) o a destra (LSB prima)—qui shift a sinistra con `RAL`/`DAD H` è efficiente.
- Negazione 16-bit: `CMA`/`ADI 1` su L poi H con propagazione riporto.
Esempio
2000H = 0AH (10), 2001H = 05H (5) → Chiama MUL8S → 2002H = 0032H (50 decimale).
2000H = F6H (-10), 2001H = 05H (5) → Risultato FFCEH (-50).
Note
- L'8085 non ha istruzione di moltiplicazione. Questa sottoruttina richiede ~200 cicli.
- Per 8-bit × 8-bit → 16-bit, il risultato sta sempre in HL.
- Assicurati spazio nello stack per CALL (2 byte).
- Usa `DAD H` (HL = HL+HL) per shift sinistra 16-bit veloce.
Questa è un'implementazione standard, pronta per colloqui.