; 
; Esame 2007-12-13
;
; Utilizzando il linguaggio Assembler 8086 e l'insieme di interrupt disponibili sui processori compatibili x86,
; si realizzi il programma che faccia quanto segue:
; 1.	chiede all'utente di digitare da tastiera un numero compreso tra 1 e 5
;       (una cifra codificate ASCII) (1pt);
; 2.	memorizza tale numero all'interno di una variabile avente nome simbolico N,
;       ampia 1 byte (1pt); 
; 3.	per N volte chiede all'utente di inserire due cifre codificate ASCII comprese 
;       tra 00 e 99
;       precedendo ogni richiesta dalla stringa posta su una nuova linea dello schermo
;       avente contenuto 
;       "Inserire il valore n. #: ", dove al posto di # viene stampato l'indice corrente 
;       del numero da inserire (4pt);
; 4.	gli N numeri immessi vengono memorizzati in un vettore VETT1 (1pt);
; 5.	terminata l'immissione degli N numeri, chiama una procedura che riceve 
;       in ingresso
;       l'indirizzo del vettore ed il numero N (3pt), e che per ogni numero inserito calcola:
;   a.	la rappresentazione binaria e la stampa su schermo in binario codificato ASCII (1pt);
;   b.	la rappresentazione binaria del complemento a 1 e la stampa su schermo in binario codificato ASCII (1pt),
;   c.	la rappresentazione binaria del complemento a 2 e la stampa su schermo in binario codificato ASCII (1pt),
; 6.	quindi, per moltiplica per 2 ogni numero inserito e lo memorizza in un vettore VETT2 (2pt);
; 7.	ripete il punto 5 per i vettore 2 (1pt). 
; 
; Esempio di output.
; Inserire numero: 2
; Inserire il valore n.1: 12
; Inserire il valore n.2: 07
; 00001010 11110101 11110100
; 00000111 11111000 11111001
; 00010100 11101011 11101000
; 00001110 11110001 11110010

.MODEL	small
.stack	100h

.data 
    N         db 0
    msgInsN   db "Inserire numero [1-5]: $"
    msgInsVal db 0Dh, 0Ah,"Inserire il valore n.$"
    VETT1     db 5 dup(?)
    VETT2     db 5 dup(?)
    pkey      db 0Dh, 0Ah, "press any key...$"

.stack

.code
start:
	; set segment registers:
    mov ax, @data
    mov ds, ax
    
    ; 1. 
    lea dx, msgInsN     ; Stampa il messaggio che chiede all'utente di
    call stampaStringa  ; inserire un numero.
    mov dl, '1'         ; Attende in ingresso una cifra codificata ASCII
    mov dh, '5'         ; compresa tra '1' e '5'.
    call getASCII
    sub al, 30h         ; Converte la codifica ASCII in binario naturale.
    
    ; 2.
    mov N, al   ; N <- AL
    
    ; 3. e 4.
    mov cl,N    ; CL = Contatore del ciclo da N a 1
    mov si,0    ; SI = indice del vettore VETT1
