diff --git a/src/constants/sizes.asm b/src/constants/sizes.asm index 34a26dd..6aef3e7 100644 --- a/src/constants/sizes.asm +++ b/src/constants/sizes.asm @@ -14,10 +14,10 @@ MAX_UINT32 equ 0xFFFFFFFF MAX_UINT16 equ 0xFFFF MAX_UINT8 equ 0xFF -MIN_INT64 equ ~0x7FFFFFFFFFFFFFFF -MIN_INT32 equ ~0x7FFFFFFF -MIN_INT16 equ ~0x7FFF -MIN_INT8 equ ~0x7F +MIN_INT64 equ ~MAX_INT64 + 1 +MIN_INT32 equ ~MAX_INT32 + 1 +MIN_INT16 equ ~MAX_INT16 + 1 +MIN_INT8 equ ~MAX_INT8 + 1 MAX_INT64 equ 0x7FFFFFFFFFFFFFFF MAX_INT32 equ 0x7FFFFFFF diff --git a/src/convert.asm b/src/convert.asm index 1b5b7da..e0d77e3 100644 --- a/src/convert.asm +++ b/src/convert.asm @@ -22,16 +22,19 @@ section .text ; 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) +; r11* Stores if input is signed (r11b=1) or unsigned (r11b=0) ('-') atoi: xor rax, rax xor rcx, rcx xor r10, r10 + xor r11b, r11b 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 r11b inc rdi inc rcx ;make sure .calculateLoop includes minus sign @@ -61,8 +64,8 @@ atoi: mov rdx, '9' jmp .getLenLoop .skipBaseNotation: - cmp rcx, 1 ;If '-' was found, using base is invalid - je .quit + test r11b, r11b;If '-' was found, using base is invalid + jnz .quit add rdi, 2 ; -- Get length of numeric string + test if valid @@ -149,14 +152,15 @@ atoi: .calcNum_cnt: imul r9 - - mov rdx, -1 - sub rdx, r10 - cmp rax, rdx - ;TODO: Add signed checks - ja .overflow - + test r11b, r11b + jz .checkUnsignedOverflow add r10, rax + jo .overflow + jmp .continue + .checkUnsignedOverflow: + add r10, rax + jc .overflow + .continue: dec rdi inc r8 loop .calculateLoop diff --git a/src/tests.asm b/src/tests.asm index 1326a8c..1f3c49b 100644 --- a/src/tests.asm +++ b/src/tests.asm @@ -345,6 +345,10 @@ section .rodata addTest(atoi7, "atoi(''0b00010111'')") ;23 addTest(atoi8, "atoi(''0b02010111'')") ;0 addTest(atoi9, "atoi(''0xabcdefg'')") ;0 + addTest(atoi10, "atoi(''18446744073709551615'')") ;MAX_UINT64 + addTest(atoi11, "atoi(''18446744073709551616'')") ;0 + addTest(atoi12, "atoi('-9223372036854775807''')") ;MIN_INT64 + addTest(atoi13, "atoi('-9223372036854775809''')") ;0 atoiStr1 db "079168045",EOS atoiStr2 db "-079168045",EOS atoiStr3 db "-0xABCDEF",EOS @@ -354,6 +358,10 @@ section .rodata atoiStr7 db "0b00010111",EOS atoiStr8 db "0b02010111",EOS atoiStr9 db "0xabcdefg",EOS + atoiStr10 db "18446744073709551615",EOS + atoiStr11 db "18446744073709551616",EOS + atoiStr12 db "-9223372036854775807",EOS + atoiStr13 db "-9223372036854775809",EOS ;itoa() addTestHeader(_itoa, "itoa") addTest(itoa1, "// See printf outputs") @@ -1297,6 +1305,30 @@ _start: lea rdi, [rel atoiStr9] call atoi assert_u_eq(0) + + ; TEST 10 + printTest(atoi10) + lea rdi, [rel atoiStr10] + call atoi + assert_u_eq(MAX_UINT64) + + ; TEST 11 + printTest(atoi11) + lea rdi, [rel atoiStr11] + call atoi + assert_eq(0) + + ; TEST 12 + printTest(atoi12) + lea rdi, [rel atoiStr12] + call atoi + assert_eq(MIN_INT64) + + ; TEST 13 + printTest(atoi13) + lea rdi, [rel atoiStr13] + call atoi + assert_eq(0) %endif ;--- itoa()