extern NR_write extern strlen extern strcat extern itoa section .rodata NL db 0xA bufferLength equ 4096 ERR_buffLen db " ERROR: Failed to complete printf(), reached buffer length!",0xA,0x0 lERR_buffLen equ $-ERR_buffLen-1 section .bss printfBuff resb bufferLength printfNBuff resb 32 section .text global print global puts global printf ;----- print (char* string) -----; ; return value: N/A print: call strlen mov rdx, rax mov rax, NR_write mov rsi, rdi mov rdi, 1 syscall ret ;----- puts (char* string) -----; ; return value: N/A puts: mov r10, rdi call print mov rdi, r10 mov rax, NR_write mov rdi, 1 mov rsi, NL mov rdx, 1 syscall ret ;----- printf(const char* string, ...) -----; ; Currently only supports specifiers: %d, %c, %s, %% ; Return value: Amount of printed characters printf: push rbp mov rbp, rsp push r12 push r14 xor r10, r10 xor r14, r14 lea r11, [rel printfBuff] .makeStr: cmp byte [rdi], 0x0 je .finish cmp r14, bufferLength-1 je .finish cmp byte [rdi], '%' je .replaceArg mov r12b, byte [rdi] mov byte [r11], r12b inc r14 jmp .continue .replaceArg: cmp byte [rdi+1], 0x0 je .continue push rdi cmp byte [rdi+1], 'd' je .rep_d cmp byte [rdi+1], '%' je .rep_pct cmp byte [rdi+1], 'c' je .rep_c cmp byte [rdi+1], 's' je .rep_s ;--- invalid specifier ---; mov byte [r11], '%' inc r14 inc r10 jmp .continue ;--- %d ---; .rep_d: cmp r10, 0 cmove rdi, rsi je .convertInt cmp r10, 1 cmove rdi, rdx je .convertInt cmp r10, 2 cmove rdi, rcx je .convertInt cmp r10, 3 cmove rdi, r8 je .convertInt cmp r10, 4 cmove rdi, r9 je .convertInt mov rdi, qword [rbp + 16 + (r10-5)*8] .convertInt: lea rsi, [rel printfNBuff] push rcx push rdx push r8 push r10 call itoa pop r10 pop r8 pop rdx pop rcx mov rsi, rax jmp .insertLoop ;--- %% ---; .rep_pct: mov rdi, '%' dec r10 jmp .charToStr ;--- %c ---; .rep_c: cmp r10, 0 cmove rdi, rsi je .charToStr cmp r10, 1 cmove rdi, rdx je .charToStr cmp r10, 2 cmove rdi, rcx je .charToStr cmp r10, 3 cmove rdi, r8 je .charToStr cmp r10, 4 cmove rdi, r9 je .charToStr mov rdi, qword [rbp + 16 + (r10-5)*8] .charToStr: mov [printfNBuff], dil mov dil, 0 mov [printfNBuff+1], dil lea rsi, [rel printfNBuff] jmp .insertLoop ;--- %s ---; .rep_s: cmp r10, 0 je .insertLoop cmp r10, 1 cmove rsi, rdx je .insertLoop cmp r10, 2 cmove rsi, rcx je .insertLoop cmp r10, 3 cmove rsi, r8 je .insertLoop cmp r10, 4 cmove rsi, r9 je .insertLoop mov rsi, qword [rbp + 16 + (r10-5)*8] ;--- Move fetched data to buffer ---; .insertLoop: cmp r14, bufferLength-1 je .finish cmp byte [rsi], 0x0 je .s0f mov r12b, byte [rsi] mov byte [r11], r12b inc r14 inc rsi inc r11 jmp .insertLoop .s0f: inc r10 pop rdi add rdi, 2 jmp .makeStr .continue: inc rdi inc r11 jmp .makeStr .finish: mov byte [r11], 0x0 mov rax, NR_write mov rdi, 1 lea rsi, [rel printfBuff] mov rdx, r14 syscall mov rax, r14 cmp r14, bufferLength-1 jl .final mov rax, NR_write mov rdi, 2 lea rsi, [rel ERR_buffLen] mov rdx, lERR_buffLen syscall .final: pop r14 pop r12 leave ret