; Assemblatore NASM 2.07
;
; convert a decimal ASCII string in a 16-bit unsigned int
; the string is read from std input
;
	global _start
 
section .data
	buffer	resb	32
	string	resb	32 

	msg	db	'the char pointed to by ESI is: '
	number	db	'0000'
		db	0ah,0

section .text
 
_start:
	mov	ecx,buffer
	mov	edx,32
	call	read

	mov	al,0ah
	mov	edx,buffer
	call	strlen			; ECX=string lenght
	mov	byte [buffer+ecx],0	; make ASCIIZ
	mov	edx,buffer
	call	str2uint16	; AX=binary number

	mov	edx,string
	call	bin2dec16	; EXC=length
	mov	byte [edx+ecx],0ah
	mov	byte [edx+ecx+1],0
	call	printasciiz

	; now print the char pointed to by ESI (in hex)

	mov	al,[esi]
	xor	ah,ah
	mov	edx,number
	call	bin2hex16
	mov	edx,msg
	call	printasciiz
 
exit:
	mov	eax, 01h ; exit()
	xor	ebx, ebx ; errno
	int	80h



; FUNCTION: str2uint16 (V0.2)
; converte una stringa ASCIIZ decimale in un numero intero
; a 16 bit senza segno
;
; Parametri:
;	EDX = indirizzo del buffer ASCII
; Return:
;	AX = numero binario 16 bit senza segno
;	ESI = puntatore al primo char non valido (oppure al NULL)
;
section .data
	pow10_16 dw	1,10,100,1000,10000

section .text
str2uint16:
	push	ebx
	push	ecx
	push	edx
	push	edi
	mov	esi,edx
	mov	ecx,0		; contatore digits sullo stack
.loop1:
	xor	ah,ah
	mov	al,[esi]	; carica la cifra decimale
	cmp	al,0
	je	.end
	cmp	al,'0'
	jb	.notvalid
	cmp	al,'9'
	ja	.notvalid
	sub	al,30h
	inc	esi
	push	ax
	inc	ecx
	cmp	ecx,5
	jbe	.loop1
.overflow:
	pop	ax
	dec	ecx		; converte solo le prime 5 cifre
.notvalid:
.end:	
	mov	di,0		; totalizzatore
	mov	ebx,pow10_16
	cmp	ecx,0
	je	.exit
.loop2:
	pop	ax
	mov	dx,[ebx]	; carica potenza del 10
	mul	dx		; mult cifra per potenza del 10 dx:ax
	add	di,ax
	inc	ebx
	inc	ebx
	loop	.loop2
.exit:
	mov	ax,di
	pop	edi
	pop	edx
	pop	ecx
	pop	ebx
	ret

; FUNCTION: bin2dec16
; converte un numero binario a 16 bit in una stringa ASCII decimale
; Parametri:
;	AX  = numero da stampare
;	EDX = indirizzo del buffer ASCII (5 cifre)
; Return:
;	ECX = lunghezza della strinag
bin2dec16:
        push    eax
        push    ebx
        push    edx
        push    esi
        mov     esi,edx
        mov     ecx,0   ; contatore cifre significative 
        mov     bx,10   ; divisore
.loop1:
        xor     dx,dx	; DX:AX = dividendo
        div     bx      ; ax=quoziente, dx=resto
        add     dl,30h
        push    dx      ; salva il digit sullo stack
        inc     ecx     ; incrementa contatore cifre
        cmp     ax,0
        jne     .loop1

        mov     eax,ecx ; salva numero digits

.loop2:		;recupera i digit dallo stack in ordine inverso (almeno 1)
        pop     dx
        mov     [esi],dl
        inc     esi
        loop    .loop2
        mov     ecx,eax ; return ECX
        pop     esi
        pop     edx
        pop     ebx
        pop     eax
        ret

; FUNCTION: bin2hex16
; converte il numero a 16 bit in AX in 4 cifre hex
; Parametri:
;	AX  = numero binario
;	EDX = buffer di 4 cifre hex (es: XXXX)
; Return:
;	none
bin2hex16:
	push	eax
	push	ebx
	push	ecx
	push	edx
	push	edi
	mov	edi,edx	; usa edi per indirizzare il buffer
	add	edi,3
	mov	cx,4
.loop1:
	xor	dx,dx		; DX:AX = dividendo
	mov	bx,16		; divisore
	div	bx		; AX=quoziente, DX=resto
	add	dl,30h
	cmp	dl,'9'
	jbe	.digit
	add	dl,7
.digit:
	mov	[edi],dl
	dec	edi
	loop	.loop1
	
	pop	edi
	pop	edx
	pop	ecx
	pop	ebx
	pop	eax
	ret


; FUNCTION: printasciiz
; stampa la stringa ASCIIZ in ingresso. La stringa è terminata da un NULL byte
; Parametri:
;	EDX = indirizzo della stringa ASCIIZ
; Return:
;	none
;
printasciiz:
	push	eax
	push	ecx
	push	edx
	mov	al,0
	call	strlen	; ecx=length
	mov	eax,ecx	; scambia ecx ed edx
	mov	ecx,edx	; indirizzo buffer in ecx
	mov	edx,eax	; length in edx
	call	write
	pop	edx
	pop	ecx
	pop	eax
	ret


; FUNCTION: strlen
; calcola la lunghezza della stringa terminata dal char AL
; Parametri:
;	AL  = carattere terminatore
;	EDX = indirizzo della stringa
; Return:
;	ECX = lunghezza stringa
strlen:
	push	eax
	push	edx
	push	esi
	mov	esi,edx	; EDX=start string
.loop1:
	mov	ah,[esi]
	cmp	ah,al
	je	.end
	inc	esi
	jmp	.loop1
.end:
	mov	ecx,esi		; ECX=end string
	sub	ecx,edx		; sottrae dalla fine del buffer l'inizio
	pop	esi
	pop	edx
	pop	eax
	ret


; FUNCTION: read
; legge un buffer da standard input
; Parametri:
;	ECX = indirizzo del buffer
;	EDX = lunghezza del buffer
;
read:
	push	eax
	push	ebx
	mov	eax, 03h		; read()
	mov	ebx, 00h		; stdin
	int	80h
	pop	ebx
	pop	eax
	ret

; FUNCTION: write
; scrive un buffer su standard input
; Parametri:
;	ECX = indirizzo del buffer
;	EDX = lunghezza del buffer
;
write:
	push	eax
	push	ebx
	mov	eax, 04h		; write()
	mov	ebx, 01h		; stdout
	int	80h
	pop	ebx
	pop	eax
	ret

