; Esercizio assembly - compito del 14 aprile 2023 ; "SEQUENZE INFREQUENTI" ; ;=================================================================================================================== ; D E F I N I Z I O N E C O S T A N T I ;=================================================================================================================== CR EQU 13 ; carriage return LF EQU 10 ; line feed DOLLAR EQU '$' ;=================================================================================================================== ; M A C R O ;=================================================================================================================== display macro xxxx ; N.B. ogni stringa deve terminare con '$' push dx push ax mov dx,offset xxxx mov ah,9 int 21h pop ax pop dx endm ;=================================================================================================================== ; D E F I N I Z I O N E S E G M E N T O S T A C K ;=================================================================================================================== PILA SEGMENT STACK 'STACK' DB 16 DUP('STACK') ; lo stack e' riempito con la stringa 'stack' ; per identificarlo meglio in fase di debug PILA ENDS ;=================================================================================================================== ; D E F I N I Z I O N E S E G M E N T O D A T I ;=================================================================================================================== DATI SEGMENT PUBLIC 'DATA' ; definizione del segmento dati bin_vect db 1,0,0,1,0,0,1,0,1,1,1,0,0,0,1,1,1,0,1,0,0,1,1,0,1,0 ; sequenza da esaminare M equ $-bin_vect-10+1 ; numero di sottosequenze da 10 triplette da testare ( M = N-10+1 ) out_vect db M dup(?),DOLLAR ; vettore di uscita, preparato per stampa a video ; messaggio per stampa a video msg0 db "Sequenza bin_vect: 10010010111000111010011010",DOLLAR msg1 db "Sequenza outVect: ",DOLLAR CRLF db CR,LF,DOLLAR ; per formattazione output lut db 8 dup(0) ; lookup table per controllo presenza triplette duplicate nella sequenza DATI ENDS ;=================================================================================================================== ; S E G M E N T O C O D I C E ;=================================================================================================================== ; FUNZIONAMENTO: vengono caricati 3 elementi per volta di bin_vect su bl, che rappresentano la tripletta ; da controllare (la parte alta del registro bx, ossia bh, viene lasciata a zero). BX verrà usato come ; indice per la lookup table "lut", nella quale controlliamo se in quella posizione è presente uno 0 ; o un 1: nel primo caso scriveremo un 1 in "lut" e si passa alla prossima tripletta; ; se già troviamo un 1 in quella posizione significa che quella tripletta è un duplicato nella ; sotto-sequenza, quindi il programma salta a "failed", dove si scrive '0' in out_vect e si passa alla ; sotto-sequenza successiva per altri 10 valori di bin_vect (8 triplette). ; Se invece per 8 volte troviamo uno 0 nella lookup table significa che la sottosequenza rispetta la ; regola (non ci sono triplette duplicate), quindi possiamo scrivere '1' su out_vect per indicare che ; quella determinata sotto-sequenza è giusta e prendere in esame poi la sotto-sequenza successiva. ; Questo va fatto per M = N-10+1 volte, dove N è il numero di elementi di bin_vect. ;=================================================================================================================== CSEG SEGMENT PUBLIC 'CODE' MAIN proc far ASSUME CS:CSEG,DS:DATI,SS:PILA,ES:NOTHING MOV AX,DATI MOV DS,AX initialize: xor dx,dx ; azzero il registro dx mov si,offset bin_vect ; si punta alla prima locazione del vettore sorgente mov di,offset out_vect ; di punta alla prima locazione del vettore di destinazione mov ch,M ; contatore primario di fine programma mov cl,8 ; contatore secondario di fine sequenza di 8 triplette triplet: ; si preleva la tripletta ABC e si posiziona nella base per massimo 8 volte xor bx,bx ; azzero bx, si usa il registro intero a 16 bit per indirizzare la lookup table mov al,[si] ; prelevo A da bin_vect or bl,al ; bl contiene 0000000A shl bl,1 ; bl contiene 000000A0 mov al,[si+1] ; prelevo B da bin_vect or bl,al ; bl contiene 000000AB shl bl,1 ; bl contiene 00000AB0 mov al,[si+2] ; prelevo C da bin_vect or bl,al ; bl contiene 00000ABC -> tripletta completa! inc si ; incremento si preparandolo per la prossima tripletta al ciclo successivo inc dl ; contatore interno che tiene conto di quanto avanza SI tra le triplette per resettarlo ; bl adesso contiene la tripletta da esaminare con gli elementi della lookup table "lut": ; se a quell'indice troviamo un 1, la tripletta è un duplicato e usciamo scrivendo '0' in "out_vect"; ; se troviamo 0 allora scriviamo l'intero 1 in "lut" e si passa alla prossima tripletta. mov al,lut[bx] ; al contiene l'elemento (intero) rappresentato dalla tripletta cmp al,0 ; confronto al <-> 0 je write1 ; se al==0 elemento non presente -> scrivo 1 e torno a triplet jmp failed ; se al==1 la tripletta è gia presente nella sequenza -> scrivo 0 in out_vect (failed) ed eseguo il refresh write1: ; controllo innanzitutto che non siamo arrivati in fondo alla sotto-sequenza di 8 triplette (10 elementi) dec cl ; decremento cl il quale tiene il conto delle 8 sotto-sequenze jz found ; se cl==0 allora la sotto-sequenza rispetta la regola! scrivo '1' in out_vect e refresh "lut" mov lut[bx],1 ; se non siamo ancora in fondo alla sotto-sequenza scrivo l'intero 1 nella lookup table jmp triplet ; e si salta al prelievo della prossima tripletta (ciclo triplet:) failed: ; la tripletta è gia presente "lut", scrivo '0' in out_vect e si passa alla sotto-seq successiva mov dh,'0' mov [di],dh ; scrivo '0' in out_vect jmp check_end ; salto incondizionato al controllo di fine sequenza check_end: found: ; ho trovato la sotto_sequenza giusta, scrivo '1' in "out_vect" e passo al controllo di fine programma mov dh,'1' mov [di],dh ; scrivo '1' in out_vect e vado a check_end: check_end: ; Controllo se sono arrivato in fondo alla sequenza totale "bin_vect" dec ch ; decremento il contatore primario (M = (N-10+1) iterazioni per l'intero processo) jz print_output ; salto a fine programma se la stringa "out_vect" è completa inc di ; altrimenti scorro "out_vect" di una posizione xor dh,dh ; azzero dh, contiene un ASCII ma serve per riposizionare SI dec dl ; avanzamento del registro SI di una posizione rispetto alla posizione inziale precedente sub si,dx ; posiziono si al giusto valore (posizione di inizio sotto-sequenza +1) refresh1: ; devo refreshare cl := 8, contatore secondario per le 8 triplette da controllare mov cl,8 ; ricarico il contatore secondario xor dl,dl ; azzero dl, mi servirà di nuovo per tener conto degli spostamenti di si dentro bin_vect xor bx,bx ; azzero base per ciclo refresh_lut, dove si azzera l'intera lookup table refresh_lut: ; devo azzerare la lookup table per 8 volte, un elemento alla volta mov lut[bx],0 ; indirizzo "lut" tramite bx azzerato prima inc bx ; elemento successivo cmp bl,8 ; se bl==8 allora ho azzerato tutta la lookup table (indice finale di "lut") je triplet ; controllo della sotto-sequenza di triplette successiva jmp refresh_lut ; print_output: ; display a video del risultato in "out_vect" display CRLF display msg0 display CRLF display msg1 display out_vect display CRLF exit: ; fine programma MOV AH,4CH ; ritorno al DOS INT 21H main endp cseg ends END MAIN ; il programma comincia all'indirizzo di MAIN