Con tasm32 compilo e linko con tlink...ho messo la direttiva .386 all'inizio del codice...
Ho tolto la funzione che ho scritto stamattina e ho rimesso la mia iniziale con lo stack...così compila, linka e va ma non stampa il numero corretto...ripeto, vista la mia scarsa abilità con l'assembly potrebbe esserci un errore anche nella funzione ATOI di lettura del numero ma senza stampa non me ne rendo conto
Tutto il codice è questo:
;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
MODO_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
DSEG SEGMENT PARA PUBLIC 'DATA'
TITOLO DB 'Assegnamento 3 - Calcolatori Elettronici$'
ISTR_1 DB 'Inserire un numero minore di 1000000: $'
ISTR_2 DB 'Inserire un numero minore di 200: $'
NCIFRE DW 00h
TEMP DB 16 DUP(?)
NUMERO DD 00h
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,DS:DSEG,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_1
CALL ATOI_A
CALL STAMPA_NUM1
CALL PROMPT_2
RET
MAIN ENDP
;---------------------------------------------------------------------;
; Procedura di inizializzazione ;
; ;
; REGISTRI UTILIZZATI: AX, DX, DS ;
;---------------------------------------------------------------------;
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,MODO_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 nella pos scelta
MOV DX,OFFSET TITOLO ;Sceglie la stringa (DS:DX)
CALL STAMPA_STRINGA ; e la stampa.
MOV DX,0606h ;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 ;
; ;
; REGISTRI UTILIZZATI: DX, AH ;
;---------------------------------------------------------------------;
PROMPT_1 PROC NEAR
MOV DX,OFFSET ISTR_1 ;Sceglie la stringa (DS:DX)
CALL STAMPA_STRINGA ; e la stampa.
RET ;Ritorno alla procedura chiamante
PROMPT_1 ENDP
PROMPT_2 PROC NEAR
MOV DX,OFFSET ISTR_2 ;Sceglie la stringa (DS:DX)
CALL STAMPA_STRINGA ; e la stampa.
RET ;Ritorno alla procedura chiamante
PROMPT_2 ENDP
;---------------------------------------------------------------------;
; Procedura per leggere un numero e memorizzarlo in NUMERO_1 ;
; ;
; REGISTRI UTILIZZATI: AX, BX, CX, SI ;
;---------------------------------------------------------------------;
ATOI_A PROC NEAR
INIT_A: XOR CX,CX ;Azzero i registri
XOR BX,BX ;
XOR AX,AX ;
MOV SI,0 ;Mi posiziono nella prima locazione dell'array
START_A: MOV AH, R_KEY_CHR ;Servizio DOS 'Read Keyboard Char'
INT DOS
CMP AL,13 ;Se hai inserito il tasto invio
JE FINELETT_A ;hai finito di inserire il numero e finisce la lettura
CMP AL, '0' ;Se non hai inserito un numero
JB ERR_A ;hai commesso un errore
CMP AL, '9' ;''
JA ERR_A ;''
MEM_A: SUB AL,'0' ;sottraggo per trasformare il char in un numero
MOV BYTE PTR TEMP[SI],AL ;lo inserisco nell'array alla posizione puntata
INC SI ;Incremento l'indice dell'array
INC CX ;Incremento il contatore delle cifre
JMP START_A ;devo ripetere il ciclo
FINELETT_A: MOV TEMP[SI+1],'$' ;Inserisco il carattere di fine stringa dopo l'ultima cifra inserita
XOR EAX,EAX ;Azzero i registri
XOR EDX,EDX
XOR EBX,EBX
MOV SI, OFFSET TEMP ;passiamo l'offset per ricavare l'indirizzo
CICLO_A: MOV EAX, DWORD PTR[BX+SI]
XOR AH,AH
CMP EAX,'$' ;Confronto per verificare se ci si trova alla fine della stringa
JE FINE_A ;se sono alla fine salto a FINE_1
CMP CX, 1 ;Confronto se il numero totale delle cifre inserite è uguale a 1
JE FINE_A ;se sì, salto a FINE_1
ADD EAX,[NUMERO] ;Sommo NUMERO in AX
MOV EDX, 10
MUL EDX ;Moltiplico NUMERO_1 per 10
DEC CX ;Decremento CL (solo in caso di CL>1)
INC BX ;incremento l'indice dell'array
MOV [NUMERO],EAX ;Sommo(sovvrascrivendo) il numero moltiplicato in NUMERO_1
JMP CICLO_A ;Ripeto il ciclo, fino ad avere CL=1
ERR_A: ;CALL PROMPT_ERR
CALL PROMPT_1
JMP INIT_A
FINE_A: ADD [NUMERO],EAX ;Sovrascrivo AX in NUMERO_1
RET
ATOI_A ENDP
;---------------------------------------------------------------------;
; Procedura per stampare un numero a 32 bit ;
; ; ;
;---------------------------------------------------------------------;
STAMPA_NUM1 PROC NEAR
XOR EDX, EDX
MOV EAX,[NUMERO] ;metto in EAX il numero da stampare
XOR EBX, EBX ;azzero il registro per il dividendo
XOR CX,CX ;azzero il registro per il contatore delle cifre
MOV EBX, 10 ;imposta il divisore
MEMONUM1:
DIV EBX ;divido per 10
PUSH DX ;salvo il resto
XOR DX,DX ;azzero DX
INC CX ;incremento il contatore cifre
CMP EAX, 0 ;devo ripetere?
JNZ MEMONUM1
STAMPANUM1: POP DX ;riprende i numeri come LIFO
MOV AX, DX ;metto in AX numero da stampare
CALL STAMPA_NUMERO ;stampo
LOOP STAMPANUM1 ;ripeto
STOP1: RET ;Ritorno alla procedura chiamante
STAMPA_NUM1 ENDP
;---------------------------------------------------------------------;
; Procedura per stampare un numero da 0 a 9 ;
; ;
; PARAMETRI: il numero e' memorizzato in AL ;
; VARIABILI: il numero della pagina e` memorizzato in PAGINA ;
; REGISTRI UTILIZZATI: AX, BL ;
;---------------------------------------------------------------------;
STAMPA_NUMERO PROC NEAR
ADD AL,'0' ;La base da cui partire e' '0'
MOV AH,W_CHR_TTY ;Servizio BIOS 'Write Char in TTY'
;che stampa il carattere
STAMP: INT BIOS_VIDEO
RET ;Ritorno alla procedura chiamante
STAMPA_NUMERO ENDP
;---------------------------------------------------------------------;
; Procedura per spostare il cursore ;
; ;
; PARAMETRI: le coordinate della posizione del cursore sono memoriz- ;
; zate nel registro DX: DH riga, DL colonna. ;
; VARIABILI: il numero della pagina e` memorizzato in PAGINA ;
; REGISTRI UTILIZZATI: AH, BH ;
;---------------------------------------------------------------------;
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 e` memorizzato in DS:DX ;
; REGISTRI UTILIZZATI: AH, DX ;
;---------------------------------------------------------------------;
STAMPA_STRINGA PROC NEAR
MOV AH,PRINT_STRING ;Servizio DOS 'Print String'; la
INT DOS ; stringa e' puntata da DS:DX.
RET ;Ritorno alla procedura chiamante
STAMPA_STRINGA ENDP
CSEG ENDS
END MAIN