libasm/ft_atoi_base_bonus.s

119 lines
1.8 KiB
ArmAsm

global ft_atoi_base
extern malloc ; for LUT
extern free ; for LUT
ft_atoi_base:
push rbx
push r12 ; sign
push r13 ; base
push r14 ; return value
push r15 ; base LUT
push rdi
push rsi
mov rdi, 256
call malloc WRT ..plt
mov r15, rax
pop rsi
pop rdi
cmp r15, 0
jz .malloc_error
xor rcx, rcx
.init_lut_loop: ; sets LUT to 0
cmp rcx, 256
je .set_base
mov byte [r15 + rcx], -1
inc rcx
jmp .init_lut_loop
.set_base:
xor rcx, rcx ; rcx is base length/count
.set_base_loop:
cmp byte [rsi + rcx], 0 ; end of base
je .check_base_len
cmp byte [rsi + rcx], 43 ; check forbidden chars
je .error
cmp byte [rsi + rcx], 45
je .error
cmp byte [rsi + rcx], 126
jg .error
cmp byte [rsi + rcx], 33
jl .error
xor rbx, rbx
mov bl, byte [rsi + rcx]
cmp byte [r15 + rbx], -1 ; check double digits in base
jne .error
mov rdx, rcx
mov byte [r15 + rbx], dl ; set base number in LUT
inc rcx
jmp .set_base_loop
.check_base_len:
cmp rcx, 2
jl .error
mov r13, rcx
xor rcx, rcx ; index = 0
xor r14, r14 ; number = 0
mov r12, 1 ; sign = 0
.skip_white_spaces:
cmp byte [rdi + rcx], 33
jle .skip_once
cmp byte [rdi + rcx], 126
jg .skip_once
jmp .get_sign_loop
.skip_once:
inc rcx
jmp .skip_white_spaces
.get_sign_loop:
cmp byte [rdi + rcx], 43
je .pos_once
cmp byte [rdi + rcx], 45
je .neg_once
jmp .get_number_loop
.neg_once:
neg r12
.pos_once:
inc rcx
jmp .get_sign_loop
.get_number_loop:
xor rbx, rbx
mov bl, byte [rdi + rcx]
cmp bl, 0
je .done
mov bl, byte [r15 + rbx] ; set bl to base index
cmp bl, -1
je .done
mov rax, r14
mul r13
mov r14, rax
add r14, rbx
inc rcx
jmp .get_number_loop
.malloc_error:
mov rax, 0
jmp .exit
.error:
mov r14, 0
.done:
mov rdi, r15
call free WRT ..plt
mov rax, r14
cmp r12, 1 ; check sign
je .exit
neg rax
.exit:
pop r15
pop r14
pop r13
pop r12
pop rbx
ret