diff --git a/src/console.asm b/src/console.asm index 60b99c9..f657659 100644 --- a/src/console.asm +++ b/src/console.asm @@ -71,6 +71,8 @@ puts: ; %X Unsigned integer, printed as hexadecimal number (uppercase) ; %b Unsigned integer, printed as binary number ; %s String +; %N* Pad left, N chars (maximum 64). Supported *: d, i, u, x, X, b +; *0N* Pad left with zeroes, N chars (maximum 64). Supported *: d, i, u, x, X, b ; Unsupported specifiers are printed as-is ; For all specifiers (except %%) an argument is expected. Mismatch between arguments given and specifiers provided will lead to issues ; Used registers: @@ -236,13 +238,16 @@ printf: .rep_d: load_arg rsi push_regs + mov rdx, r13 cmp byte [rdi + 1], 'u' je .callUINT2STR mov rdi, rsi + mov rsi, r12 call dec2str jmp .loadConvertedStr .callUINT2STR: mov rdi, rsi + mov rsi, r12 call udec2str .loadConvertedStr: mov rsi, rax @@ -261,8 +266,12 @@ printf: push rax push rdx push r9 + push r10 + mov rdx, r12 + mov rcx, r13 call hex2str mov rsi, rax + pop r10 pop r9 pop rdx pop rax diff --git a/src/convert.asm b/src/convert.asm index cbe8dcd..6b3dcd1 100644 --- a/src/convert.asm +++ b/src/convert.asm @@ -11,26 +11,27 @@ section .text global hex2str global bin2str -;----- dec2str(int) -----; +;----- dec2str(int, padLen, bool padZeroes) -----; ; Converts a signed integer to a string (decimal output) ; Return value: Pointer to string containing the converted integer ; Used registers: ; rax* int stored for div >> (ret) pointer to cnvtBuff[] ; rcx* Counts length of created string -; rdx* modulo as calculated by div >> character storage for cnvtBuff +; rdx* (arg) padZeroes >> modulo as calculated by div >> character storage for cnvtBuff ; rdi* (arg) integer to convert to string >> Remembers if num is negative -; rsi* Points to cnvtBuff for writing characters +; rsi* (arg) Padding length ; r8* Dividor for div +; r9* Points to cnvtBuff[] +; r10* padZeroes arg (since rdx used by DIV) +; r12 Remembers if number is negative dec2str: - lea rsi, [rel cnvtBuffRev] - test rdi, rdi - jnz .notZero - lea rsi, [rel cnvtBuff] - mov byte [rsi], '0' - mov byte [rsi+1], EOS - jmp .quit - - .notZero: + push r12 + xor r12, r12 + mov r10, ' ' + mov r9, '0' + test rdx, rdx + cmovnz r10, r9 + lea r9, [rel cnvtBuffRev] mov rax, rdi xor dil, dil xor rcx, rcx @@ -43,51 +44,78 @@ dec2str: mov r8, 10 div r8 add rdx, '0' - mov [rsi], dl - inc rsi + mov [r9], dl + inc r9 inc rcx test rax, rax jnz .convert test dil, dil jz .makeString - mov [rsi], byte '-' - inc rcx - inc rsi + mov r12, 1 .makeString: + sub rsi, rcx + cmp rsi, rcx + jl .noPadding + mov r8, rcx + mov rdi, rsi + xor rsi, rsi + mov rdx, 64 + call clamp + mov rcx, rax + test r12, r12 + jz .paddingLoop + cmp r10, '0' + je .paddingLoop + mov byte [r9], '-' + inc r9 + inc r8 + xor r12, r12 + .paddingLoop: + mov byte [r9], r10b + inc r9 + inc r8 + loop .paddingLoop + mov rcx, r8 + .noPadding: + test r12, r12 + jz .positive + mov [r9], byte '-' + inc r9 + inc rcx + .positive: lea rdi, [rel cnvtBuff] - dec rsi + dec r9 .makeStringLoop: - mov al, [rsi] + mov al, [r9] mov [rdi], al inc rdi - dec rsi + dec r9 loop .makeStringLoop mov byte [rdi], EOS .quit: lea rax, [rel cnvtBuff] + pop r12 ret -;----- udec2str(uint) -----; +;----- udec2str(uint, padLen, bool padZeroes) -----; ; Converts an unsigned integer to a string (decimal output) ; Return value: Pointer to string containing the converted integer ; Used registers: ; rax* uint stored for div >> (ret) pointer to cnvtBuff[] ; rcx* Counts length of created string -; rdx* modulo as calculated by div >> character storage for cnvtBuff +; rdx* (arg) padZeroes >> modulo as calculated by div ; rdi* (arg) integer to convert to string -; rsi* Points to cnvtBuff for writing characters +; rsi* (arg) padLen ; r8* Dividor for div +; r9* Points to cnvtBuff for writing characters +; r10* padZeroes arg (since rdx used by DIV) udec2str: - lea rsi, [rel cnvtBuffRev] - test rdi, rdi - jnz .notZero - lea rsi, [rel cnvtBuff] - mov byte [rsi], '0' - mov byte [rsi+1], EOS - jmp .quit - - .notZero: + mov r10, ' ' + mov r9, '0' + test rdx, rdx + cmovnz r10, r9 + lea r9, [rel cnvtBuffRev] mov rax, rdi xor rcx, rcx .convert: @@ -95,18 +123,34 @@ udec2str: mov r8, 10 div r8 add rdx, '0' - mov [rsi], dl - inc rsi + mov [r9], dl + inc r9 inc rcx test rax, rax jnz .convert + sub rsi, rcx + cmp rsi, rcx + jl .noPadding + mov r8, rcx + mov rdi, rsi + xor rsi, rsi + mov rdx, 64 + call clamp + mov rcx, rax + .paddingLoop: + mov byte [r9], r10b + inc r9 + inc r8 + loop .paddingLoop + mov rcx, r8 + .noPadding: lea rdi, [rel cnvtBuff] - dec rsi + dec r9 .makeStringLoop: - mov al, [rsi] + mov al, [r9] mov [rdi], al inc rdi - dec rsi + dec r9 loop .makeStringLoop mov byte [rdi], EOS @@ -114,33 +158,31 @@ udec2str: lea rax, [rel cnvtBuff] ret -;----- hex2str(uint, bool uppercase) -----; +;----- hex2str(uint, bool uppercase, padLen, bool padZeroes) -----; ; Converts an unsigned integer to a string (hexadecimal output) ; Return value: Pointer to string containing the converted integer ; Used registers: ; rax* uint stored for div >> (ret) Pointer to cnvtBuff[] ; rdi (arg) Integer to convert ; rsi* (arg) 0=convert lowercase, (any other value)=convert uppercase >> Points to cnvtBuff for writing characters -; rdx* module as calculated by div -; rcx* Counts length of created string +; rdx* (arg) Padding length >> module as calculated by div +; rcx* (arg) padZeroes >> Counts length of created string ; r8* Dividor for div ; r9* Store arg rsi (uppercase) +; r10* Store arg rdx ; r11* Amount to add to number (for ASCII conversion, lowercase or uppercase) +; r12 Store arg padZeroes hex2str: + push r12 mov r9, rsi + mov r10, rdx + mov r12, ' ' + mov rsi, '0' + test rcx, rcx + cmovnz r12, rsi lea rsi, [rel cnvtBuffRev] - test rdi, rdi - jnz .notZero - lea rsi, [rel cnvtBuff] - mov word [rsi], '0x' - mov byte [rsi + 2], '0' - mov byte [rsi + 3], EOS - jmp .quit - - .notZero: mov rax, rdi xor rcx, rcx - mov r8, 87 test r9, r9 cmovz r11, r8 @@ -163,10 +205,25 @@ hex2str: inc rcx test rax, rax jnz .convert - - mov word [rsi], 'x0' - inc rsi - add rcx, 2 + sub r10, rcx + cmp r10, rcx + jl .noPadding + mov r8, rcx + push rsi + mov rdi, r10 + xor rsi, rsi + mov rdx, 64 + call clamp + pop rsi + mov rcx, rax + .paddingLoop: + mov byte[rsi], r12b + inc rsi + inc r8 + loop .paddingLoop + mov rcx, r8 + .noPadding: + dec rsi lea rdi, [rel cnvtBuff] .makeString: mov al, [rsi] @@ -178,6 +235,7 @@ hex2str: .quit: lea rax, [rel cnvtBuff] + pop r12 ret ;----- bin2str(uint, padLen, bool padZeroes) -----; @@ -223,14 +281,10 @@ bin2str: cmp rsi, rcx jl .noPadding mov r8, rcx - push rsi - push rdx mov rdi, rsi xor rsi, rsi mov rdx, 64 call clamp - pop rdx - pop rsi mov rcx, rax .paddingLoop: mov byte [r9], r10b diff --git a/src/tests.asm b/src/tests.asm index 78ee28c..198a92e 100644 --- a/src/tests.asm +++ b/src/tests.asm @@ -92,6 +92,16 @@ section .rodata printf5Str db "%x|%X , %x|%X",NL,EOS printf6 db TAB,"printf(",DQUO,"%b | %8b | %08b\n",DQUO,", 5, 5, 5): ",NL,TAB,TAB,EOS printf6Str db "%b | %8b | %08b",NL,EOS + printf7 db TAB,"printf(",DQUO,"%d | %8d | %08d\n",DQUO,", -234, -234, -234): ",NL,TAB,TAB,EOS + printf7Str db "%d | %8d | %08d",NL,EOS + printf8 db TAB,"printf(",DQUO,"%i | %8i | %08i\n",DQUO,", -234, -234, -234): ",NL,TAB,TAB,EOS + printf8Str db "%i | %8i | %08i",NL,EOS + printf9 db TAB,"printf(",DQUO,"%u | %8u | %08u\n",DQUO,", -234, -234, -234): ",NL,TAB,TAB,EOS + printf9Str db "%u | %8u | %08u",NL,EOS + printf10 db TAB,"printf(",DQUO,"%x | %8x | %08x\n",DQUO,", 0xAB0F, -0xAB0F, 0xAB0F): ",NL,TAB,TAB,EOS + printf10Str db "%x | %8x | %08x",NL,EOS + printf11 db TAB,"printf(",DQUO,"%X | %8X | %08X\n",DQUO,", 0xAB0F, -0xAB0F, 0xAB0F): ",NL,TAB,TAB,EOS + printf11Str db "%X | %8X | %08X",NL,EOS ; strlen() msgStrlen db NL,"TEST strlen()",NL,EOS @@ -350,6 +360,51 @@ _start: mov rdx, 5 mov rcx, 5 call printf + + ; TEST 7 + lea rdi, [rel printf7] + call print + lea rdi, [rel printf7Str] + mov rsi, -234 + mov rdx, -234 + mov rcx, -234 + call printf + + ; TEST 8 + lea rdi, [rel printf8] + call print + lea rdi, [rel printf8Str] + mov rsi, -234 + mov rdx, -234 + mov rcx, -234 + call printf + + ; TEST 9 + lea rdi, [rel printf9] + call print + lea rdi, [rel printf9Str] + mov rsi, -234 + mov rdx, -234 + mov rcx, -234 + call printf + + ; TEST 10 + lea rdi, [rel printf10] + call print + lea rdi, [rel printf10Str] + mov rsi, 0xAB0F + mov rdx, 0xAB0F + mov rcx, 0xAB0F + call printf + + ; TEST 11 + lea rdi, [rel printf11] + call print + lea rdi, [rel printf11Str] + mov rsi, 0xAB0F + mov rdx, 0xAB0F + mov rcx, 0xAB0F + call printf %endif ;---