;
; Esame 2008-12-05
;
; Utilizzando il linguaggio Assembler 8086 e l'insieme di interrupt disponibili
; sui processori compatibili x86, si realizzi il programma che faccia quanto 
; segue:
; 1. dichiara nel segmento dati un vettore avente nome simbolico VETT avente 10
;    elementi di ampiezza un byte;                                         (1pt)
; 2. per 10 volte:
;    a. chiede all'utente di digitare da tastiera un numero compreso
;       tra 40 e 99 e lo converte in binario;                              (2pt)
;    b. memorizza tale numero in un elemento di VETT;                     (1pt)
;    c.	stampa a video la rappresentazione esadecimale, ottale e binaria di tale
;       numero;                                                            (3pt)
;    d. quindi si posiziona sulla linea successiva;                        (1pt)
; 3. terminata l'immissione degli elementi del vettore, successivamente:
;    a. calcola la media dei numeri inseriti memorizza la parte intera
;       nella locazione avente nome simbolico MI e la parte parte frazionaria
;       nella locazione avente nome simbolico MD;                          (4pt)
;    b.	stampa a video tale media tale media come un numero decimale razionale
;       avente due cifre decimali (esempio 12,34).                        (3pt)


.MODEL	small
.stack	100h
.data 
; 1. dichiara nel segmento dati un vettore di nome simbolico VETT avente 10
;    elementi di ampiezza un byte;
	VETT	db 10 dup(?)
	; Messaggio di richiesta inserimento numero;
	Ins_msg db "Inserisci un numero [40-99]: $"
	; Variabili contententi la media;
	MI		db 0
	MD		db 0
	; Messaggio di fine programma.
	pkey	db 13,10,10,"Press key to exit...$"
.code
start:
	mov	 ax,@data		; Get the address of the data segment
	mov	 ds,ax			; Set the DS segment

	; Inizio esercizio
	
	; 2. per 10 volte:
	mov  cx,10	; Inizializza il registro contatore
	mov  si,0	; Inizializza il registro indice per puntare agli elem. di VETT
ciclo1:	
	; 2a. chiede all'utente di digitare da tastiera un numero da tastiera
	call insNumero		; Chiamata al sottoprogramma insNumero che
						; restituisce un numero binario memorizzato in AL

	; 2b. memorizza tale numero in un elemento di VETT1;
	mov  VETT[SI], al

	; 2c.	stampa a video
	call stampaSep
	call stampaHex	; la rappresentazione esadecimale,
	call stampaSep
	call stampaOct	; ottale, e
	call stampaSep 
	call stampaBin	; binaria di tale numero;

	; 2d. quindi si posiziona sulla linea successiva;
	call newline
	inc si
	dec cx
	jnz ciclo1

	; 3.
	; 3a. calcola la media dei numeri inseriti
	mov  dx,0	; DX <- 0, DX sara' usato per contenere la somma corrente degli
				;           elementi del vettore, pertanto viene azzerato
	mov  cl,10  ; Numero di iterazioni per eseguire la somma degli elem. del vett.
	mov  si,0  ; Indice del vettore
ciclo2:
	mov  al,VETT[SI]	; AL <- VETT[SI], copia in AL l'i-esimo elemento del vett. 
	cbw					; converte AL in AX
	add  dx,ax			; DX = DX + AX
	inc  si				; incrementa SI per puntare al successivo elem. del vett.
	dec  cl				; Decrementa CL, indice del ciclo
	jnz  ciclo2			; Se CL non e` zero torna all'inizio del ciclo
	mov  ax,dx			; AX <- DX, AX contiene il risultato della somma
	; Si noti che al piu` la somma vale 990 ed e` quindi rappresentabile in un 
	; registro a 16 bit come AX - Quando calcoliamo la media la divisione
	; per 10 produce un quoziente avente al massimo valore 99 e rappresentabile
	; in un registro ad 8 bit come AL.
	; Pertanto in questo caso e` sufficiente fare AL = AX / 10
	mov  bl,10
	div  bl				; AL = AX / BL con resto in AH
	mov  MI,al			; Salve il quoziente in MI
	mov  MD,ah			; Salva il resto in MD

	; 3b. stampa a video tale media
	mov  al,MI
	call bin2DecAscii
	mov  al,','
	call output
	mov  al,MD
	call bin2DecAscii
		
	; Fine esercizio
	mov		dx,offset pkey
	call    print
    call	input
	mov		ax, 4C00h
	int		21h

