From 2d78510b9af6f70ec34d77f0e047c698bdf061a9 Mon Sep 17 00:00:00 2001 From: Mikhail Osipov Date: Sat, 12 Oct 2019 00:23:50 +0300 Subject: draft --- Makefile | 4 +-- backup.s | 32 +++++++++++++++++ lib.s | 17 +++++++++ main.s | 14 ++++++-- printf.s | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ restore.s | 32 +++++++++++++++++ string.s | 21 +++++++++++ sys.s | 4 --- 8 files changed, 235 insertions(+), 9 deletions(-) create mode 100644 backup.s create mode 100644 lib.s create mode 100644 printf.s create mode 100644 restore.s create mode 100644 string.s 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 -- cgit v1.2.3-70-g09d2