ciclo3:
    lea dx, msgInsVal   ; Stampa il messaggio che chiede all'utente di
    call stampaStringa  ; di inserire un valore.  
    mov ax, si  
    inc al
    add al, '0'     ; Codifica ASCII di AL (CL)
    call output
    mov al, ':'     ; Stampa il carattere ':'
    call output     ;
    call stampaSpazio
    mov dl, '0'     ; Chiama la procedura getASCII passando
    mov dh, '9'     ; i valori degli estremi dell'intervallo
    call getASCII   ; di caratteri accettati.
    ;Ho acquisito il carattere ASCII corrispondente alle decine.
    sub al, '0'		; Conversione in binario
    ; Conversione in decine.
    mov bl, 10      ; BL <- 10
    mul bl          ; AX = AL * BL = AL (visto che AH = 0 e AL = 0 .. 90
    ; Salva il risultato (decine) in BL
    mov bl, al      ; BL <- AL
    call getASCII	; Attende il carattere corrispondente alle unita`
    sub al, '0'
    add al, bl
    mov VETT1[si], al   ; 4. Copia il numero inserito (presente in AL)
                        ; nell'si-esimo elemento di VETT1.                   
    inc si                    
    dec cl
    jne ciclo3
    
    ; 5.
    lea bx, VETT1
    mov al, N
    call punto5 ; Chiama la procedura specificata al punto 5.
    
    ; 6.
    mov cl, N   ; CL = Contatore del ciclo da N a 0
    mov si, 0   ; SI = indice dei vettori VETT1 e VETT2
ciclo6:
    mov al, VETT1[si]   ; AL <- VETT1[si]
    sal al, 1           ; AL = AL * 2
    mov VETT2[si],al    ; VETT2[si] <- AL
    inc si
    dec cl
    jnz ciclo6
    
    ; 7.
    lea bx, VETT2
    mov al, N
    call punto5 ; Chiama la procedura specificata al punto 5. 
    
    ; Fine esercizio
    lea dx, pkey
    call stampaStringa
    mov ah, 1    ; wait for any key....    
    int 21h
    mov ax, 4c00h ; exit to operating system.
    int 21h    
    
punto5 proc
    push ax
    push cx
    push si
    mov cl, al   ; Inizializza il ciclo di elaborazione dei vettori
    mov si, 0   ; Azzera SI, indice del vettore VETT1.
ciclo5:
    call newline    ; Stampa i caratteri di newline.
    ; 5.a.
    mov al, [BX+SI]   ; al <- [BX+SI] si-esimo elemento della memoria
                        ; indicata dall'indirizzo ds:bx                    
    call bin2ASCII
    
    ; 5.b.
    call stampaSpazio
    not al
    call bin2ASCII
    
    ; 5.c.
    call stampaSpazio
    not al
    neg al
    call bin2ASCII
    
    inc si
    dec cl
    jnz ciclo5
    pop si
    pop cx
    pop ax
    ret
punto5 endp

;
; Procedura per stampare uno spazio.
stampaSpazio proc
    push ax
    mov al, ' '
    call output
    pop ax
    ret
stampaSpazio endp

;
; Procedura per stampare un numero binario contenuto nel registro AL
; in binario codificato ASCII.
bin2ASCII proc
    push ax
    push bx
    push cx
    mov cl, 8
    mov bl, al
ciclobin2ASCII:
    sal bl, 1
    jc  bit1
bit0:
    mov al, '0'
    jmp outASCIIbit
bit1:

    mov al, '1'
outASCIIbit:
    call output
    dec cl
    jnz ciclobin2ASCII
    pop cx
    pop bx
    pop ax
    ret
bin2ASCII endp
    
;
; Procedura per prelevare un carattere da tastiera
; compreso nell'intervallo indicato dai registri DL e DH.
; Il carattere letto e' ritornato tramite AL.
getASCII proc
inASCII:
    call input  ; Attende in ingresso la cifra e controlla che la sua codifica
    cmp al, dl  ; ASCII sia compresa tra il valore contenuto nel registro DL
    jb  inASCII  ;
    cmp al, dh ; ed il valore contenuto nel registro DH.
    ja  inASCII
    call output ; Eco della cifra inserita.
    ret
getASCII endp

;
; Procedura per prelevare un carattere da tastiera    
; Il carattere letto e' restituito in AL.
input proc
   	mov ah, 7
	int 21h
    ret
input endp

;
; Stampa il carattere contenuto in AL
;
output proc
    push ax
    push dx
    mov ah, 2
	mov dl, AL
	int 21h       ; output character.
	pop dx
	pop ax
    ret
output endp

;
; Stampa una stringa terminata da $ indirizzata dal registro DX
;
stampaStringa proc
    push ax
    mov ah, 9
    int 21h
    pop ax
    ret
stampaStringa endp

;
; Stampa il newline
;
newline proc
    push ax
    mov al, 0Ah
    call output
    mov al, 0Dh
    call output
    pop ax
    ret
newline endp

;
; Procedura bin2AAA
; Stampa un numero binario naturale su 8 bit (0..255) in un numero codificato ASCII.
; input: AL = numero da convertire
;
bin2AAA proc
    PUSH AX
    PUSH BX
    MOV AH, 0
    MOV BL, 100    ; BL <- 100
    DIV BL         ; AL = AX / operando (byte) = 0 - 9
                   ; AH = resto                = 0 - 99
    ADD AL, 30h    ; codifica ASCII del quoziente
    CALL output
    MOV AL, AH     ; AL <- AH = 0 - 99
    MOV AH, 0      ; AH <- 0  => AX = 0 - 99
    MOV BL, 10     ; BL <- 10
    DIV BL         ; AL = AX / operando (byte) = 0 - 9
                   ; AH = resto                = 0 - 9
    ADD AL, 30h    ; codifica ASCII del quoziente
    CALL output
    MOV AL, AH     ; AL <- AH = resto
    ADD AL, 30h    ; codifica ASCII del resto
    CALL output
    POP BX
    POP AX
    RET
bin2AAA endp

end start ; set entry point and stop the assembler.