insNumero proc
	push bx				; Salvataggio registri utilizzati
	push dx
	lea  dx, Ins_msg	; Stampa a video la stringa 
	call print			; che chiede di inserire un numero
inkeyD:					; Immissione decine
	call input			; Attende l'inserimento di un carattere
	cmp  al,'4'			; Confronta AL con '4':
	jb   inkeyD			; se inferiore torna ad aspettare l'immissione di un carattere
	cmp  al,'9'			; Confronta AL con '9':
	ja   inkeyD			; se superiore torna ad aspettare l'immissione di un carattere
	call output			; Eco a video del primo carattere inserito
	sub  al,'0'			; Conversione da numero decimale ASCII a binario
	mov  bl,10			; Conversione a decine
	mul  bl				; ax = al * bl
	mov  bx, ax			; Memorizza il risultato in BX
inkeyU:					; Immissione unita`
	call input			; Attende l'inserimento di un carattere
	cmp  al,'0'			; Confronta AL con '0':
	jb   inkeyU			; se inferiore torna ad aspettare l'immissione di un carattere
	cmp  al, '9'		; Confronta AL con '9':
	ja   inkeyU			; se superiore torna ad aspettare l'immissione di un carattere
	call output			; Eco a video del primo carattere inserito
	sub  al, '0'		; Conversione da numero decimale ASCII a binario
	mov  ah, 0			;
	add	 ax, bx			; Somma le unita` alle decine precedentemente calcolate
	pop  dx				; Ripristino registri utilizzati,
	pop  bx				; il valore di ritorno e` contenuto nel registro AX.
	ret
insNumero endp

stampaHex proc
	push ax			; Salvataggio registri
	push bx
	mov  ah,0		; Azzeramento AH per far coincidere AL con AX
	mov  bl,16		; Divisore
	div  bl			; AL = AX / BL, resto in AH
	call hexoutput	; Output della cifra esadecimale
	mov  al, ah
	call hexoutput
	mov  al, 'h'	; Suffisso del numero
	call output
	pop  bx
	pop  ax
	Ret
stampaHex endp

hexoutput proc
	push ax
	cmp  al,9
	ja	 lettera
numero:
	add  al,30h
	call output
	jmp  fine_hexoutput
lettera:
	add  al,37h
	call output
fine_hexoutput:
	pop  ax
	Ret
hexoutput endp

stampaOct proc
	push ax			; Salvataggio registri
	push bx
	mov  ah,0		; Azzeramento AH per far coincidere AL con AX
	mov  bl,64		; Divisore
	div  bl			; AL = AX / BL, resto in AH
	add	 al,30h
	call output		; Output a video
	mov  al,ah
	mov  ah,0
	mov  bl,8
	div  bl
	add  al,30h
	call output
	mov  al,ah
	add  al,30h
	call output
	mov  al, 'o'	; Suffisso del numero
	call output
	pop  bx
	pop  ax
	Ret
stampaOct endp

stampaBin proc
	push ax
	push cx
	push dx
	mov  dl,al
	mov  cl,8
ciclo_print8Bit:
	shl  dl,1
	jc   print1
	jmp  print0
print1:
	mov  al,'1'
	call output
	jmp  end_ciclo_print8Bit
print0:
	mov  al,'0'
	call output
end_ciclo_print8Bit:
	dec  cl
	jnz  ciclo_print8bit
	pop  dx
	pop  cx
	pop  ax
	Ret
stampaBin endp

stampaSep proc
	push ax
	mov al, 9
	call output
	pop ax
	Ret
stampaSep endp

bin2DecAscii proc
	push ax			; Salvataggio registri
	push bx
	mov  ah,0		; Azzeramento ah, per poter dividere AL
centinaia:			; Centinaia
	mov  bl,100		; Divisore delle centinaia
	div  bl			; AL = AX / BL , resto in AH
	cmp  al,0		; se il risultato e` 0, non stampare nulla
	je   decine		; e passa alle decine
	add  al,30h		; altrimenti converti in numuero binario nel corrispondente
	call output		; carattere ASCII ed invia allo schermo
decine:				; idem per le decine
	mov  al,ah
	mov  ah,0
	mov  bl,10
	div  bl
	cmp  al,0
	je   unita
	add  al,30h
	call output
unita:				; idem per le unita`
	mov  al,ah
	mov  ah,0
	add  al,30h
	call output
	pop  bx
	pop  ax
	Ret
bin2DecAscii endp

include sottoprogrammi.inc
end start