PDA

View Full Version : [ASSEMBLY/x86] Contare sequenza numeri


aedesy
28-06-2013, 23:14
Salve a tutti. Sono alle prese con la prese con la tesina di Calcolatori. Una bellissima materia per quanto mi riguarda ma vedo che l'Assembly

(TASM) è alquanto ostico per un neofita come me. Ma vediamo comunque di riuscire a farcela. Dati due numeri A e B devo contare il numero di volte

che si presenta la sequenza '0110' dei numeri compresi tra A e B. Per adesso ho svolto il codice per trovare la sequeza in solo numero, sviluppando

i seguenti passi:

1) Aquisisco il numero come stringa di caratteri
2) Lo converto in word
3) Lo converto in binario
4) Controllo la il numero di volte che si presenta '0110'
5) Stampo il risultato

Di problemi ne ho incontrati strada facendo ma grazie all'aiuto del debug sono riuscito a risorverli. Solo che adesso, nel debug, in corrispodenza

della procedura STAMPA_BIN compaiono delle istruzioni che non riesco a capire e che mi portano ad avere come risultato sempre zero. Nello

specifico in corrispondenza di

SHL DX,01h
ADC AL,AL
MOV CS:[SI],AL
INC SI
DEC CL

corrispondono

XOR DH,[3232]
XOR AL,00
ADD AL,46
DEC CL

e non mi so spiegare il perché. Spero che qualcuno mi possa aiutare. Grazie :)



;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 'CORSO di CALCOLATORI ELETTRONICI$'
ISTRUZIONE_1 DB CR,LF,LF,HT,'Digita il primo numero (max 5 cifre): $'
BIN_MESS DB CR,LF,HT,HT,'Rappresentazione Binaria: $'
TERMINE DB CR,LF,LF,HT,'Un''altra iterazione? [S/N]$'
MSG_ERRORE DB CR,LF,LF,HT,'Sono permessi solo caratteri numerici! Pertanto...$'
MSG_EMPTY DB CR,LF,LF,HT,'Non hai scritto nessun numero$'
RIS DB CR,LF,LF,HT,'IL RISULTATO E $'
NUM_1 DB 5 DUP(?)
NUM_B Db 16 DUP (?)
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
CALL ACQUISIZIONE_1
CALL CONVERSIONE
CALL STAMPA_BIN
CALL CONTROLLO
CALL STAMPA_RIS
CALL TEST_FINALE
JNZ CICLO_PRINCIPALE
RET ;Ritorno al Sistema Operativo
MAIN ENDP



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
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 PROC NEAR
MOV DX,OFFSET ISTRUZIONE_1
CALL STAMPA_STRINGA ; e la stampa.
RET ;Ritorno alla procedura chiamante
PROMPT ENDP

;------------------------------------------------------------------------;
; Procedura per l'acquisione del primo numero;
;------------------------------------------------------------------------;

ACQUISIZIONE_1 PROC NEAR
INIZIO_1: LEA SI,NUM_1
MOV CL,05d
MOV CH,0
CICLO_1: MOV AH,R_KEY_CHR
INT DOS
CMP AL,CR
JE FINE_1
CMP AL,'9'
JG ERRORE_1
CMP AL,'0'
JL ERRORE_1
MOV CS:[SI],AL
INC SI
LOOP CICLO_1
JMP FINE_1
ERRORE_1: LEA DX,MSG_ERRORE
CALL STAMPA_STRINGA
LEA DX,ISTRUZIONE_1
CALL STAMPA_STRINGA
JMP INIZIO_1
FINE_1: MOV AL,00H
MOV CS:[SI],AL
RET
ACQUISIZIONE_1 ENDP

;-----------------------------------------------------------------;
CONVERSIONE PROC NEAR
LEA SI,NUM_1
PUSH BX
PUSH CX
PUSH BP
PUSH SI

MOV CX,0000H
START: MOV AL,CS:[SI]
CMP AL,00H
JE EMPTY
INC CX
INC SI
JMP START
EMPTY: POP SI
MOV AX,0000H
CMP CX,0000H
JE W1

MOV AX,5
SUB AX,CX
MOV CX,AX
CMP CX,0000H
JE W5
W2: PUSH CX
MOV BX,5
MOV CX,5
W3: MOV AL,CS:[SI+BX-1]
MOV CS:[SI+BX],AL
DEC BX
LOOP W3
MOV AL,'0'
MOV CS:[SI+BX],AL
POP CX
LOOP W2


