215 lines
3.1 KiB
ArmAsm
215 lines
3.1 KiB
ArmAsm
|
|
global ft_atoi_base
|
|
global check_duplicate_char
|
|
extern ft_strlen
|
|
|
|
section .data
|
|
invalid_chars: db "+- ", 0x0c, 0x0a, 0x0d, 0x09, 0x0b, 0
|
|
whitespaces: db " ", 0x0c, 0x0a, 0x0d, 0x09, 0x0b, 0
|
|
|
|
section .text
|
|
|
|
; checks if a char is in the invalid_chars
|
|
get_char_index:
|
|
xor rax, rax
|
|
push rsi
|
|
|
|
get_char_index_loop:
|
|
cmp dil, [rsi] ;is char invalid
|
|
jz get_char_index_found
|
|
|
|
mov al, [rsi] ; is end of string
|
|
test al, al
|
|
lea rsi, [rsi + 1]
|
|
jne get_char_index_loop
|
|
|
|
mov rax, -1 ;not found and at the end
|
|
pop rsi
|
|
ret
|
|
|
|
get_char_index_found:
|
|
pop rax ;return index of the found char
|
|
sub rsi, rax
|
|
mov rax, rsi
|
|
ret
|
|
|
|
;function that ... it's in the name why are you looking here
|
|
; parameters : the string in rdi
|
|
; returns 1 if there is a duplicate char
|
|
check_duplicate_char:
|
|
|
|
mov al ,[rdi] ; test if \0
|
|
test al, al
|
|
jz no_duplicate
|
|
|
|
push rdi
|
|
mov rsi, rdi
|
|
lea rsi, [rsi + 1]
|
|
mov dil, [rdi]
|
|
call get_char_index
|
|
pop rdi
|
|
|
|
cmp rax, -1 ;is char found
|
|
lea rdi, [rdi + 1]
|
|
jz check_duplicate_char
|
|
mov rax, 1
|
|
ret
|
|
|
|
no_duplicate:
|
|
xor rax, rax
|
|
ret
|
|
|
|
|
|
|
|
;function that checks if the base is valid
|
|
;a valid base does not have any of these char : "+-" or any space defined by isspace(3) and does not have any duplicate char or does not have any char
|
|
; returns 0 if base is not valid
|
|
check_base:
|
|
xor rax, rax
|
|
|
|
mov al, [rdi] ; check if it's an empty string
|
|
test al, al
|
|
jne chk_bs_duplicate
|
|
xor rax, rax
|
|
ret
|
|
|
|
chk_bs_duplicate:
|
|
push rdi
|
|
call check_duplicate_char
|
|
pop rdi
|
|
test rax, rax
|
|
jz chk_bs_char
|
|
|
|
xor rax, rax
|
|
ret
|
|
|
|
|
|
chk_bs_char:
|
|
mov al, [rdi] ; if rdi is \0, return 0
|
|
test al, al
|
|
jz base_ok
|
|
|
|
push rdi ; if current char is in invalid_chars
|
|
mov dil, [rdi];
|
|
lea rsi, [rel invalid_chars]
|
|
call get_char_index
|
|
pop rdi
|
|
|
|
cmp rax, -1 ; if not -1, error
|
|
lea rdi, [rdi + 1]
|
|
jz chk_bs_char
|
|
|
|
xor rax, rax; return 0
|
|
ret
|
|
|
|
base_ok:
|
|
mov rax,1
|
|
ret
|
|
|
|
|
|
; prototype : int ft_atoi_base(char *str, char *base)
|
|
; rdi str
|
|
; rsi base
|
|
ft_atoi_base:
|
|
xor rax, rax ;check if there is a null pointer in rdi or rsi
|
|
test rdi, rdi
|
|
jz final_number
|
|
test rsi, rsi
|
|
jz final_number
|
|
|
|
push rdi ; is base valid
|
|
push rsi
|
|
mov rdi, rsi
|
|
call check_base
|
|
pop rsi
|
|
pop rdi
|
|
|
|
test rax, rax
|
|
jne whitespace_skip ; if 0 , base is not valid
|
|
xor rax, rax
|
|
ret
|
|
|
|
xor rdx, rdx
|
|
|
|
whitespace_skip_inc:
|
|
lea rdi, [rdi + 1]
|
|
whitespace_skip:
|
|
push rdi
|
|
push rsi
|
|
mov dil, [rdi]
|
|
lea rsi, [rel whitespaces]
|
|
call get_char_index
|
|
pop rsi
|
|
pop rdi
|
|
|
|
cmp rax, 0
|
|
jge whitespace_skip_inc
|
|
jmp plus_minus
|
|
|
|
plus_minus_invert:
|
|
xor rdx, 1
|
|
|
|
plus_minus_inc:
|
|
lea rdi, [rdi + 1]
|
|
|
|
plus_minus:
|
|
mov al, [rdi]
|
|
cmp al, '-'
|
|
jz plus_minus_invert
|
|
|
|
cmp al, '+'
|
|
jz plus_minus_inc
|
|
|
|
|
|
|
|
push rdi
|
|
push rsi
|
|
mov rdi, rsi
|
|
call ft_strlen
|
|
pop rsi
|
|
pop rdi
|
|
|
|
mov rbx, rax
|
|
|
|
xor rax, rax
|
|
|
|
push rdx
|
|
|
|
number_loop:
|
|
mov dl, [rdi]
|
|
test dl, dl
|
|
jz final_number
|
|
|
|
push rax
|
|
push rdi
|
|
push rsi
|
|
mov dil, dl
|
|
call get_char_index
|
|
pop rsi
|
|
pop rdi
|
|
|
|
mov rdx, rax ; save return value in rdx
|
|
pop rax
|
|
|
|
cmp rdx, -1
|
|
jz final_number
|
|
|
|
push rdx ; imul sets rdx to 0
|
|
imul rbx
|
|
pop rdx
|
|
add rax, rdx
|
|
|
|
lea rdi, [rdi + 1]
|
|
|
|
jmp number_loop
|
|
|
|
final_number:
|
|
pop rdx
|
|
test rdx, rdx
|
|
jne neg_final_number
|
|
ret
|
|
|
|
neg_final_number:
|
|
neg rax
|
|
ret
|