; File: toupper2.asm last updated 09/26/2001
;
; Convert user input to upper case.
; This version uses some special looping instructions.
;
; Assemble using NASM:  nasm -f elf toupper2.asm
; Link with ld:  ld toupper2.o 
;

%define STDIN 0
%define STDOUT 1
%define SYSCALL_EXIT  1
%define SYSCALL_READ  3
%define SYSCALL_WRITE 4
%define BUFLEN 256


	SECTION	.data			; initialized data section

msg1:	db "Enter string: " 		; user prompt 
len1: 	equ $-msg1			; length of first message

msg2:   db "Original: "			; original string label 
len2:	equ $-msg2			; length of second message

msg3:	db "Convert:  "			; converted string label
len3:	equ $-msg3

msg4:	db 10, "Read error", 10		; error message
len4:	equ $-msg4


	SECTION .bss			; uninitialized data section
buf:	resb BUFLEN			; buffer for read
newstr:	resb BUFLEN			; converted string
rlen:	resb 4				; length


	SECTION .text			; Code section.
	global	_start			; let loader see entry point

_start:	nop				; Entry point.
start:					; address for gdb
	; prompt user for input
	;
	mov	eax, SYSCALL_WRITE	; write function
	mov	ebx, STDOUT		; Arg1: file descriptor
	mov	ecx, msg1		; Arg2: addr of message
	mov	edx, len1		; Arg3: length of message
	int	080h			; ask kernel to write

	; read user input
	;
	mov	eax, SYSCALL_READ	; read function
	mov 	ebx, STDIN		; Arg 1: file descriptor
	mov	ecx, buf		; Arg 2: address of buffer
	mov	edx, BUFLEN		; Arg 3: buffer length
	int	080h

	; error check
	;
	mov	[rlen], eax		; save length of string read
	cmp	eax, 0			; check if any chars read
	jg	read_OK			; >0 chars read = OK
	mov	eax, SYSCALL_WRITE	; ow print error
        mov     ebx, STDOUT
	mov	ecx, msg4
	mov	edx, len4
	int	080h
	jmp	exit			; skip over rest
read_OK:


	; Loop for upper case conversion
	; assuming rlen > 0
	;
L1_init:
	mov	ecx, [rlen]		; initialize count
	mov	esi, buf		; point to start of buffer
	mov	edi, newstr		; point to start of new string
	cld				; clear dir. flag, inc pointers

L1_top:
	lodsb				; load al w char in [esi++]
	cmp	al, 'a'			; less than 'a'?
	jb	L1_cont	
	cmp	al, 'z'			; more than 'z'?
	ja	L1_cont
	and	al, 11011111b		; convert to uppercase

L1_cont:
	stosb				; store al in [edi++]
	loop	L1_top			; loop if --ecx > 0
L1_end:


	; print out user input for feedback
	;
	mov	eax, SYSCALL_WRITE	; write message
	mov	ebx, STDOUT
	mov	ecx, msg2
	mov 	edx, len2
	int	080h

	mov	eax, SYSCALL_WRITE	; write user input 
	mov	ebx, STDOUT
	mov	ecx, buf
	mov	edx, [rlen]
	int	080h

	; print out converted string
	;
	mov	EAX, SYSCALL_WRITE	; write message
	mov	EBX, STDOUT
	mov	ECX, msg3
	mov 	EDX, len3
	int	080h

	mov	EAX, SYSCALL_WRITE	; write out string
	mov	EBX, STDOUT
	mov	ECX, newstr
	mov	EDX, [rlen]
	int	080h


	; final exit
	;
exit:	mov	EAX, SYSCALL_EXIT	; exit function
	mov	EBX, 0			; exit code, 0=normal
	int	080h			; ask kernel to take over
