summaryrefslogtreecommitdiff
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
parent1248eae0617555a4f13f7bbee9f120ad3d46c5f3 (diff)
draftng
-rw-r--r--Makefile4
-rw-r--r--backup.s32
-rw-r--r--lib.s17
-rw-r--r--main.s14
-rw-r--r--printf.s120
-rw-r--r--restore.s32
-rw-r--r--string.s21
-rw-r--r--sys.s4
8 files changed, 235 insertions, 9 deletions
diff --git a/Makefile b/Makefile
index 69beadf..05f6c5f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
PROGNAME=$(shell pwd | xargs basename)
-$(PROGNAME): main.o
- ld -o $@ $<
+$(PROGNAME): main.o printf.o string.o
+ ld -o $@ $^
%.o: %.s syscall.s
as -o $@ $<
diff --git a/backup.s b/backup.s
new file mode 100644
index 0000000..10f9fb5
--- /dev/null
+++ b/backup.s
@@ -0,0 +1,32 @@
+.ifndef __BACKUP__
+.set __BACKUP__, 1
+
+.macro __backup_next n, args:vararg
+.ifnb \args
+ __backup\n \args
+.endif
+.endm
+
+.macro __backup4 arg:req, args:vararg
+ pushq \arg
+.ifnb \args
+.error "backup: too many arguments"
+.endif
+.endm
+
+.macro __backup3 arg:req, args:vararg
+ pushq \arg
+ __backup_next 4, \args
+.endm
+
+.macro __backup2 arg:req, args:vararg
+ pushq \arg
+ __backup_next 3, \args
+.endm
+
+.macro backup arg:req, args:vararg
+ pushq \arg
+ __backup_next 2, \args
+.endm
+
+.endif
diff --git a/lib.s b/lib.s
new file mode 100644
index 0000000..1397b90
--- /dev/null
+++ b/lib.s
@@ -0,0 +1,17 @@
+.ifndef __LIB__
+.set __LIB__, 1
+
+.include "restore.s"
+.include "backup.s"
+.include "sys.s"
+
+.macro prologue
+ pushq %rbp
+ movq %rsp, %rbp
+.endm
+
+.set STDIN, 0
+.set STDOUT, 1
+.set STDERR, 2
+
+.endif
diff --git a/main.s b/main.s
index aa1f293..7bc2b73 100644
--- a/main.s
+++ b/main.s
@@ -2,9 +2,17 @@
.globl _start
_start:
- sys write, $STDOUT, $msg, $len
+ movq %rsp, %rbp
+
+ pushq $-1024
+ pushq $-1024
+ pushq $msg
+ pushq $fmt
+ call printf
+
sys exit, $0
.data
-msg: .ascii "Hello, World!\n"
-len = .-msg
+fmt: .asciz "%s and %d and %u\n"
+msg: .asciz "Hello, World"
+bye: .asciz "bye!"
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
diff --git a/restore.s b/restore.s
new file mode 100644
index 0000000..da1ec03
--- /dev/null
+++ b/restore.s
@@ -0,0 +1,32 @@
+.ifndef __RESTORE__
+.set __RESTORE__, 1
+
+.macro __restore_next n, args:vararg
+.ifnb \args
+ __restore\n \args
+.endif
+.endm
+
+.macro __restore4 arg:req, args:vararg
+.ifnb \args
+.error "restore: too many arguments"
+.endif
+ popq \arg
+.endm
+
+.macro __restore3 arg:req, args:vararg
+ __restore_next 4, \args
+ popq \arg
+.endm
+
+.macro __restore2 arg:req, args:vararg
+ __restore_next 3, \args
+ popq \arg
+.endm
+
+.macro restore arg:req, args:vararg
+ __restore_next 2, \args
+ popq \arg
+.endm
+
+.endif
diff --git a/string.s b/string.s
new file mode 100644
index 0000000..b6bc317
--- /dev/null
+++ b/string.s
@@ -0,0 +1,21 @@
+.include "lib.s"
+
+.globl strlen
+strlen:
+ prologue
+
+ backup %rdi, %rcx
+
+ movq 16(%rbp), %rdi
+ xorq %rax, %rax
+ movq $-1, %rcx
+
+ repne scasb
+
+ movq $-2, %rax
+ subq %rcx, %rax
+
+ restore %rdi, %rcx
+
+ leave
+ ret
diff --git a/sys.s b/sys.s
index 2a76e09..b2d002e 100644
--- a/sys.s
+++ b/sys.s
@@ -62,8 +62,4 @@
syscall
.endm
-.set STDIN, 0
-.set STDOUT, 1
-.set STDERR, 2
-
.endif