printf(): Add support for %s, fix buffer flushing (length given was r11, not r10)
This commit is contained in:
@@ -7,7 +7,7 @@ section .rodata
|
||||
printfBuffLen equ 128
|
||||
section .bss
|
||||
printfBuff resb printfBuffLen
|
||||
printfArgs resq 5
|
||||
printfArgs resq 5 ;5=>rsi,rdx,rcx,r8,r9
|
||||
section .text
|
||||
global print
|
||||
global puts
|
||||
@@ -59,15 +59,17 @@ puts:
|
||||
; Return value: Amount of printed characters
|
||||
; Supported specifiers:
|
||||
; %% Literal percentage sign
|
||||
; %s String
|
||||
; <!> 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:
|
||||
; 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
|
||||
; rax* (ret) amount of printed characters
|
||||
; rdi* (arg) pointer to format[] to format and print
|
||||
; rsi* (optional arg) >> Used for inserting strings to buffer
|
||||
; 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
|
||||
; 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:
|
||||
@@ -77,16 +79,17 @@ printf:
|
||||
|
||||
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
|
||||
mov [rel printfArgs + SIZE_QWORD * 0], rsi
|
||||
mov [rel printfArgs + SIZE_QWORD * 1], rdx
|
||||
mov [rel printfArgs + SIZE_QWORD * 2], rcx
|
||||
mov [rel printfArgs + SIZE_QWORD * 3], r8
|
||||
mov [rel printfArgs + SIZE_QWORD * 4], r9
|
||||
|
||||
xor rdx, rdx
|
||||
xor r10, r10
|
||||
xor r11, r11
|
||||
|
||||
.process:
|
||||
cmp byte [rdi], EOS
|
||||
@@ -109,6 +112,8 @@ printf:
|
||||
je .wrapup
|
||||
cmp byte [rdi + 1], '%'
|
||||
je .rep_pct
|
||||
cmp byte [rdi + 1], 's'
|
||||
je .rep_s
|
||||
|
||||
;--- Invalid ---;
|
||||
mov r9w, word [rdi]
|
||||
@@ -125,22 +130,55 @@ printf:
|
||||
add r10, 1
|
||||
add r11, 1
|
||||
jmp .process
|
||||
|
||||
|
||||
;--- '%s' ---;
|
||||
.rep_s:
|
||||
cmp rdx, 4
|
||||
ja .s_fromStack
|
||||
mov rsi, [printfArgs + SIZE_QWORD * rdx]
|
||||
jmp .insertString
|
||||
.s_fromStack:
|
||||
lea rsi, [rbp + RBP_OFFSET_CALLER + ((rdx-5) * SIZE_QWORD)]
|
||||
|
||||
;--- Insert string to buffer ---;
|
||||
.insertString:
|
||||
cmp byte [rsi], EOS
|
||||
je .endInsertString
|
||||
mov r9b, 1
|
||||
cmp r10, printfBuffLen-1
|
||||
je .flushBuffer
|
||||
.flushReturn_1:
|
||||
mov r8b, byte [rsi]
|
||||
mov [printfBuff + r10], r8b
|
||||
inc rsi
|
||||
inc r10
|
||||
inc r11
|
||||
jmp .insertString
|
||||
.endInsertString:
|
||||
inc rdx
|
||||
add rdi, 2
|
||||
jmp .process
|
||||
|
||||
.flushBuffer:
|
||||
push rdi
|
||||
push rsi
|
||||
push rdx
|
||||
push r11
|
||||
mov rax, NR_write
|
||||
mov rdi, FD_stdout
|
||||
lea rsi, [rel printfBuff]
|
||||
mov rdx, r11
|
||||
mov rdx, r10
|
||||
syscall
|
||||
pop r10
|
||||
pop r11
|
||||
pop rdx
|
||||
pop rsi
|
||||
pop rdi
|
||||
xor r10, r10
|
||||
|
||||
cmp r9b, 0
|
||||
je .flushReturn_0
|
||||
cmp r9b, 1
|
||||
je .flushReturn_1
|
||||
|
||||
.wrapup:
|
||||
mov rax, NR_write
|
||||
|
@@ -34,8 +34,12 @@ section .rodata
|
||||
|
||||
; 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
|
||||
printf1 db TAB,"printf(",DQUO,"He%ll%o there%%%%%!%!%\n",DQUO,"): ",NL,TAB,TAB,EOS
|
||||
printf1Str db "He%ll%o there%%%%%!%!%",NL,EOS
|
||||
printf2 db TAB,"printf(",DQUO,"Are %s doing %s?\n",DQUO,", printf2Str1, printf2Str2): ",NL,TAB,TAB,EOS
|
||||
printf2Str db "Are %s doing %s?",NL,EOS
|
||||
printf2Str1 db "you",EOS
|
||||
printf2Str2 db "okay",EOS
|
||||
|
||||
; strlen()
|
||||
strlenStr1 db "Hello",EOS
|
||||
@@ -94,6 +98,14 @@ _start:
|
||||
call print
|
||||
lea rdi, [rel printf1Str]
|
||||
call printf
|
||||
|
||||
; TEST 2
|
||||
lea rdi, [rel printf2]
|
||||
call print
|
||||
lea rdi, [rel printf2Str]
|
||||
lea rsi, [rel printf2Str1]
|
||||
lea rdx, [rel printf2Str2]
|
||||
call printf
|
||||
%endif
|
||||
|
||||
;---
|
||||
|
Reference in New Issue
Block a user