Adds basic printf() (currently only support '%%')
This commit is contained in:
118
src/console.asm
118
src/console.asm
@@ -3,10 +3,15 @@
|
||||
extern strlen
|
||||
|
||||
section .rodata
|
||||
mNL db NL
|
||||
mNL db NL
|
||||
printfBuffLen equ 128
|
||||
section .bss
|
||||
printfBuff resb printfBuffLen
|
||||
printfArgs resq 5
|
||||
section .text
|
||||
global print
|
||||
global puts
|
||||
global printf
|
||||
|
||||
;----- print(*str[]) -----;
|
||||
; Prints given string to the console to stdout
|
||||
@@ -31,7 +36,10 @@ print:
|
||||
; Prints given string to the console to stdout and prints a new line
|
||||
; Return value: Amount of printed characters
|
||||
; Used registers:
|
||||
;
|
||||
; rax* syscall >> (ret) amount of printed characters
|
||||
; rdi* (arg) Pointer to str[] >> syscall arg (fd)
|
||||
; rsi* syscall arg (pointer to str[])
|
||||
; rdx* syscall arg (length of str[]+1)
|
||||
puts:
|
||||
sub rsp, SIZE_QWORD
|
||||
call print
|
||||
@@ -45,3 +53,109 @@ puts:
|
||||
inc rax
|
||||
add rsp, SIZE_QWORD
|
||||
ret
|
||||
|
||||
;----- printf(*format[], ...) -----;
|
||||
; Formats and prints given string to console to stdout
|
||||
; Return value: Amount of printed characters
|
||||
; Supported specifiers:
|
||||
; %% Literal percentage sign
|
||||
; <!> Unsupported specifiers are printed as-is
|
||||
; Used registers:
|
||||
; rax (ret) amount of printed characters
|
||||
; rdi (arg) pointer to format[] to format and print
|
||||
; rsi (optional arg)
|
||||
; rdx (optional arg) >> Keeps track of amount of processed format specifiers
|
||||
; rcx (optional arg)
|
||||
; r8 (optional arg) >> Used for moving characters
|
||||
; r9 (optional arg) >> Keeps track of where to jump after flushing buffer
|
||||
; r10* Keeps track of current index of printfBuff
|
||||
; r11* Keeps track of total characters (return value)
|
||||
printf:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
sub rsp, SIZE_QWORD
|
||||
|
||||
cmp byte [rdi], EOS
|
||||
je .emptyStr
|
||||
|
||||
xor r10, r10
|
||||
xor r11, r11
|
||||
|
||||
; Store arguments to memory - easier to load data + more available registers (= less stack usage)
|
||||
mov [printfArgs + SIZE_QWORD * 0], rsi
|
||||
mov [printfArgs + SIZE_QWORD * 1], rdx
|
||||
mov [printfArgs + SIZE_QWORD * 2], rcx
|
||||
mov [printfArgs + SIZE_QWORD * 3], r8
|
||||
mov [printfArgs + SIZE_QWORD * 4], r9
|
||||
|
||||
.process:
|
||||
cmp byte [rdi], EOS
|
||||
je .wrapup
|
||||
mov r9b, 0
|
||||
cmp r10, printfBuffLen-1
|
||||
je .flushBuffer
|
||||
.flushReturn_0:
|
||||
cmp byte [rdi], '%'
|
||||
je .argReplacement
|
||||
mov r8b, [rdi]
|
||||
mov [printfBuff+r10], r8b
|
||||
inc r10
|
||||
inc r11
|
||||
inc rdi
|
||||
jmp .process
|
||||
|
||||
.argReplacement:
|
||||
cmp byte [rdi + 1], EOS
|
||||
je .wrapup
|
||||
cmp byte [rdi + 1], '%'
|
||||
je .rep_pct
|
||||
|
||||
;--- Invalid ---;
|
||||
mov r9w, word [rdi]
|
||||
mov [printfBuff+r10], r9w
|
||||
add rdi, 2
|
||||
add r10, 2
|
||||
add r11, 2
|
||||
jmp .process
|
||||
|
||||
;--- '%%' ---;
|
||||
.rep_pct:
|
||||
mov [printfBuff+r10], byte '%'
|
||||
add rdi, 2
|
||||
add r10, 1
|
||||
add r11, 1
|
||||
jmp .process
|
||||
|
||||
|
||||
.flushBuffer:
|
||||
push rdx
|
||||
push r11
|
||||
mov rax, NR_write
|
||||
mov rdi, FD_stdout
|
||||
lea rsi, [rel printfBuff]
|
||||
mov rdx, r11
|
||||
syscall
|
||||
pop r10
|
||||
pop rdx
|
||||
xor r10, r10
|
||||
|
||||
cmp r9b, 0
|
||||
je .flushReturn_0
|
||||
|
||||
.wrapup:
|
||||
mov rax, NR_write
|
||||
mov rdi, FD_stdout
|
||||
lea rsi, [rel printfBuff]
|
||||
mov rdx, r10
|
||||
mov r10, r11
|
||||
syscall
|
||||
mov rax, r10
|
||||
jmp .quit
|
||||
|
||||
.emptyStr:
|
||||
xor rax, rax
|
||||
|
||||
.quit:
|
||||
add rsp, SIZE_QWORD
|
||||
leave
|
||||
ret
|
||||
|
@@ -5,6 +5,7 @@ extern exit
|
||||
; console.asm
|
||||
extern print
|
||||
extern puts
|
||||
extern printf
|
||||
; string.asm
|
||||
extern strlen
|
||||
extern strcpy
|
||||
@@ -14,6 +15,7 @@ extern strcat
|
||||
section .rodata
|
||||
TEST_print equ 1
|
||||
TEST_puts equ 1
|
||||
TEST_printf equ 1
|
||||
TEST_strlen equ 1
|
||||
TEST_strcpy equ 1
|
||||
TEST_strcat equ 1
|
||||
@@ -30,6 +32,11 @@ section .rodata
|
||||
; puts()
|
||||
msgPuts db "TEST puts()",EOS
|
||||
|
||||
; printf()
|
||||
msgPrintf db "TEST printf()",NL,EOS
|
||||
printf1 db TAB,"printf(",DQUO,"He%ll%o there%%%%%!%s%!%\n",DQUO,"): ",NL,TAB,TAB,EOS
|
||||
printf1Str db "He%ll%o there%%%%%!%s%!%",NL,EOS
|
||||
|
||||
; strlen()
|
||||
strlenStr1 db "Hello",EOS
|
||||
strlenStr2 db "Hello, world!",NL,EOS
|
||||
@@ -75,6 +82,20 @@ _start:
|
||||
call puts
|
||||
%endif
|
||||
|
||||
;---
|
||||
;--- printf()
|
||||
;---
|
||||
%if TEST_printf
|
||||
lea rdi, [rel msgPrintf]
|
||||
call printf
|
||||
|
||||
; TEST 1
|
||||
lea rdi, [rel printf1]
|
||||
call print
|
||||
lea rdi, [rel printf1Str]
|
||||
call printf
|
||||
%endif
|
||||
|
||||
;---
|
||||
;--- strlen()
|
||||
;---
|
||||
|
Reference in New Issue
Block a user