230 lines
2.9 KiB
NASM
230 lines
2.9 KiB
NASM
global ft_atoibase
|
|
extern ft_bzero
|
|
extern ft_isspace
|
|
extern __errno_location
|
|
|
|
section .text
|
|
|
|
;int has_dup(const char *s) {
|
|
; uint32_t bits[8] = {0}; // 8*32 = 256 bits
|
|
; for (const unsigned char *p = (const unsigned char*)s; *p; ++p) {
|
|
; unsigned int v = *p;
|
|
; unsigned int idx = v >> 5; // division par 32
|
|
; unsigned int bit = v & 31; // v % 32
|
|
; uint32_t mask = 1u << bit;
|
|
; if (bits[idx] & mask) return -1;
|
|
; bits[idx] |= mask;
|
|
; }
|
|
; return 0;
|
|
;}
|
|
|
|
; return base_len and check for "-+" or duplicate char
|
|
; rdi: base
|
|
check_base:
|
|
; uint32_t buffer[8]
|
|
push rbp
|
|
mov rbp, rsp
|
|
sub rsp, 40
|
|
|
|
mov qword [rsp + 32], rdi
|
|
|
|
; bzero buffer, 32
|
|
mov rdi, rsp
|
|
mov rsi, 32
|
|
call ft_bzero wrt ..plt
|
|
|
|
mov rax, qword [rsp + 32]
|
|
|
|
.loop:
|
|
mov dl, byte [rax]
|
|
test dl, dl
|
|
je .done
|
|
|
|
; if (*p == '-' || *p == '+') return -1
|
|
cmp dl, 45
|
|
je .error
|
|
cmp dl, 43
|
|
je .error
|
|
|
|
; r10(idx) = *p / 32
|
|
; rdx(bit) = *p % 32
|
|
mov r10, [rax]
|
|
shr r10, 5
|
|
mov rdx, [rax]
|
|
and rdx, 31
|
|
|
|
; mask = 1 << rdx(bit)
|
|
mov r11, 1
|
|
mov cl, dl
|
|
shl r11, cl
|
|
|
|
; if (bits[idx] & mask) return -1
|
|
mov r9, [rsp + rdx]
|
|
and r9, r11
|
|
test r9, r9
|
|
jne .error
|
|
|
|
; bits[idx] |= mask
|
|
or [rsp + rdx], r11
|
|
|
|
; ++p
|
|
inc rax
|
|
|
|
jmp .loop
|
|
.done:
|
|
sub rax, qword [rsp + 32]
|
|
|
|
.return:
|
|
add rsp, 40
|
|
pop rbp
|
|
ret
|
|
|
|
.error:
|
|
mov rax, -1
|
|
jmp .return
|
|
|
|
; skip whitespace and sign
|
|
; rdi: str
|
|
; return:
|
|
; rax str + x + is_signed
|
|
; dl is_signed
|
|
find_start:
|
|
push r12
|
|
mov r12, rdi
|
|
.loop:
|
|
mov dil, byte [r12]
|
|
call ft_isspace wrt ..plt
|
|
|
|
test rax, rax
|
|
je .done
|
|
test dil, dil
|
|
je .done
|
|
|
|
inc r12
|
|
jmp .loop
|
|
.done:
|
|
mov rax, r12
|
|
xor dl, dl
|
|
|
|
pop r12
|
|
|
|
cmp byte [rax], '-'
|
|
je .is_signed
|
|
|
|
ret
|
|
.is_signed:
|
|
inc dl
|
|
inc rax
|
|
ret
|
|
|
|
|
|
; rdi: base
|
|
; rsi: char
|
|
; rdx: baselen
|
|
|
|
; int i = 0
|
|
; while i < baselen
|
|
; if (c == base[i])
|
|
; return base[i]
|
|
; inc i
|
|
; return -1
|
|
|
|
get_num_from_base:
|
|
xor rax, rax
|
|
|
|
.loop:
|
|
cmp rax, rdx
|
|
jge .not_found
|
|
|
|
mov cl, byte [rdi + rax]
|
|
cmp cl, sil
|
|
je .found
|
|
|
|
inc rax
|
|
jmp .loop
|
|
|
|
.found:
|
|
ret
|
|
|
|
.not_found:
|
|
mov rax, -1
|
|
ret
|
|
|
|
; r12: str
|
|
; r13: base
|
|
ft_atoibase:
|
|
push r12
|
|
push r13
|
|
push r14
|
|
push r15
|
|
|
|
mov r12, rdi
|
|
mov r13, rsi
|
|
|
|
; if (check_base(base) <= 0 ) return 0;
|
|
mov rdi, r13
|
|
call check_base
|
|
test rax, rax
|
|
jle .invalid_base
|
|
|
|
; r14 = base_len
|
|
mov r14, rax
|
|
|
|
; str += start + is_signed
|
|
; rb9 = is_signed
|
|
mov rdi, r12
|
|
call find_start
|
|
mov r12, rax
|
|
mov r15b, dl
|
|
|
|
xor r11, r11
|
|
.loop:
|
|
cmp byte [r12], 0
|
|
je .end_loop
|
|
|
|
|
|
mov rdi, r13
|
|
movzx rsi, byte [r12]
|
|
mov rdx, r14
|
|
|
|
push r11
|
|
call get_num_from_base
|
|
pop r11
|
|
test rax, rax
|
|
jl .end_loop
|
|
|
|
imul r11d, r14d
|
|
jo .overflow
|
|
add r11, rax
|
|
jc .overflow
|
|
|
|
inc r12
|
|
jmp .loop
|
|
|
|
.end_loop:
|
|
mov rax, r11
|
|
.done:
|
|
|
|
test r15b, r15b
|
|
je .cleanup
|
|
neg rax
|
|
.cleanup:
|
|
|
|
pop r12
|
|
pop r13
|
|
pop r14
|
|
pop r15
|
|
ret
|
|
|
|
.invalid_base:
|
|
; errno = EINVAL
|
|
call __errno_location wrt ..plt
|
|
mov dword [rax], 22
|
|
xor rax, rax
|
|
jmp .done
|
|
|
|
.overflow:
|
|
call __errno_location wrt ..plt
|
|
mov dword [rax], 34
|
|
xor rax, rax
|
|
jmp .cleanup
|