diff options
| author | Charles <sircharlesaze@gmail.com> | 2019-11-25 03:37:45 +0100 |
|---|---|---|
| committer | Charles <sircharlesaze@gmail.com> | 2019-11-25 03:37:45 +0100 |
| commit | 9af248e8a78f111a39d507f199d56eb8af6e52d6 (patch) | |
| tree | 4b86561a5fea5f22d8d51c5b2a029cad98feaa25 /ft_atoi_base.s | |
| parent | c0bcb694bbcef0273d6e6fa93854ce6a10432b87 (diff) | |
| download | libasm-9af248e8a78f111a39d507f199d56eb8af6e52d6.tar.gz libasm-9af248e8a78f111a39d507f199d56eb8af6e52d6.tar.bz2 libasm-9af248e8a78f111a39d507f199d56eb8af6e52d6.zip | |
ft_atoi_base.s kinda done
Diffstat (limited to 'ft_atoi_base.s')
| -rw-r--r-- | ft_atoi_base.s | 279 |
1 files changed, 183 insertions, 96 deletions
diff --git a/ft_atoi_base.s b/ft_atoi_base.s index 581b68b..663b399 100644 --- a/ft_atoi_base.s +++ b/ft_atoi_base.s @@ -10,126 +10,213 @@ ; ; ; **************************************************************************** ; + +; Only need to save reg if we use them after + +; caller rules: +; 1. save caller-saved reg r10, r11 +; /!\ all param reg +; 2. pass param with regs rdi, rsi, rdx, rcx, r8, r9 +; if there is more pass them onto the stack in reverse order +; 3. use call +; 4. restore stack state by removing passed on the stack param +; 5. return value of callee in rax +; 6. restore the caller-saved register and saved passed params +; We can assume that no other register has been altered. + + +; callee rules: +; 1. allocate local variables by sub sum of sizes of thoses var to rsp +; the stack grows downward so we will access those local by adding to rsp. +; 2. push callee-saved reg onto the stack: rbx, rbp, r12, r13, r14, r15. +; +; >>> function body <<< +; +; 3. place return value in rax +; 4. restore callee-saved registers +; 5. remove local var, add to the stack the previoulsy subtracted amount. +; 6. use ret + + 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 - + ; ===prolog=== + ; long int nb (8) + ; int radix (4) + ; int is_negative (4) + sub rsp, 16 + mov qword [rsp], 0x0 ; nb = 0 + mov dword [rsp + 8], 0x0 ; radix = 0 + mov dword [rsp + 12], 0x0 ; is_negative = 0 + push rbx + push r11 + push r15 + + ; ===body=== ; check if the base is valid - mov rdi, r13 + push rdi + mov rdi, rsi call _check_base - cmp rax, 0 - je CHECK_BASE_FALSE - + pop rdi + cmp eax, 0x0 + je FT_ATOI_BASE_ERROR ; 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 + mov rbx, -1 ; rbx is rdi str index +FT_ATOI_BASE_IGNORE_SPACES: + inc rbx + push rdi + mov dil, byte [rdi + rbx] + call _ft_isspace + pop rdi + cmp rax, 1 + je FT_ATOI_BASE_IGNORE_SPACES + + ; ignore '+', '-' reverse the current sign + mov qword [rsp], 0x0 ; nb = 0 + mov dword [rsp + 8], 0x0 ; radix = 0 + mov dword [rsp + 12], 0x0 ; is_negative = 0 + mov dword [rsp + 12], 0x0 ; weird behavior FIXME + dec rbx + jmp FT_ATOI_BASE_SIGN_LOOP +FT_ATOI_BASE_SIGN_LOOP_FOUND_NEG: + not dword [rsp + 12] +FT_ATOI_BASE_SIGN_LOOP: + inc rbx + cmp byte [rdi + rbx], 0x2b ; if '+' + je FT_ATOI_BASE_SIGN_LOOP + cmp byte [rdi + rbx], 0x2d ; if '-' + je FT_ATOI_BASE_SIGN_LOOP_FOUND_NEG + + ; base radix + push rdi + mov rdi, rsi 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 + pop rdi + mov dword [rsp + 8], eax + ; main loop +FT_ATOI_BASE_LOOP: + push rdi + push rsi + mov dil, byte [rdi + rbx] + call _base_pos ; get value of the current char int the base + pop rsi + pop rdi + cmp rax, -1 ; if is not in base break + je FT_ATOI_BASE_LOOP_END + + mov r11, [rsp] ; place nb in register for multiplication + xor r15, r15 ; same for radix + mov r15d, dword [rsp + 8] + imul r11, r15 ; multiply by the radix + mov [rsp], r11 ; store multiplication result + add [rsp], rax ; add the current value + + inc rbx + jmp FT_ATOI_BASE_LOOP +FT_ATOI_BASE_LOOP_END: + + cmp dword [rsp + 12], 0 + je FT_ATOI_BASE_END + neg qword [rsp] + + ; ===epilog=== +FT_ATOI_BASE_END: + mov rax, [rsp] + pop r15 + pop r11 + pop rbx + add rsp, 16 + ret +FT_ATOI_BASE_ERROR: + mov rax, 0x0 + pop r15 + pop r11 + pop rbx + add rsp, 16 + ret -; rdi: char *base -; sil: char searched +; dil: char searched +; rsi: char *base _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 + mov rax, -1 +BASE_POS_LOOP: + inc rax + cmp byte [rsi + rax], 0 ; if '\0' char not in base + je BASE_POS_NOT_FOUND + cmp dil, byte [rsi + rax] ; loop until '\0' or found + jne BASE_POS_LOOP + ret +BASE_POS_NOT_FOUND: + mov rax, -1 ret - BASE_POS_NOT_FOUND: - mov rax, -1 - ret ; rdi: char *base _check_base: - ; check for empty or size 1 base + sub rsp, 4 + mov dword [rsp], 0 +; 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 + pop rdi + cmp rax, 2 + jl CHECK_BASE_FALSE + + ; xor rcx, rcx +CHECK_BASE_LOOP: + cmp byte [rdi], 0 + je CHECK_BASE_LOOP_END + cmp byte [rdi], 0x2b ; check '+' + je CHECK_BASE_FALSE + cmp byte [rdi], 0x2d ; check '-' + je CHECK_BASE_FALSE + +; check for spaces + push rdi + mov dil, [rdi] ; pass current char as argument + call _ft_isspace + pop rdi + cmp rax, 1 + je CHECK_BASE_FALSE + +; check for duplicates in base + xor rcx, rcx ; index from curr +1 +CHECK_BASE_DUP_LOOP: + inc rcx + mov r10b, byte [rdi] ; r10b = checked char + cmp r10b, byte [rdi + rcx] ; check if found dup + je CHECK_BASE_FALSE + cmp byte [rdi + rcx], 0 ; if \0 end dup check + jne CHECK_BASE_DUP_LOOP + + inc rdi + jmp CHECK_BASE_LOOP +CHECK_BASE_LOOP_END: + + add rsp, 4 + mov rax, 1 + ret +CHECK_BASE_FALSE: + add rsp, 4 + xor rax, rax 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 + cmp dil, 0x20 + je ISSPACE_TRUE + sub dil, 0x9 + cmp dil, 0x5 + jl ISSPACE_TRUE + xor rax, rax + ret +ISSPACE_TRUE: + mov rax, 0x1 ret - ISSPACE_TRUE_END: - mov rax, 1 - ret |
