Salve a tutti!
Ho creato un piccolo programma che dovrebbe calcolare l'area di un triangolo qualsiasi dati in input base e altezza.
Ma c'è un problema: il risultato ottenuto alla fine è errato anche se secondo me i passaggi matematici per il calcolo dell'area del triangolo tradotti in assembly8086 sono corretti.
DATA SEGMENT PUBLIC
INTRO DB "CALCOLATORE AREA TRIANGOLO!",10,13,'$'
DOM1 DB "Digita il valore della base del triangolo: ",'$'
DOM2 DB "Digita il valore della alterzza del triangolo: ",'$'
RIS DB "Area del triangolo: ",'$'
CHIUSURA DB "Fine del programma",10,13,'$'
ACAPO DB 10,13,'$'
BASE DB ?
ALTEZZA DB ?
NUM DB ?
QUO DB ?
RESTO DB ?
DIECI DB 10
CONTA DB 0
DUE DB 2
DECIMALE DB ?
DATA ENDS ;FINE DEL SEGMENTO DEI DATI
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
INIZIO:
;CARICAMENTO DEI DATI
MOV AX,DATA
MOV DS,AX
MOV AX,03H ;RICHIESTA PULIZIA DELLO SCHERMO
INT 10H ;INTERRUPT CHE PERMETTE LA PULIZIA DELLO SCHERMO
STAMPA MACRO FRASE
MOV AH,09H ;RICHIESTA STAMPA DELLA STRINGA
LEA DX,FRASE ;CARICAMENTO DEI DATI
INT 21H ;INTERRUPT CHE PERMETTE LA STAMPA DI UNA FRASE
ENDM ;FINE DELLA MACRO PER LA STAMPA DELLE STRINGHE
STAMPA INTRO ;RICHIAMO LA MACRO PER STAMPARE LA FRASE
STAMPA ACAPO ;RICHIAMO LA MACRO PER STAMPARE LA FRASE
STAMPA DOM1 ;RICHIAMO LA MACRO PER STAMPARE LA FRASE
CALL INPUT ;RICHIAMO LA PROCEDURA PER L'INPUT DEL NUMERO
MOV BASE,BL
STAMPA ACAPO ;RICHIAMO LA MACRO PER STAMPARE LA FRASE
STAMPA DOM2 ;RICHIAMO LA MACRO PER STAMPARE LA FRASE
CALL INPUT ;RICHIAMO LA PROCEDURA PER L'INPUT DEL NUMERO
MOV ALTEZZA,BL
CALL CALCOLO_AREA ;RICHIAMO LA PROCEDURA PER IL CALCOLO DELL'AREA DEL TRIANGOLO
STAMPA ACAPO ;RICHIAMO LA MACRO PER STAMPARE LA FRASE
STAMPA RIS ;RICHIAMO LA MACRO PER STAMPARE LA FRASE
CALL STAMPARIS ;RICHIAMO LA PROCEDURA PER ESEGUIRE LA STAMPA DEL RISULTATO
MOV CH,00H
MOV CL,QUO
CALL STAMPARIS
CMP RESTO,00H
JNG FINEPROGRAMMA
MOV AH,02H
MOV DL,'.'
INT 21H
MOV CH,00H
MOV CL,DECIMALE
CALL STAMPARIS
FINEPROGRAMMA:
STAMPA ACAPO
STAMPA CHIUSURA
;RESTITUISCO IL CONTROLLO AL DOS
MOV AH,4CH
INT 21H
;PROCEDURE
INPUT PROC NEAR
MOV BX,0 ;AZZERO IL REGISTRO BX
MOV CONTA,0
CICLO:
MOV AH,01H ;RICHIESTA INPUT DI UN CARATTERE
INT 21H ;INTERRUPT CHE PERMETTE INPUT DI UN CARATTERE
CMP AL,0DH ;COMPARE FRA AL E IL VALORE DELLA TABELLA ASCII DEL TASTO INVIO
JE FINE ;SE IL TASTO PREMUTO è INVIO è FINITO L'INPUT
ADD CONTA,1
CMP CONTA,2
JE FINE
MOV AH,00H ;AZZERO LA PARTE ALTA DI AX
PUSH AX ;METTO AX NELLO STACK
MOV AX,BX
MUL DIECI ;MOLTIPLICO AX PER 10
MOV BX,AX
POP AX
SUB AL,30H
MOV AH,0
ADD BX,AX
JMP CICLO ;FINE DEL CICLO
FINE:
RET ;RESTITUISCO IL CONTROLLO AL MAIN
ENDP ;FINE DELLA PROCEDURA
CALCOLO_AREA PROC NEAR
;AREA DEL TRIANGOLO = (BASE * ALTEZZA) / 2
MOV AH,00H ;AZZERO LA PARTE ALTA DI AX
MOV AL,BASE ;METTO IN AL LA BASE
MUL ALTEZZA ;MOLTIPLICO AX PER L'ALTEZZA
DIV DUE ;DIVIDO IL REGISTRO AX PER 2 --> QUOZIENTE IN AL E IL RESTO IN AH
MOV QUO,AL ;SALVO IL QUOZIENTE NELLA RISPETTIVA VARIABILE
CMP AH,00H ;COMPARE FRA IL RESTO E AH
JE FINE1;SE IL RESTO è UGUALE A ZERO(NON ESISTE) SALTO ALLA FINE DELLA PROCEDURA
MOV RESTO,AH ;SALVO IL RESTO NELLA RISPETTIVA VARIABILE
CMP AH,9 ;COMPARE FRA IL RESTO E 9
JG CALCOLODECIM ;SE IL RESTO è PIù GRANDE DI 9 SALTA A "CALCOLODECIM"
MOV AL,RESTO ;METTO IN AL IL RESTO
MOV AH,00H ;AZZERO LA PARTE ALTA DI AX
MUL DIECI ;MOLTIPLICO PER 10 IL REGISTRO AX
MOV RESTO,AL ;SALVO IL RISULTATO NELLA VARIABILE RESTO
CALCOLODECIM:
MOV AH,00H ;AZZERO LA PARTE ALTA DI AX
MOV AL,RESTO ;METTO IN AL IL RESTO
DIV DUE ;DIVIDO IL REGISTRO AX PER 2 --> QUOZIENTE IN AL E IL RESTO IN AH
MOV DECIMALE,AL ;SALVO LA PARTE DECIMALE
FINE1:
RET ;RESTITUISCO IL CONTROLLO AL DOS
ENDP ;FINE DELLA PROCEDURA PER IL CALCOLODELL'AREA DEL TRIANGOLO
STAMPARIS PROC NEAR
;AZZERAMENTO DEI DUE REGISTRI
XOR AX,AX
MOV CONTA,0
MOV AX,CX
MOV BL,DIECI
CICLODIV: ;inizio del ciclo
CMP AX,9 ;confronto il registro AX con 9
JG DIVISIONE ;se il numero è maggiore di 9 significa che è almeno a due cifre quindi bisogna dividere per 10
JLE NODIVISIONE ;se il numero è minore o uguale a nove si rappresenta di sicuro in un byte e salto il ciclo
DIVISIONE:
MOV DH,00H
MOV DL,00H
;nel registro AX c'è il numero che devo dividere
MOV BH,00H
DIV BX ;divido per 10 che è contenuto in BX --> AX QUOZIENTE E DX RESTO!!!
PUSH DX ;metto nello stack il resto della divisione che è contenuto in DX
;non tocco il registro ax in quanto contiene già il probabile successivo numero che deve dividere
ADD CONTA,1 ;incremento la variabile contatore
JMP CICLODIV ;salto incondizionato a "CICLODIV" così da ripetere il ciclo
NODIVISIONE:
MOV NUM,AL
CMP CONTA,0
JZ STAMPA1
JNZ STAMPA2
STAMPA1:
MOV AH,02H ;richiesta per la stampa di un singolo carattere
MOV DL,NUM ;sposto in DL il carattere
ADD DL,30H ;conversione
INT 21H ;interrupt che permette di stampa il carattere
JMP EXIT ;salto incodizionato alla fine del programma
STAMPA2:
MOV AH,02H ;richiesta per la stampa di un singolo carattere
MOV DL,NUM ;sposto in DL il carattere
ADD DL,30H ;conversione
INT 21H ;interrupt che permette di stampa il carattere
XOR AX,AX ;azzero il registro AX per sicurezza
XOR BX,BX ;azzero il registro BX per sicurezza
CICLOSTAMPA: ;ciclo per la stampa di un numero a più cifre
POP BX ;tiro fuori il numero dallo stack in DX
MOV AH,02H ;richiesta per la stampa di un singolo carattere
MOV DL,BL
ADD DL,30H
INT 21H
SUB CONTA,1 ;decremento conta di 1
CMP CONTA,0
JZ EXIT ;se la variabile conta è uguale a zero allora ha finito i numeri e quindi esco dal ciclo
JNZ CICLOSTAMPA ;se la variabile non è zero allora ricomincio il ciclo per la stampa
EXIT:
RET
ENDP ;FINE DELLA PROCEDURA PER LA STAMPA DEL RISULTATO
CODE ENDS ;FINE DEL SEGMENTO DEL CODICE
END INIZIO ;CHIUSURA ETICHETTA CHE INDICA L'INIZIO DEL PROGRAMMA
Se qualcuno mi potrebbe aiutare a trovare l'errore lo ringrazio in anticipo