W5: MOV BP,0000H
MOV CX,5
MOV BX,10000
W4: MOV AL,CS:[SI]
SUB AL,'0'
MOV AH,00H
MUL BX
INC SI
ADD BP,AX
MOV AX,BX
MOV BX,10
DIV BX
MOV BX,AX
LOOP W4

MOV AX,BP
JMP FINE_CONV

W1: LEA DX,MSG_EMPTY
CALL STAMPA_STRINGA
JMP FINE_CONV

FINE_CONV: POP BP

POP CX
POP BX
RET
CONVERSIONE ENDP

;---------------------------------------------------------------;

STAMPA_BIN PROC NEAR

LEA SI,NUM_B
MOV DX,AX
MOV CL,10H
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
MOV CS:[SI],AL
INC SI
DEC CL ;Decrementa il contatore del ciclo
JNZ CICLO_BINARIO ;Se non e' 0 itera un'altra volta
RET ;Ritorno alla procedura chiamante

STAMPA_BIN ENDP


CONTROLLO PROC NEAR
MOV BX,0000H
MOV CL,00H
LEA SI,NUM_B

BO_0: MOV AL,CS:[SI]
BO_X: CMP CL,16
JE FINE_CO
BO_Z: CMP AL,0
JE BO_1
INC SI
INC CL
JMP BO_0

BO_1: INC SI
INC CL
CMP CL,16
JE FINE_CO
MOV AL,CS:[SI]
CMP AL,1
JE BO_2
JMP BO_0

BO_2: INC SI
INC CL
CMP CL,16
JE FINE_CO
MOV AL,CS:[SI]
CMP AL,1
JE BO_3
JMP BO_0

BO_3: INC SI
INC CL
MOV AL,CS:[SI]
CMP AL,0
JE CO5
JMP BO_X

CO5: INC BX
CMP CL,16
JE FINE_CO
JMP BO_Z

FINE_CO: RET
CONTROLLO ENDP



STAMPA_RIS PROC NEAR
MOV DX,OFFSET RIS
CALL STAMPA_STRINGA
MOV AX,BX
CMP AX,10000
JC SRW_0
MOV DX,0000H
MOV BX,10000
DIV BX
CALL STAMPA_NUMERO
MOV AX,DX
JMP SRW_1
SRW_0: CMP AX,1000
JC SRB_0
SRW_1: MOV DX,0000H
MOV BX,1000
DIV BX
CALL STAMPA_NUMERO
MOV AX,DX
JMP SRB_1

SRB_0: CMP AX,100
JC SRB_2
SRB_1: MOV BL,100
DIV BL
CALL STAMPA_NUMERO
MOV AL,AH
MOV AH,00H
JMP SRB_3
SRB_2: CMP AX,10
JC SRB_4
SRB_3: MOV BL,10
DIV BL
CALL STAMPA_NUMERO
MOV AL,AH
SRB_4: CALL STAMPA_NUMERO

RET
STAMPA_RIS ENDP

TEST_FINALE PROC NEAR
MOV DX,OFFSET TERMINE
CALL STAMPA_STRINGA ; e la stampa.
CALL LETTURA_SN ;Legge da tastiera senza echo.
CMP AL,'n' ;Modifica il FLAG 'Z'
RET ;Ritorno alla procedura chiamante
TEST_FINALE ENDP


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'
INT BIOS_VIDEO
RET ;Ritorno alla procedura chiamante
STAMPA_NUMERO ENDP

LETTURA_SN PROC NEAR
NUOVA_LETTURA: MOV AH,R_KEY_CHR_NE ;Servizio DOS 'Read Keyboard Char
INT DOS ; Without Echo'
OR AL,00100000b ;Converte in minuscolo
CMP AL,'n' ;Se il tasto premuto e' 'N' esce
JZ FINE_LETTURA ; dalla procedura
CMP AL,'s' ;Se non e' 'S', ne legge
JNZ NUOVA_LETTURA ; un altro
FINE_LETTURA: RET ;Ritorno alla procedura chiamante
LETTURA_SN ENDP

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


STAMPA_STRINGA PROC NEAR
MOV AH,PRINT_STRING ;Servizio DOS 'Print String'; la
INT DOS
RET ;Ritorno alla procedura chiamante
STAMPA_STRINGA ENDP


CSEG ENDS
END MAIN

lorenzo001
29-06-2013, 08:17
Vedi http://forum.html.it/forum/showthread.php?s=&threadid=1547748