summaryrefslogtreecommitdiff
path: root/printf.s
diff options
context:
space:
mode:
authorMikhail Osipov <mike.osipov@gmail.com>2019-10-12 00:23:50 +0300
committerMikhail Osipov <mike.osipov@gmail.com>2019-10-12 00:23:50 +0300
commit2d78510b9af6f70ec34d77f0e047c698bdf061a9 (patch)
treef56f2c9d7c29952748d62aa99d6e8fdc76402ada /printf.s
parent1248eae0617555a4f13f7bbee9f120ad3d46c5f3 (diff)
draftng
Diffstat (limited to 'printf.s')
-rw-r--r--printf.s120
1 files changed, 120 insertions, 0 deletions
diff --git a/printf.s b/printf.s
new file mode 100644
index 0000000..3bb24ca
--- /dev/null
+++ b/printf.s
@@ -0,0 +1,120 @@
+.include "lib.s"
+
+.macro bufpush
+ cmpq $bufend, %rdi
+ jle 9f
+ stosb
+ 9:
+.endm
+
+.globl printf
+printf:
+ prologue
+
+ backup %rax, %rbx, %rcx, %rdx
+ backup %rsi, %rdi
+
+ movq 16(%rbp), %rsi
+ leaq 24(%rbp), %rbx
+ movq $buf, %rdi
+
+.loop:
+ lodsb
+ testb %al, %al
+ jz .loopout
+
+ cmpb $'%, %al
+ jne .append
+
+ lodsb
+ testb %al, %al
+ jz .loopout
+
+ cmpb $'%, %al
+ je .append
+
+ cmpb $'s, %al
+ je .print_string
+
+ cmpb $'d, %al
+ je .print_signed
+
+ cmpb $'u, %al
+ je .print_unsigned
+
+ jmp .loop
+
+.append:
+ bufpush
+ jmp .loop
+
+.print_string:
+ backup %rsi
+
+ movq (%rbx), %rsi
+ addq $8, %rbx
+ jmp 2f
+
+ 1: bufpush
+ 2: lodsb
+ testb %al, %al
+ jnz 1b
+
+ restore %rsi
+ jmp .loop
+
+.print_signed:
+ movq (%rbx), %rax
+ addq $8, %rbx
+
+ cmpq $0, %rax
+ jge 1f
+
+ pushq %rax
+ movb $'-, %al
+ bufpush
+ popq %rax
+ negq %rax
+
+ 1:
+ movq $10, %rcx
+ call .print_number
+ jmp .loop
+
+.print_unsigned:
+ movq (%rbx), %rax
+ addq $8, %rbx
+
+ movq $10, %rcx
+ call .print_number
+ jmp .loop
+
+.print_number:
+ xorq %rdx, %rdx
+ divq %rcx
+ pushq %rdx
+ testq %rax, %rax
+ jz 1f
+ call .print_number
+ 1:
+ popq %rax
+ addq $'0, %rax
+ bufpush
+ ret
+
+.loopout:
+ movq %rdi, %rdx
+ subq $buf, %rdx
+ movq $buf, %rsi
+ movq $STDOUT, %rdi
+ sys write
+
+ restore %rsi, %rdi
+ restore %rax, %rbx, %rcx, %rdx
+
+ leave
+ ret
+
+.bss
+.comm buf, 4096
+.comm bufend, 2