; Esercizio 8
;
; La locazione di nome ENNE contiene un numero unsigned N > 0.
; Nella doppia locazione di nome FATT viene lasciato il fattoriale di N.
; Nella locazione di nome ERROR viene lasciato 1 o 0 a seconda che si sia
; avuto o no traboccamento nel calcolo del fattoriale.
;
.MODEL	small
.stack	100h

.data 
    ENNE 	db 1 ; Numero N di cui calcolare il fatt.
    FATT 	dw 0 ; Risultato del fattoriale
    ERROR 	db 0
    msg0	db "Calcolo del Fattoriale.$"
    msg1	db 13,10,"Inserire un numero [1-9, 0 per uscire]: $"
    err_msg db "Risultato del fattoriale non rappresentabile.$"
    fat_msg db "Il fattoriale e`: $"
    
.code

include ..\include\stdio.inc
include ..\include\utils.inc
include ..\include\ioNumbers.inc

start:
	call init
	
    ; Inizio esercizio
	lea	dx, msg0	; Stampa il messaggio iniziale con cui
	call print		;  chiede l'immissione di un numero
inizio:	
	lea	dx, msg1	; Stampa il messaggio iniziale con cui
	call print		;  chiede l'immissione di un numero
	mov bl, '0'
	mov bh, '9'
	call get1charInRange
	call output
	call newline
	sub al, '0'
	jz fine
	mov ENNE, al
	mov cl, ENNE
	call fattoriale
	cmp ch,1
	jne stampa_risultato
	
	lea dx, err_msg; mov dx, offset err_msg
	call print
	jmp inizio
	
stampa_risultato:
	mov FATT, ax
	lea dx, fat_msg
	call print
	mov ax, fatt
	call printBin16toDecASCII
	call newline
	jmp inizio

fine:
    ; Fine esercizio ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
    call pressKeyAndExit

	;;; Procedure utilizzate

; fattoriale - Calcola il fattoriale di un numero
; Parametri in ingresso
;   CL - Numero di cui calcolare il fattoriale
; Ritorna il valore calcolato in DX,AX
; Se il fattoriale non e' calcolabile perche' il valore e` piu' grande di 64k
; allora CH viene impostato a 1.
fattoriale proc
    mov ch, 0       ; CH <- 0 (contiente il flag di errore)
    mov dx, 0		; DX <- 0 (per 
    mov ax, 1       ; AX <- 1 : DX,AX = 1 e` primo moltiplicatore utilizzato
ciclo:
    mul cx          ; (dx ax) = ax * cx
    jc traboccamento; se CF = 1 allora ho errore
    loop ciclo      ; Decremento il moltiplicatore (dec cx , jnz ciclo)
        			; Se non e' nullo proseguo con le moltiplicazioni
    mov ch,0
    jmp fine_fatt   ; Salto alla fine
traboccamento:
    mov ch, 1
fine_fatt:
	Ret
fattoriale endp


; outbin
;   Converte il numero binario contenuto in AX e lo stampa a video
;   Nessun parametro ritornato.
outbin proc
	push ax
	add al,30h
	call output
	pop ax
	Ret
outbin endp

; get1charInRange
;   Accetta 1 carattere in ingresso
;   Parametri in ingresso:
;     BL estremo inferiore dell'insieme dei codici ASCII accettati
;	  BH estremo superiore dell'insieme dei codici ASCII accettati
;   Il carattere e` ritornato nel registro AL
get1charInRange proc
inKey:
	call input
	cmp	al, bl
	jb  inkey
	cmp al,bh
	ja  inkey
	Ret
get1charInRange endp

end start ; set entry point and stop the assembler.