	.section	.text
	.global	atoi
	.type	atoi, @function
atoi:
	pushl	%ebp
	movl	%esp, %ebp
	subl	$32, %esp		# Allocate space
	movl	$1, -16(%ebp)		# any = one
	movl	$0, -20(%ebp)		# acc = zero
	movl	$-1, -24(%ebp)		# cutoff = 4294967295
	cmpl	$1, 20(%ebp)
	jbe	invalid			# base < 2
	cmpl	$36, 20(%ebp)
	jbe	prepare_to_skip_space	# base > 36
invalid:
	movl	$-22, %eax		# Return -EINVAL
	jmp	end
prepare_to_skip_space:
	movl	$1, -8(%ebp)		# index = 1
	jmp	skip_space
skip_the_next_space:
	addl	$1, -8(%ebp)		# index += 1
skip_space:
	movl	8(%ebp), %edx		# Load string
	movl	-8(%ebp), %eax		# Load index
	addl	%edx, %eax		# %eax = string + index
	movzbl	(%eax), %eax		# Load address of byte
	cmpb	$32, %al
	je	skip_the_next_space	# string[index] == space
	movl	-24(%ebp), %eax
	movl	$0, %edx
	divl	20(%ebp)
	movl	%edx, -28(%ebp)		# cutlim = cutoff % base
	movl	-24(%ebp), %eax
	movl	$0, %edx
	divl	20(%ebp)
	movl	%eax, -24(%ebp)		# cutoff /= base
	movl	8(%ebp), %edx
	movl	-8(%ebp), %eax
	addl	%edx, %eax
	movzbl	(%eax), %eax
	movb	%al, -1(%ebp)		# ch = string[index]
	jmp	while_less_than_length
is_ch_a_number:
	cmpb	$47, -1(%ebp)
	jbe	is_ch_an_uppercase	# ch <= 47
	cmpb	$57, -1(%ebp)
	ja	is_ch_an_uppercase	# ch > 57 (9)
	subb	$48, -1(%ebp)		# ch -= 48 (0)
	jmp	is_ch_over_base
is_ch_an_uppercase:
	cmpb	$64, -1(%ebp)
	jbe	is_ch_a_lowercase	# ch <= 64
	cmpb	$90, -1(%ebp)
	ja	is_ch_a_lowercase	# ch > 90 (Z)
	subb	$55, -1(%ebp)		# ch -= 55
	jmp	is_ch_over_base
is_ch_a_lowercase:
	cmpb	$96, -1(%ebp)
	jbe	is_any_zero		# ch <= 96
	cmpb	$122, -1(%ebp)
	ja	is_any_zero		# ch > 122 (z)
	subb	$87, -1(%ebp)		# ch -= 87
is_ch_over_base:
	movzbl	-1(%ebp), %eax
	cmpl	20(%ebp), %eax
	jnb	is_any_zero
	cmpl	$0, -16(%ebp)		# Load and compare any
	je	assign_any_zero		# any == 0
	movl	-20(%ebp), %eax		# Load acc
	cmpl	%eax, -24(%ebp)		# Load and compare cutoff
	jb	assign_any_zero		# acc > cutoff
	movl	-20(%ebp), %eax		# Load acc
	cmpl	-24(%ebp), %eax		# Load and compare cutoff
	jne	increase_acc		# acc != cutoff
	movzbl	-1(%ebp), %eax		# Load ch
	cmpl	%eax, -28(%ebp)		# Load and compare ch
	jnb	increase_acc		# ch <= cutlim
assign_any_zero:
	movl	$0, -16(%ebp)
	jmp	next_ch
increase_acc:
	movl	$1, -16(%ebp)		# any = 1
	movl	-20(%ebp), %eax		# Load acc
	imull	20(%ebp), %eax		# Load and multiply base with acc
	movl	%eax, -20(%ebp)		# Save it to acc
	movzbl	-1(%ebp), %eax
	addl	%eax, -20(%ebp)		# acc += ch
next_ch:
	addl	$1, -8(%ebp)		# index += 1
	movl	8(%ebp), %edx		# Load string
	movl	-8(%ebp), %eax		# Load index
	addl	%edx, %eax		# %eax = string + index
	movzbl	(%eax), %eax		# Get address of byte
	movb	%al, -1(%ebp)		# ch = string[index]
while_less_than_length:
	movl	8(%ebp), %eax		# Load string
	movzbl	(%eax), %eax		# Get address of string
	movzbl	%al, %eax
	cmpl	-8(%ebp), %eax
	jnb	is_ch_a_number		# index > string[0]
	jmp	is_any_zero
is_any_zero:
	cmpl	$0, -16(%ebp)		# Load any
	jne	is_remain_not_null	# any != 0
	movl	16(%ebp), %eax		# Load result
	movl	$-1, (%eax)		# *result = 4294967295
	movl	$-34, %eax		# Return -ERANGE
	jmp	end
is_remain_not_null:
	cmpl	$0, 12(%ebp)		# Load and compare remain
	je	assign_result		# remain == 0
	movl	8(%ebp), %eax		# Load string
	movzbl	(%eax), %eax		# Get address of string
	movl	-8(%ebp), %edx		# Save it
	movl	%edx, %ecx
	subl	%ecx, %eax		# %ecx = string - index
	movl	%eax, %edx
	movl	12(%ebp), %eax		# Load remain
	movb	%dl, (%eax)		# remain[0] = string[0] - index
	movl	$1, -12(%ebp)		# index2 = 1
	jmp	copy_remain
copy_remain_byte:
	movl	8(%ebp), %edx		# Load string
	movl	-8(%ebp), %eax		# Load index
	addl	%edx, %eax		# %eax = string + index
	movl	12(%ebp), %ecx		# Load remain
	movl	-12(%ebp), %edx		# Load index2
	addl	%ecx, %edx		# %edx = remain + index2
	movzbl	(%eax), %eax		# Get address of byte in string
	movb	%al, (%edx)		# Copy it to address of byte in remain
	addl	$1, -8(%ebp)		# index += 1
	addl	$1, -12(%ebp)		# index2 += 1
copy_remain:
	movl	8(%ebp), %eax		# Load string
	movzbl	(%eax), %eax		# Get address of string
	movzbl	%al, %eax
	cmpl	-8(%ebp), %eax		# index <= string[0]
	jnb	copy_remain_byte	# if not bigger
assign_result:
	movl	16(%ebp), %eax		# Load result
	movl	-20(%ebp), %edx		# Load acc
	movl	%edx, (%eax)		# Copy acc to address of result
	movl	$0, %eax		# Return 0
end:
	movl	%ebp, %esp		# Deallocate space
	popl	%ebp
	ret
