diff --git a/src/convert.asm b/src/convert.asm index 3045b04..0368d6b 100644 --- a/src/convert.asm +++ b/src/convert.asm @@ -6,9 +6,154 @@ section .bss cnvtBuff resb 67 cnvtBuffRev resb 67 section .text + global atoi global itoa global utoa +;----- atoi(*str[]) -----; +; Converts numeric string to an integer +; Return value: Converted integer or 0 if input was invalid +; Used registers: +; rax* (ret) +; rdi* (arg) Numeric string to convert +; rsi* Stores base +; rdx* Stores max usable ascii number +; rcx* Loop counter +; r8* tmp storage rsi (cmov) >> Loop counter for calculating base^n +; r9* tmp storage rdx (cmov) >> Calculated base^n +; r10* Stores return value (since RAX is used by IMUL) +atoi: + xor rax, rax + xor rcx, rcx + xor r10, r10 + cmp byte [rdi], EOS + je .quit + + ; -- Test if negative (increase pointer to str, result is always calculated positively. Once reaching '-' again, then NEG) + cmp byte [rdi], '-' + jne .noMinusSign + inc rdi + inc rcx ;make sure .calculateLoop includes minus sign + + ; -- Determine base + .noMinusSign: + ; hex? + mov r8, 16 + cmp word [rdi], '0x' + cmove rsi, r8 + je .skipBaseNotation + ; octal? + mov r8, 8 + mov r9, '7' + cmp word [rdi], '0o' + cmove rsi, r8 + cmove rdx, r9 + je .skipBaseNotation + ; binary? + mov r8, 2 + mov r9, '1' + cmp word [rdi], '0b' + cmove rsi, r8 + cmove rdx, r9 + je .skipBaseNotation + ; nope, decimal + mov rsi, 10 + mov rdx, '9' + jmp .getLen + .skipBaseNotation: + cmp rcx, 1 ;If '-' was found, using base is invalid + je .quit + add rdi, 2 + + ; -- Get length of numeric string + test if valid + .getLen: + .getLenLoop: + cmp byte [rdi], EOS + je .calculate + cmp byte [rdi], '0' + jb .quit + ; Test if valid + cmp rsi, 16 + je .getLenLoop_testHex + cmp byte [rdi], dl + ja .quit + jmp .getLenLoop_cnt + .getLenLoop_testHex: + cmp byte [rdi], 'F' + ja .quit + cmp byte [rdi], 'A' + jb .testHex_isNum + jmp .getLenLoop_cnt + .testHex_isNum: + cmp byte [rdi], '9' + ja .quit + + .getLenLoop_cnt: + inc rdi + inc rcx + jmp .getLenLoop + + ; -- Calculate the number + .calculate: + dec rdi ;don't point to EOS + xor r8, r8 + + .calculateLoop: + cmp byte [rdi], '-' + je .wrapup_neg + ; Calculate base^n + .calcBase: + test r8, r8 + jz .calcBase_firstLoop + cmp r8, 1 + je .calcBase_secondLoop + jmp .calcBase_otherLoops + + .calcBase_firstLoop: + mov r9, 1 + jmp .calcNum + .calcBase_secondLoop: + mov r9, rsi + jmp .calcNum + .calcBase_otherLoops: + mov rax, rsi + mov r9, r8 + dec r9 + .calcBaseLoop: + imul rsi + dec r9 + test r9, r9 + jnz .calcBaseLoop + mov r9, rax + + ; Calculate number + .calcNum: + xor rax, rax + mov al, byte [rdi] + cmp al, 'A' + jb .calcNum_notHex + sub al, 55 ;'A'-10 (65-10) + jmp .calcNum_cnt + .calcNum_notHex: + sub al, '0' + + .calcNum_cnt: + imul r9 + + add r10, rax + dec rdi + inc r8 + loop .calculateLoop + + jmp .quit + + .wrapup_neg: + neg r10 + + .quit: + mov rax, r10 + ret + ;----- itoa(int, base, padLen, bool padZeroes) -----; ; Converts a signed integer to a string ; Return value: Pointer to converted string or 0(EOS) if entered base is invalid