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 ; get index of char in string or returns -1 if not found ; char in dil ; str in rsi get_char_index: xor rax, rax push rsi ; keep start index in stack test dil, dil je .error .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 .error mov rax, -1 ;not found and at the end pop rsi ret .get_char_index_found: pop rax ;return index of the found char (compare to top of stack) 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 return test rsi, rsi jz return 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 ret 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 xor rdx, rdx 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 rdx ; keep invert sign setting in stack push rdi push rsi mov rdi, rsi call ft_strlen pop rsi pop rdi mov rbx, rax ; keep the length of the base in rbx xor rax, rax 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 ; if the char is not in the base, return the number 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 return: ret