Gestire numeri con più cifre 8086[Risolto]

di il
8 risposte

Gestire numeri con più cifre 8086[Risolto]

Ciao a tutti!

Per semplificare la creazione di qualche programmino in Assembly 8086 vorrei creare un programma che gestisca in maniera autonoma la stampa di numeri a più cifre e in futuro magari includerlo come procedura in qualche altro programma.

Tuttavia mi sorgono dei dubbi e delle perplessità, poichè mi è stato sempre detto che bisogna dividere sempre per dieci così da ottenere le varie cifre che costituiscono il numero.
Ad esempio:

Ho come numero 3576.
Se lo divido per 10 il quoziente sarà 357 e come resto 6 e il quoziente supera un byte, poichè so che quando divido per un numero di un byte il risultato si suddivide in due parti, cioè il quoziente in AL e il resto in AH...
Qualche consiglio?

8 Risposte

  • Re: Gestire numeri con più cifre 8086[Risolto]

    In questo caso devi usare un operando a 16 bit

    Cosa non ti convince?
  • Re: Gestire numeri con più cifre 8086[Risolto]

    Non mi convince il fatto che se divido un numero per 10 non sempre il quoziente sta in un byte come nell'esempio del post precedente

    Perchè io so che quando il divisore è rappresetabile tramite un byte il risultato si suddivide in AL il quoziente e in AH il resto...
  • Re: Gestire numeri con più cifre 8086[Risolto]

    Ma nell'esempio che hai fatto, il numero 3576 dove l'hai inserito?
  • Re: Gestire numeri con più cifre 8086[Risolto]

    Il numero 3576 in una ipotetica variabile

    Per ora ho scritto questo programma ma c'è un problema:
    • Se il numero è a una sola cifra tutto ok
    • Se il numero è a più cifre allora non stampa nulla
    Ecco il codice, non riesco a capire il perché nonostante il debug...
    
    DATA SEGMENT PUBLIC
    
    	STRINGA DB "Numero: ",'$'
    	NUMERO DW 34 ;variabile che può contentere un numero qualsiasi
    	DIECI DW 10   ;divisore è 10 perchè cos' ottengo le singole cifre da stampare
    	CONTA DB 0 ;variabile contatore 
    	NMAX DB ?
    	
    	
    DATA ENDS ;fine del segmento dei dati
    
    CODE SEGMENT
    
    	ASSUME CS:CODE,DS:DATA 
    	
    INIZIO: ;inizio del programma
    	
    	MOV AX,DATA
    	MOV DS,AX ;carico i dati nel segmento dei dati
    
    	;AZZERO IL REGISTRO AX E BX poichè li uso per effettuare la serie di divisioni per ottenere così la stampa del numero finale.
    	
    	XOR AX,AX ;azzero il registro AX
    	XOR BX,BX ;azzero il registro BX
    	
    	MOV AX,NUMERO ;metto in AX il numero da dividere
    	MOV BX,DIECI ;metto in BX il numero che deve dividere cioè 10 
    	
    CICLODIV: ;inizio del ciclo 
    
    	CMP AX,9 ;confronto il registro AX con 9 
    	JG DIVISIONE ;se il numero è maggiore di 9 significa che è almeno a due cifre quindi bisogna dividere per 10 
    	JLE NODIVISIONE ;se il numero è minore o uguale a nove si rappresenta di sicuro in un byte e salto il ciclo
    	
    	DIVISIONE: 
    
    		;nel registro AX c'è il numero che devo dividere
    		DIV BX ;divido per 10 che è contenuto in BX --> AX QUOZIENTE E DX RESTO!!!
    		PUSH DX ;metto nello stack il resto della divisione che è contenuto in DX 
    		;non tocco il registro ax in quanto contiene già il probabile successivo numero che deve dividere
    		
    		ADD CONTA,1 ;incremento la variabile contatore 
    		
    		JMP CICLODIV ;salto incondizionato a "CICLODIV" così da ripetere il ciclo
    		
    	NODIVISIONE:
    		
    		MOV AH,09H ;richiesta per la stampa di una stringa
    		LEA DX,STRINGA ;carico la stringa in DX
    		INT 21H	;interrupt che permette la stampa della stringa
    		
    		MOV NMAX,AL ;salvo il NMAX il contenuto di AL 
    		
    		CMP CONTA,0 
    		JZ STAMPA1 
    		JNZ STAMPA2
    		
    		STAMPA1:
    			MOV AH,02H ;richiesta per la stampa di un singolo carattere
    			MOV DL,NMAX ;sposto in DL il carattere 
    			ADD DL,30H ;conversione 
    			INT 21H ;interrupt che permette di stampa il carattere
    			JMP EXIT ;salto incodizionato alla fine del programma
    			
    		STAMPA2:
    			
    			MOV AH,02H  ;richiesta per la stampa di un singolo carattere
    			MOV DL,NMAX ;sposto in DL il carattere 
    			ADD DL,30H ;conversione 
    			INT 21H ;interrupt che permette di stampa il carattere
    			
    			XOR AX,AX ;azzero il registro AX per sicurezza
    			xor bx,bx
    			
    			CICLOSTAMPA: ;ciclo per la stampa di un numero a più cifre
    			
    				POP BX ;tiro fuori il numero dallo stack in DX 
    				
    				MOV AH,02H ;richiesta per la stampa di un singolo carattere
    				MOV DL,BL
    				ADD DL,30H 
    				INT 21H 
    				
    				SUB CONTA,1 ;decremento conta di 1 
    				
    				CMP CONTA,0
    				JZ EXIT ;se la variabile conta è uguale a zero allora ha finito i numeri e quindi esco dal ciclo
    				JNZ CICLOSTAMPA ;se la variabile non è zero allora ricomincio il ciclo per la stampa 
    				
    				
    EXIT:
    MOV AH,4CH ;richiesta per restituire il controllo al DOS
    INT 21H ;interrupt che permette di restituire il controllo al DOS
    
    CODE ENDS ;fine del segmento del codice
    END INIZIO ;chiusura etichetta che indica l'inizio del programma
    
  • Re: Gestire numeri con più cifre 8086[Risolto]

    Prima di dividere devi azzerare DX perché il dividendo è a 32 bit e la parte alta è in DX
  • Re: Gestire numeri con più cifre 8086[Risolto]

    Ho corretto il codice come dici tu ed effettivamente funziona!!
    Però non ho ben capito il motivo...

    Inviato dal mio HUAWEI P7-L10 utilizzando Tapatalk
  • Re: Gestire numeri con più cifre 8086[Risolto]

    Però non ho ben capito il motivo...
    Più che altro non l'hai studiato ...

    La divisione opera con

    Dividendo / Divisore

    per ottenere

    Quoziente e Resto

    Hai due possibilità di effettuare la divisione

    (Byte Form)
    Il Dividendo è in AX e il Divisore un valore a 8 bit - Il Quoziente sarà in AL e il Resto in AH

    (Word Form)
    Il Dividendo è in DX:AX e il Divisore un valore a 16 bit - Il Quoziente sarà in AX e il Resto in DX

    Nel tuo codice hai usato l'ultima forma (Word Form) perché hai diviso per BX (che è un valore a 16 bit).
    Quindi la CPU si attende il Dividendo nei registri DX:AX nel formato H:L e ottieni Quoziente in AX e Resto in DX.
  • Re: Gestire numeri con più cifre 8086[Risolto]

    Si ho usato la seconda opzione per la divisione...ecco il sorgente:
    
    DATA SEGMENT PUBLIC
    
    	STRINGA DB "Numero: ",'$'
    	NUMERO DW 3219 ;variabile che può contentere un numero qualsiasi
    	DIECI DW 10   ;divisore è 10 perchè cos' ottengo le singole cifre da stampare
    	CONTA DB 0 ;variabile contatore 
    	NMAX DB ?
    	
    	
    DATA ENDS ;fine del segmento dei dati
    
    CODE SEGMENT
    
    	ASSUME CS:CODE,DS:DATA 
    	
    INIZIO: ;inizio del programma
    	
    	MOV AX,DATA
    	MOV DS,AX ;carico i dati nel segmento dei dati
    
    	;AZZERO IL REGISTRO AX E BX poichè li uso per effettuare la serie di divisioni per ottenere così la stampa del numero finale.
    	
    	XOR AX,AX ;azzero il registro AX
    	XOR BX,BX ;azzero il registro BX
    	
    	MOV AX,NUMERO ;metto in AX il numero da dividere
    	MOV BX,DIECI ;metto in BX il numero che deve dividere cioè 10 
    	 
    	
    CICLODIV: ;inizio del ciclo 
    
    	CMP AX,9 ;confronto il registro AX con 9 
    	JG DIVISIONE ;se il numero è maggiore di 9 significa che è almeno a due cifre quindi bisogna dividere per 10 
    	JLE NODIVISIONE ;se il numero è minore o uguale a nove si rappresenta di sicuro in un byte e salto il ciclo
    	
    	DIVISIONE: 
    		MOV DH,00H
    		MOV DL,00H
    		;nel registro AX c'è il numero che devo dividere
    		DIV BX ;divido per 10 che è contenuto in BX --> AX QUOZIENTE E DX RESTO!!!
    		PUSH DX ;metto nello stack il resto della divisione che è contenuto in DX 
    		;non tocco il registro ax in quanto contiene già il probabile successivo numero che deve dividere
    		
    		ADD CONTA,1 ;incremento la variabile contatore 
    		
    		JMP CICLODIV ;salto incondizionato a "CICLODIV" così da ripetere il ciclo
    		
    	NODIVISIONE:
    		
    		MOV AH,09H ;richiesta per la stampa di una stringa
    		LEA DX,STRINGA ;carico la stringa in DX
    		INT 21H	;interrupt che permette la stampa della stringa
    		
    		MOV NMAX,AL ;salvo il NMAX il contenuto di AL 
    		
    		CMP CONTA,0 
    		JZ STAMPA1 
    		JNZ STAMPA2
    		
    		STAMPA1:
    			MOV AH,02H ;richiesta per la stampa di un singolo carattere
    			MOV DL,NMAX ;sposto in DL il carattere 
    			ADD DL,30H ;conversione 
    			INT 21H ;interrupt che permette di stampa il carattere
    			JMP EXIT ;salto incodizionato alla fine del programma
    			
    		STAMPA2:
    			
    			MOV AH,02H  ;richiesta per la stampa di un singolo carattere
    			MOV DL,NMAX ;sposto in DL il carattere 
    			ADD DL,30H ;conversione 
    			INT 21H ;interrupt che permette di stampa il carattere
    			
    			XOR AX,AX ;azzero il registro AX per sicurezza
    			xor bx,bx
    			
    			CICLOSTAMPA: ;ciclo per la stampa di un numero a più cifre
    			
    				POP BX ;tiro fuori il numero dallo stack in DX 
    				
    				MOV AH,02H ;richiesta per la stampa di un singolo carattere
    				MOV DL,BL
    				ADD DL,30H 
    				INT 21H 
    				
    				SUB CONTA,1 ;decremento conta di 1 
    				
    				CMP CONTA,0
    				JZ EXIT ;se la variabile conta è uguale a zero allora ha finito i numeri e quindi esco dal ciclo
    				JNZ CICLOSTAMPA ;se la variabile non è zero allora ricomincio il ciclo per la stampa 
    				
    				
    EXIT:
    MOV AH,4CH ;richiesta per restituire il controllo al DOS
    INT 21H ;interrupt che permette di restituire il controllo al DOS
    
    CODE ENDS ;fine del segmento del codice
    END INIZIO ;chiusura etichetta che indica l'inizio del programma
    
    Grazie e ciaoo
Devi accedere o registrarti per scrivere nel forum
8 risposte