salve a tutti, posto qui per chiedere aiuto...da diversi giorni ho questo problema sul mio codice cioè compilo faccio il linking ma quando vado ad eseguire mi dice: LA cpu NTVDM ha inontaro un istruzione non valida! Tutto ha avuto inizio quando ho iniziato ad usare i registri eax e edx e a porre all'inizio del file il .386 difatti se elimino questi il tutto gira perfettamente però nn posso fare a meno di utlizzare i registri eax e edx per una funzione ke stò facendo...posto il codice con la speranza ke qualcuno di voi sappia dirmi cosa sbaglio...![]()
![]()
TITLE - Esercitazione di Calcolatori Elettronici
;.386
;Definizione costanti
PAGINA EQU 00h
HT EQU 09h
LF EQU 0Ah
CR EQU 0Dh
BIOS_VIDEO EQU 10H
SET_VIDEO_MODE EQU 00h;in AH
MODE_TESTO EQU 03H;in AL
SET_CURSOR EQU 02h;in AH
W_CHR_TTY EQU 0Eh;in AH
DOS EQU 21H
R_KEY_CHR EQU 01H
PRINT_STRING EQU 09H
R_KEY_CHR_NE EQU 07h
PRE_LEN EQU 10
DSEG SEGMENT PARA PUBLIC 'DATA'
SEGNO DB ?
NUM DW 0
NUM_A2 DW 0
NUM_QUADR DD 0
DIVD DW ?
ERR_MESS DB CR,LF,LF,CR,'Valore non ammesso.Inserire un nuovo numero compreso tra -999 e 999:',0DH,0AH,'$'
TITOLO DB 'CORSO di CALCOLATORI ELETTRONICI$'
ISTRUZIONI DB CR,LF,LF,CR,'Inserire un numero compreso tra -999 e 999:$'
BIN_MESS DB CR,LF,HT,HT,'Rappresentazione Binaria:$'
A2_MESS DB CR,LF,HT,HT,'Rappresentazione Binaria in complemento A2:$'
DEC_MESS DB CR,LF,HT,HT,'Rappresentazione Decimale del quadrato del numero:$'
TERMINE DB CR,LF,LF,HT,'Un altra iterazione? [S/N]$'
CODICE_TASTO DB ?
DSEG ENDS
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,DSSEG,SS:STACKM
CSEG SEGMENT PARA PUBLIC 'CODE'
;----------------------------------------------------------------------------------;
; Corpo principale del programma ;
;----------------------------------------------------------------------------------;
MAIN PROC FAR
PUSH DS ;Istruzioni da lasciare sempre
MOV AX,00h ; al principio dei programmi!
PUSH AX ;
CALL INIZIALIZZAZIONE
CICLO_PRINCIPALE: CALL PROMPT
CALL LETTURA_DATI
CALL STAMPA_BIN
CALL COMP_A2
CALL STAMPA_A2
CALL QUADR
CALL STAMPA_DEC
CALL TEST_FINALE
JNZ CICLO_PRINCIPALE
RET ;Ritorno al Sistema Operativo
MAIN ENDP
;----------------------------------------------------------------------------------;
; Procedura di inizializzazione ;
;----------------------------------------------------------------------------------;
INIZIALIZZAZIONE PROC NEAR
MOV AX,DSEG ;Inizializzazione segmento dati
MOV DS,AX ; tramite il registro AX.
MOV AH,SET_VIDEO_MODE ;Servizio BIOS 'Set Video Mode':
MOV AL,MODE_TESTO ;modo testo 80 x 25,colori
INT BIOS_VIDEO ;
MOV DX,0315h ;Imposta riga (DH) e colonna (DL)
CALL SPOSTA_CURSORE ;Muove il cursore nel pos scelta
MOV DX,OFFSET TITOLO ;Sceglie la stringa (DSX)
CALL STAMPA_STRINGA ;e la stampa.
MOV DX,0400h ;Imposta riga(DH) e colonna (DL)
CALL SPOSTA_CURSORE ;Muove il cursore nella pos scelta
RET ;Ritorno alla procedura chiamante
INIZIALIZZAZIONE ENDP
;-----------------------------------------------------------------------------------;
; Procedura per stampare il messaggio iniziale
;-----------------------------------------------------------------------------------;
PROMPT PROC NEAR
MOV DX,OFFSET ISTRUZIONI ;Sceglie la stringa (DSX)
CALL STAMPA_STRINGA ; e la stampa.
RET ;Ritorna alla procedura chiamante
PROMPT ENDP
;-----------------------------------------------------------------------------------;
; Procedura per stampare un numero in formato binario
;-----------------------------------------------------------------------------------;
STAMPA_BIN PROC NEAR
MOV DX,OFFSET BIN_MESS ;Sceglie la stringa (DSX)
CALL STAMPA_STRINGA ;e la stampa.
MOV DX,[NUM] ;Carica il numero inserito
MOV BL,10h ;Contatore di bits
CICLO_BINARIO: XOR AL,AL ;Azzera il registro AL
SHL DX,01h ;shift logico a Sinistra
ADC AL,AL ;In AL si pone il CARRY
CALL STAMPA_NUMERO ;Stampa cifra binaria
DEC BL ;Decrementa il contatore del ciclo
JNZ CICLO_BINARIO ;Se non é 0 itera un altra volta
RET ;Ritorno alla procedura chiamante
STAMPA_BIN ENDP
;-----------------------------------------------------------------------------------;
; Procedura per stampare in formato binario il numero in complemento a2 ;
;-----------------------------------------------------------------------------------;
STAMPA_A2 PROC NEAR
MOV DX,OFFSET A2_MESS ;Sceglie la stringa (DSX)
CALL STAMPA_STRINGA ;e la stampa.
CALL COMP_A2 ;Vado a complementare il numero
MOV DX,[NUM_A2] ;Carica il numero inserito
MOV BL,10h ;Contatore di bits
CICLO_BINARIO1: XOR AL,AL ;Azzera il registro AL
SHL DX,01h ;shift logico a Sinistra
ADC AL,AL ;In AL si pone il CARRY
CALL STAMPA_NUMERO ;Stampa cifra binaria
DEC BL ;Decrementa il contatore del ciclo
JNZ CICLO_BINARIO1 ;Se non é 0 itera un altra volta
RET ;Ritorno alla procedura chiamante
STAMPA_A2 ENDP
;-----------------------------------------------------------------------------------;
; Procedura per stampare un numero in formato decimale
;-----------------------------------------------------------------------------------;
STAMPA_DEC PROC NEAR
;...
RET ;ritorno alla procedura chiamante
STAMPA_DEC ENDP
;-----------------------------------------------------------------------------------;
; Procedura per fare il complemento A2 del numero inserito
;-----------------------------------------------------------------------------------;
COMP_A2 PROC NEAR
MOV SEGNO,0; azzero il flag del segno
MOV DX,[NUM];carico il numero inserito
NOT DX; ne faccio il complemento a1
ADD DX,1B;aggiungo 1 per fare il complemento a2
MOV NUM_A2,DX;
RET
COMP_A2 ENDP
;-----------------------------------------------------------------------------------;
; Procedura per fare il quadrato del numero inserito
;-----------------------------------------------------------------------------------;
QUADR PROC NEAR
MOV AX,NUM
MUL NUM; risultato della moltiplicazione in DX:AX
SHL EDX,16
MOV DX,AX
MOV NUM_QUADR,EDX
RET
QUADR ENDP
;------------------------------------------------------------------------------------;
; Procedura per determinare se occorre un'altra iterazione ;
; ;
; REGISTRI UTILIZZATI: AX, DX ;
; CODICE DI RITORNO: ;
; Zero flag = 0 -> un'altra iterazione ;
; Zero flag = 1 -> esci dal programma ;
;------------------------------------------------------------------------------------;
TEST_FINALE PROC NEAR
MOV DX,OFFSET TERMINE ;Sceglie la strinaga (DSX)
CALL STAMPA_STRINGA ;e la stampa.
CALL LETTURA_SN ;legge la stringa senza echo.
CMP AL,'n' ;modifica il FLAG 'Z'
RET ;Ritorno alla procedura chiamante
TEST_FINALE ENDP
;************************************************* ***********************************;
;* Procedura di basso livello di interfaccia *;
;************************************************* ***********************************;
;------------------------------------------------------------------------------------;
; Procedura per stampare un numero da 0 a 9 ;
;------------------------------------------------------------------------------------;
STAMPA_NUMERO PROC NEAR
ADD AL,'0' ;La base da cui partire é '0'
MOV AH,W_CHR_TTY ;Servizio BIOS 'Write char in TTY'
INT BIOS_VIDEO
RET ;Ritorna alla procedura chiamante
STAMPA_NUMERO ENDP
;-----------------------------------------------------------------------------------;
; Procedura per leggere il numero immesso e memorizzarlo in BUFFER
;-----------------------------------------------------------------------------------;
LETTURA_DATI PROC NEAR
LAB0: XOR DX,DX
LAB1: MOV BX,10
MOV AH,08H ;legge un carattere senza echo
INT 21H
CMP AL,CR ;controlla è un invio?
JE FINE
CMP AL,'-'
JE MOD_SEGNO
CONTINUA: CMP AL,'0'
JB LAB1
CMP AL,'9'
JA LAB1
PUSH DX
MOV DL,AL
MOV AH,02H ;se ho premuto un numero lo stampo a video
INT 21H
POP DX
SUB AL,'0';sottrae la codifica di zero
XCHG AX,BX
XOR BH,BH
MUL DX;moltiplica per 10
MOV DX,AX
ADD DX,BX;somma la cifra letta
MOV NUM,DX
CMP NUM,999
JA I_ERR
JMP LAB1
I_ERR: LEA DX, ERR_MESS
MOV AH,9
INT 21H
JMP LAB0
MOD_SEGNO: MOV SEGNO,1
PUSH DX
MOV DL,AL
MOV AH,02H ;stampo il segno '-'
INT 21H
POP DX
JMP CONTINUA
COMPLEMENTA: MOV SEGNO,0
NOT NUM
ADD NUM,1B
JMP FINE
FINE: CMP SEGNO,1
JE COMPLEMENTA
RET
LETTURA_DATI ENDP
;------------------------------------------------------------------------------------;
; Procedura per leggere da tastiera uno dei tasti 'S' o 'N'
;------------------------------------------------------------------------------------;
LETTURA_SN PROC NEAR
NUOVA_LETTURA: MOV AH,R_KEY_CHR_NE ;Servizio DOS 'Read keyboard char'
INT DOS ;Whitout echo
OR AL,00100000b ;Converte in minuscolo
CMP AL,'n' ;Se il tasto premuto é 'N' esce
JZ FINE_LETTURA ;dalla procedura
CMP AL,'s' ;Se non é 's', ne legge
JNZ NUOVA_LETTURA ;un altro
FINE_LETTURA: RET
LETTURA_SN ENDP
;-----------------------------------------------------------------------------------;
; Procedura per spostare il cursore
;-----------------------------------------------------------------------------------;
SPOSTA_CURSORE PROC NEAR
MOV BH,PAGINA ;Pagina video attiva.
MOV AH,SET_CURSOR ;Servizio BIOS 'Set Cursor
INT BIOS_VIDEO ;Position'
RET ;Ritorno alla procedura chiamante
SPOSTA_CURSORE ENDP
;-----------------------------------------------------------------------------------;
; Procedura per stampare una stringa ;
; ;
; PARAMETRI: l'indirizzo della stringa é memorizzato in DSX ;
; REGISTRI UTILIZZATI: AH, DX ;
;-----------------------------------------------------------------------------------;
STAMPA_STRINGA PROC NEAR
MOV AH,PRINT_STRING ;Servizio DOS 'Print String'; la
INT DOS ;stringa é puntata da DSX.
RET ;Ritorno alla procedura chiamante
STAMPA_STRINGA ENDP
CSEG ENDS
END MAIN