1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
; **************************************************************************** ;
; ;
; ::: :::::::: ;
; ft_atoi_base.s :+: :+: :+: ;
; +:+ +:+ +:+ ;
; By: cacharle <marvin@42.fr> +;+ +:+ +;+ ;
; +;+;+;+;+;+ +;+ ;
; Created: 2019/11/22 03:59:15 by cacharle ;+; ;+; ;
; Updated: 2019/11/22 21:18:08 by cacharle ;;; ;;;;;;;;.fr ;
; ;
; **************************************************************************** ;
extern _ft_strlen
global _ft_atoi_base
; int ft_atoi_base(const char *str, const char *base);
_ft_atoi_base:
mov r12, rdi ; r12 = str
mov r13, rsi ; r13 = base
; check if the base is valid
mov rdi, r13
call _check_base
cmp rax, 0
je CHECK_BASE_FALSE
; ignore space in front
mov r15, -1 ; str index
FT_ATOI_BASE_IGNORE_SPACES:
inc r15
mov dil, byte [r12 + r15]
call _ft_isspace
cmp rax, 1
je FT_ATOI_BASE_IGNORE_SPACES
; cmp byte [r12 + r15], 0x2d
; mov r11, zf ; r11 = is negative
mov rdi, r13
call _ft_strlen
mov r14, rax ; r14 = radix
xor rcx, rcx ; return value
FT_ATOI_BASE_LOOP:
mov sil, [r12 + r15]
call _base_pos ; get value of the current char int the base
cmp rax, -1 ; if is not in base break
je FT_ATOI_BASE_LOOP_END
imul rcx, r14 ; multiply by the radix
add rcx, rax ; add the current value
inc r15
jmp FT_ATOI_BASE_LOOP
FT_ATOI_BASE_LOOP_END:
mov rax, rcx
ret
; rdi: char *base
; sil: char searched
_base_pos:
mov rax, -1
BASE_POS_LOOP:
inc rax
cmp byte [rdi + rax], 0 ; if '\0' char not in base
je BASE_POS_NOT_FOUND
cmp sil, byte [rdi + rax] ; loop until '\0' or found
jne BASE_POS_LOOP
ret
BASE_POS_NOT_FOUND:
mov rax, -1
ret
; rdi: char *base
_check_base:
; check for empty or size 1 base
push rdi
call _ft_strlen
pop rdi
cmp rax, 2
jl CHECK_BASE_FALSE
xor rcx, rcx ; rcx = index
CHECK_BASE_LOOP:
cmp byte [rdi + rcx], 0
je CHECK_BASE_LOOP_END
cmp byte [rdi + rcx], 0x2b ; check '+'
je CHECK_BASE_FALSE
cmp byte [rdi + rcx], 0x2d ; check '-'
je CHECK_BASE_FALSE
push rdi ; save base
mov dil, [rdi + rcx] ; pass current char as argument
call _ft_isspace
pop rdi ; recover base
cmp rax, 1
je CHECK_BASE_FALSE ; check for spaces
; check for duplicates in base
mov rdx, rcx ; index from curr +1
CHECK_BASE_DUP_LOOP:
inc rdx
mov r10b, byte [rdi + rcx] ; r10b = checked char
cmp r10b, byte [rdi + rdx] ; check if found dup
je CHECK_BASE_FALSE
cmp byte [rdi + rdx], 0 ; if \0 end dup check
jne CHECK_BASE_DUP_LOOP
inc rcx
jmp CHECK_BASE_LOOP
CHECK_BASE_LOOP_END:
mov rax, 1
ret
CHECK_BASE_FALSE:
xor rax, rax
ret
; dil: char c
_ft_isspace:
cmp dil, 20h ; if space jump next
je ISSPACE_TRUE_END
sub dil, 9h
cmp dil, 5h
jl ISSPACE_TRUE_END
xor rax, rax
ret
ISSPACE_TRUE_END:
mov rax, 1
ret
|