TITLE - PROGETTO DI CALCOLATORI ELETTRONICI A DSEG SEGMENT PARA PUBLIC 'DATA' ;************************; ;* COSTANTI *; ;************************; PAGINA EQU 00h LF EQU 0Ah CR EQU 0Dh UGUALE EQU 61 ESPRES_MAX EQU 70 NUM_LUNG EQU 5 HT EQU 09h ;************************; ;* VARIABILI *; ;************************; TITOLO DB 'CORSO di CALCOLATORI ELETTRONICI A$' SOTTOTITOLO DB 'CALCOLATORE di ESPRESSIONI LOGICHE HEX$' AUTORI DB 'di Longari Michele e Zoni Luca$' ISTR_INS DB CR,HT,'PREGO INSERIRE ESPRESSIONE NEL FORMATO XXXXoXXXXo...oXXXX=',LF,CR,'$' ISTR_INS2 DB CR,HT,'(dove ''X'' indica una cifra esadecimale e ''o'' un operatore)',LF,CR,'$' ISTR_AVANTI DB CR,HT,'PREMERE UN TASTO QUALSIASI PER PROSEGUIRE OPPURE ESC PER USCIRE',LF,CR,'$' A_CAPO DB CR, LF, '$' RICH_ESPRES DB 'Immettere espressione logica esadecimale: $' ISTR_RISULT DB 'Risultato dell''espressione logica immessa: $' ESPRES_LUNG DB ESPRES_MAX ESPRESSIONE DB ESPRES_MAX DUP(?) NUM_ASCII DB NUM_LUNG DUP(?) OPERANDO DW 00H RISULTATO DW 00H POS_ESPR DW 00H POS_NUM DW 00H DSEG ENDS ;*******************; ;* CODICE *; ;*******************; STACKM SEGMENT PARA STACK 'STACK' ;Viene allocata una zona di DB 64 DUP('12345678') ;memoria per lo Stack: in STACKM ENDS ;tutto 64*8 bytes. ASSUME CS:CSEG,DS:DSEG,SS:STACKM CSEG SEGMENT PARA PUBLIC 'CODE' ;********************************************************************************; ;* MAIN: DOPO LA CHIAMATA DELLA PROCEDURA D'INIZIALIZZAZIONE STAMPA *; ;* E GESTISCE IL CALCOLO DELL'ESPRESSIONE LOGICA *; ;********************************************************************************; MAIN PROC FAR PUSH DS ;Istruzioni da lanciare SEMPRE MOV AX,00h ;al principio dei programmi! PUSH AX CALL INIZIALIZZAZIONE CICLO_PRINCIPALE: CALL STAMPA_ISTR MOV AH,07H INT 21H ;funzione DOS: lettura da tastiera senza echo CMP AL,1Bh JE ESCI JMP IMMISSIONE JMP CICLO_PRINCIPALE IMMISSIONE: CALL INSERIMENTO CALL CALCOLA_RISULTATO CALL STAMPA_RISULTATO MOV AH,07H INT 21H ;funzione DOS: lettura da tastiera senza echo CMP AL,1Bh JE ESCI JMP IMMISSIONE ESCI: RET ;ritorno al sistema operativo MAIN ENDP ;********************************************************************************; ;* PROCEDURA STAMPA_ISTR: STAMPA LA PAGINA INIZIALE CON LE ISTRUZIONI *; ;********************************************************************************; STAMPA_ISTR PROC NEAR CALL CLR_SCR MOV DX,0900h ;imposta riga (DH) e colonna (DL) CALL SPOSTA_CURSORE ;muove il cursore nella posizione scelta MOV DX,OFFSET ISTR_INS ;sceglie la stringa (DS:DX) CALL STAMPA_STRINGA ; e la stampa MOV DX,OFFSET ISTR_INS2 ;sceglie la stringa (DS:DX) CALL STAMPA_STRINGA ; e la stampa MOV DX,OFFSET A_CAPO ;sceglie la stringa (DS:DX) CALL STAMPA_STRINGA ; e la stampa MOV DX,OFFSET ISTR_AVANTI ;sceglie la stringa (DS:DX) CALL STAMPA_STRINGA ; e la stampa RET STAMPA_ISTR ENDP ;****************************************************************************************************; ;* PROCEDURA INIZIALIZZAZIONE: INIZIALIZZA IL SEGMENTO DEI DATI E SETTA LA MODALITA' VIDEO *; ;****************************************************************************************************; INIZIALIZZAZIONE PROC NEAR MOV AX,DSEG ;inizializzazione segmento dati MOV DS,AX ;tramite il registro AX. MOV AX,3 ;servizio BIOS 'set video mode': INT 10h ;modo testo 80x25, colori RET ;ritorno alla procedura chiamante INIZIALIZZAZIONE ENDP ;********************************************************************************************************; ;* PROCEDURA SPOSTA_CURSORE: POSIZIONA IL CURSORE IN UNA DETERMINATA POSIZIONE DEL MONITOR, *; ;* INDICATA DALLE COORDINATE DH,DL *; ;********************************************************************************************************; SPOSTA_CURSORE PROC NEAR MOV BH,PAGINA ;Pagina video attivata. MOV AH,02h ;Servizio BIOS set cursor INT 10h ;Position RET ;Ritorno alla procedura chiamante SPOSTA_CURSORE ENDP ;*******************************************************************; ;* PROCEDURA INSERIMENTO: ...DI UN'ESPRESSIONE LOGICA HEX *; ;*******************************************************************; INSERIMENTO PROC NEAR CALL CLR_SCR CALL LEGGI_ESPRES RET INSERIMENTO ENDP ;************************************************************************************************; ;* PROCEDURA STAMPA_STRINGA: STAMPA A MONITOR UNA GENERICA STRINGA PUNTATA DA DS:DX *; ;************************************************************************************************; STAMPA_STRINGA PROC NEAR MOV AH,09h ;Servizio DOS print string; la INT 21h ;stringa e' puntata da DS:DX RET ;ritorno alla procedura chiamante STAMPA_STRINGA ENDP ;****************************************************************************************; ;* PROCEDURA CLR_SCR: RIPRISTINA IL MONITOR ATTRAVERSO IL SERVIZIO BIOS 10H *; ;****************************************************************************************; CLR_SCR PROC NEAR MOV AX,0600H ;AH=06H specifica il servizio "SCROLL WINDOW UP" MOV BX,0700H ;mentre AL=00H indica che verra' cancellato tutto il video MOV CX,0000H ;coordinate di partenza MOV DX,184FH ;coordinate di arrivo INT 10H ;servizio BIOS "VIDEO AND SCREEN SERVICES" CALL STAMPA_TITOLO RET CLR_SCR ENDP ;********************************************************************************; ;* PROCEDURA STAMPA_TITOLO: STAMPA A MONITOR IL TITOLO DEL PROGRAMMA *; ;********************************************************************************; STAMPA_TITOLO PROC NEAR MOV DX,0315h ;imposta riga (DH) e colonna (DL) CALL SPOSTA_CURSORE ;muove il cursore nella pos scelta MOV DX,OFFSET TITOLO ;sceglie la stringa (DS:DX) CALL STAMPA_STRINGA ;e la stampa MOV DX,0413h ;imposta riga (DH) e colonna (DL) CALL SPOSTA_CURSORE ;muove il cursore nella pos scelta MOV DX,OFFSET SOTTOTITOLO ;sceglie la stringa (DS:DX) CALL STAMPA_STRINGA ;e la stampa MOV DX,0517h ;imposta riga (DH) e colonna (DL) CALL SPOSTA_CURSORE ;muove il cursore nella pos scelta MOV DX,OFFSET AUTORI ;sceglie la stringa (DS:DX) CALL STAMPA_STRINGA ;e la stampa RET ;ritorno alla procedura chiamante STAMPA_TITOLO ENDP ;*************************************************************************************************************************; ;* PROCEDURA LEGGI_ESPRES: LEGGE UNA NUOVA ESPRESSIONE DALL'UTENTE *; ;* *; ;* EFFETTUA CONTROLLI SULLA LUNGHEZZA DELL'ESPRESSIONE E SULLA CORRETTEZZA DEI CARATTERI INSERITI. *; ;* PONE IL RISULTATO IN ESPRESSIONE. *; ;*************************************************************************************************************************; LEGGI_ESPRES PROC NEAR MOV DX,0800H CALL SPOSTA_CURSORE MOV DX,OFFSET RICH_ESPRES ;Stampa una stringa di richiesta inserimento espressione CALL STAMPA_STRINGA MOV DX,OFFSET A_CAPO ;Stampa una riga vuota CALL STAMPA_STRINGA MOV DL,[ESPRES_LUNG] ;Pone in DL il numero massimo di caratteri ammessi XOR DH,DH ;azzero DH MOV SI,00H ;inizializzo SI a 0 MOV POS_ESPR,00H ;inizializzo POS_ESPR a 0 Attendi_Car: MOV AH,07h ;servizio BIOS 'READ KEYBOARD CHAR WITHOUT ECO' INT 21h ;pone in AL il risultato CMP AL,08H ;se e' stato premuto il tasto BACKSPACE JE Serv_BkSp ;lo gestico all'interno della label Serv_BkSp CMP POS_ESPR,04H ;Se POS_ESPR=4 aspetto un operatore JNZ Attendi_Num ;Se no aspetto un numero CMP AL,UGUALE ;se viene premuto '=' vado alla label Fine JE Fine_Espr CMP SI,DX ;controllo se ho raggiunto il numero massimo di caratteri JE Attendi_Car ;se sì chiedo in ingresso un nuovo carattere fino a quando ;non viene premunto '=' o BACKSPACE CMP AL,'+' ;se il carattere e' un operando corretto lo inserisco JZ Carat_OK CMP AL,'*' JZ Carat_OK CMP AL,'!' JZ Carat_OK JMP Attendi_Car Attendi_Num: CMP AL,'0' ;se il carattere e' compreso tra 0 e 9 lo inserisco JB Attendi_Car CMP AL,'9' JBE Carat_OK AND AL,0DFH ;rende maiuscole le lettere inserite in input CMP AL,'A' ;se il carattere e' un lettera compresa tra 'A' e 'F' lo inserisco JB Attendi_Car CMP AL,'F' JG Attendi_Car Carat_OK: MOV ESPRESSIONE[SI],AL ;salva il carattere immesso nella posizione di INC SI ;ESPRESSIONE puntata da SI e la incrementa INC POS_ESPR MOV AH,0Eh ;servizio BIOS 'Write char in TTY' INT 10h CMP POS_ESPR,05H JNZ Avanti1 MOV POS_ESPR,00H Avanti1: JMP Attendi_Car Fine_Espr: MOV ESPRESSIONE[SI],'$' ;e' stato premuto '=', quindi inserisco il carattere di RET ;fine stringa e ritorno alla procedura chiamante Serv_BkSp: CMP SI,00H ;se il BACKSPACE e' il primo carattere inserito lo ignoro JE Attendi_Car ;e richiedo un nuovo carattere MOV AH,0EH ;e torno indietro nello schermo di una INT 10H ;posizione MOV AL,' ' ;per poi stampare uno spazio INT 10H MOV AL,08H ;torno quindi nuovamente indietro di una posizione nello schermo INT 10H DEC SI ;decremento il numero di caratteri inseriti CMP POS_ESPR,00H JNZ Avanti2 MOV POS_ESPR,05H Avanti2: DEC POS_ESPR JMP Attendi_Car LEGGI_ESPRES ENDP ;----------------------------; ; PROCEDURA DI CALCOLO ; ;----------------------------; CALCOLA_RISULTATO PROC NEAR MOV RISULTATO,00H ;Azzero il risultato MOV POS_ESPR,04H ;Xchè per i primi 4 valori non mi serve MOV POS_NUM,00H ;Azzero POS_NUM MOV SI,00H CMP ESPRESSIONE[SI],'$' ;Se sono a fine ESPRESSIONE JNZ Ciclo_Num1 MOV NUM_ASCII[SI],'$' ;Nemmeno un numero inserito RET Ciclo_Num1: MOV AL,ESPRESSIONE[SI] ;Prendo il valore da ESPRESSIONE MOV NUM_ASCII[SI],AL ;Metto l'elemento in NUM_ASCII INC SI CMP SI,4 JB Ciclo_Num1 MOV NUM_ASCII[SI],'$' CALL ASC2HEX ;Conversione numero ASCII in hex, risultato in AX MOV RISULTATO,AX ;In RISULTATO ci metto il primo numero Ciclo_Calcola: MOV SI,WORD PTR POS_ESPR CMP ESPRESSIONE[SI],'$' ;Se sono a fine ESPRESSIONE JZ Fine_Calcolo ;Ho finito il calcolo MOV AL,ESPRESSIONE[SI] MOV AH,00H ;Azzero la parte alta di A MOV OPERANDO,AX ;In OPERANDO ho l'operando INC POS_ESPR MOV POS_NUM,00H ;Azzero POS_NUM Ciclo_Num: MOV SI,WORD PTR POS_ESPR ;Metto in SI il valore di POS_ESPR MOV AL,ESPRESSIONE[SI] ;Prendo il valore da ESPRESSIONE MOV SI,WORD PTR POS_NUM ;Metto in SI il valore di POS_NUM MOV NUM_ASCII[SI],AL ;Metto l'elemento in NUM_ASCII INC POS_ESPR INC POS_NUM CMP POS_NUM,4 JB Ciclo_Num ;Adesso in NUM_ASCII ho un numero INC SI MOV NUM_ASCII[SI],'$' CALL ASC2HEX ;Conversione numero ASCII in hex, risultato in AX CMP OPERANDO,'+' JZ Op_Or CMP OPERANDO,'*' JZ Op_And XOR AX,RISULTATO JMP Risult Op_Or: OR AX,RISULTATO JMP Risult Op_And: AND AX,RISULTATO JMP Risult Risult: MOV RISULTATO,AX JMP Ciclo_Calcola Fine_Calcolo: MOV AX,RISULTATO CALL HEX2ASC ;Conversione risultato HEX in ASCII RET CALCOLA_RISULTATO ENDP ;---------------------------------------------------------------------------------------------------------; ; PROCEDURA : ASC2HEX ; ; DESCRIZIONE : Converte i quattro caratteri ASCII corrispondenti a simboli ; ; del sistema di numerazione esadecimale; tale stringa è puntata in ingresso da DS:SI ed è ; ; trasformata nel numero esadecimale xyzwH a sedici bit che le ; ; corrisponde, lasciato in uscita in AX; il puntatore SI viene ; ; incrementato di quattro posizioni. ; ;---------------------------------------------------------------------------------------------------------; ASC2HEX PROC NEAR MOV SI,00H PUSH BX CALL ASC2BYT ;Preleva in AL il valore xyH MOV BH,AL ;Sposta in BH il valore xyH CALL ASC2BYT ;Preleva in AL il valore wzH MOV BL,AL ;Sposta in BL il valore wzH PUSH BX ;Lascia in AX il valore finale xywzH POP AX POP BX RET ASC2HEX ENDP ;----------------------------------------------------------------------------; ; PROCEDURA : ASC2BYT ; ; DESCRIZIONE : Converte la coppia di caratteri ASCII corrispondenti a sim- ; ; boli del sistema di numerazione esadecimale; tale coppia è ; ; puntata in ingresso da DS:SI ed è trasformata nel numero ; ; esadecimale xyH a otto bit che le corrisponde, lasciato ; ; in uscita in AL; il puntatore SI viene incrementato ; ; di due posizioni. ; ;----------------------------------------------------------------------------; ASC2BYT PROC NEAR CALL ASC2NIB ;Preleva in AL il valore 0xH MOV AH,AL ;Sposta in AH il valore 0xH SHL AH,1 ;Trasforma in AH il valore nella forma x0H SHL AH,1 ; ------- ------ SHL AH,1 ; SHL: | ffC | <-- | AH | <-- 0 SHL AH,1 ; ------- ------ CALL ASC2NIB ;Preleva in AL il valore 0yH OR AL,AH ;Lascia in AL il valore finale xyH RET ASC2BYT ENDP ;-----------------------------------------------------------------------------; ASC2NIB PROC NEAR MOV AL,NUM_ASCII[SI] CMP AL," " JB AscX4 ;ASCII di controllo JZ AscX2 ;SPAZIO, lo traduco in 00H CMP AL,"0" JB AscX4 CMP AL,":" JB AscX1 CMP AL,"A" JB AscX4 CMP AL,"G" JB AscX0 CMP AL,"a" JB AscX4 CMP AL,"g" JB AscX5 AscX4: SUB AL,AL JMP AscX3 AscX5: SUB AL,20H AscX0: SUB AL,07H AscX1: SUB AL,10H AscX2: SUB AL,20H AscX3: INC SI RET ASC2NIB ENDP ;-----------------------------------------------------------------------------; ; PROCEDURA : HEX2ASC ; ; DESCRIZIONE : Provvede alla conversione dei 4 nibble di un numero binario ; ; a 16 bit nei 4 caratteri ASCII corrispondenti, memorizzandoli ; ; poi in ESPRESSIONE. ; ; Il codice da convertire è fornito, in ingresso, in AX ed è ; ; ancora disponibile in AX in uscita. ; ;-----------------------------------------------------------------------------; HEX2ASC PROC NEAR MOV SI,00H PUSH AX PUSH AX MOV AL,AH CALL BYT2ASC POP AX CALL BYT2ASC POP AX RET HEX2ASC ENDP ;-----------------------------------------------------------------------------; ; PROCEDURA : BYT2ASC ; ; DESCRIZIONE : Provvede alla conversione dei 2 nibble di un numero binario ; ; a 8 bit nei 2 caratteri ASCII corrispondenti, ponendoli poi ; ; a video nella posizione di stampa corrente, nel colore pre- ; ; cedentemente predisposto in CS:[ATTRIB]. ; ; Il codice da convertire Š fornito, in ingresso, in AL ed Š ; ; ancora disponibile in AL in uscita. ; ;-----------------------------------------------------------------------------; BYT2ASC PROC NEAR PUSH AX PUSH AX ;AL=xyH SHR AL,1 SHR AL,1 SHR AL,1 SHR AL,1 ;AL=0xH CMP AL,0AH ;Salta a Num se AL=0xH < 0AH, cioè se il nibble JC Num ;appena isolato è un numero (da 0 a 9) ADD AL,07H ;Altrimenti si tratta di una lettera (da A a F) Num: ADD AL,30H MOV NUM_ASCII[SI],AL ;AL= INC SI POP AX ;AL=xyH AND AL,0FH ;AL=0yH CMP AL,0AH ;Salta a Num1 se AL=0yH <0AH, cioè se il nibble JC Num1 ;appena isolato è un numero (da 0 a 9) ADD AL,07H ;Altrimenti si tratta di una lettera (da A a F) Num1: ADD AL,30H MOV NUM_ASCII[SI],AL ;AL= INC SI POP AX RET BYT2ASC ENDP ;*************************************************************************************************************************; ;* PROCEDURA PER LA STAMPA A MONITOR *; ;* DEL RISULTATO DELL'ESPRESSIONE *; ;*************************************************************************************************************************; STAMPA_RISULTATO PROC NEAR MOV DX,OFFSET A_CAPO ;sceglie la stringa (DS:DX) CALL STAMPA_STRINGA ; e la stampa MOV DX,OFFSET A_CAPO ;sceglie la stringa (DS:DX) CALL STAMPA_STRINGA ; e la stampa MOV DX,OFFSET ISTR_RISULT ;sceglie la stringa (DS:DX) CALL STAMPA_STRINGA ; e la stampa MOV DX,OFFSET NUM_ASCII CALL STAMPA_STRINGA MOV DX,OFFSET A_CAPO ;sceglie la stringa (DS:DX) CALL STAMPA_STRINGA ; e la stampa MOV DX,OFFSET A_CAPO ;sceglie la stringa (DS:DX) CALL STAMPA_STRINGA ; e la stampa MOV DX,OFFSET ISTR_AVANTI ;sceglie la stringa (DS:DX) CALL STAMPA_STRINGA ; e la stampa RET STAMPA_RISULTATO ENDP ;----------; ; END CSEG ; ;----------; CSEG ENDS END MAIN