summaryrefslogtreecommitdiff
path: root/start.asm
diff options
context:
space:
mode:
authorSebastian G. Kirmayer <gloria@gloria-mundi.eu>2026-07-07 23:54:15 +0200
committerSebastian G. Kirmayer <gloria@gloria-mundi.eu>2026-07-07 23:54:15 +0200
commit9a6c7d85eb1be819b94d0feb0cb84de8546e36fd (patch)
tree73bab5bccdeffed245bd596cdeadde5cfddeb42f /start.asm
Diffstat (limited to 'start.asm')
-rw-r--r--start.asm456
1 files changed, 456 insertions, 0 deletions
diff --git a/start.asm b/start.asm
new file mode 100644
index 0000000..b2bef32
--- /dev/null
+++ b/start.asm
@@ -0,0 +1,456 @@
+# Copyright (C) 2026 Sebastian G. Kirmayer <gloria@gloria-mundi.eu>
+#
+# This file is part of sysf-i386.
+#
+# sysf-i386 is free software: you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option)
+# any later version.
+#
+# sysf-i386 is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along
+# with sysf-i386. If not, see <https://www.gnu.org/licenses/>.
+#
+
+# Syscall numbers
+NR_exit=1
+NR_read=3
+NR_write=4
+NR_open=5
+NR_close=6
+NR_brk=45
+
+text
+label _start
+ call init_heap
+
+ # option parsing
+ leal @%esp+4 %ebp
+
+L loop
+ addl 4 %ebp
+ movl @%ebp %ebx
+ testl %ebx %ebx
+ jz done.
+ movb @%ebx %cl
+ cmpb 0x2D %cl # -
+ jne filename.
+ incl %ebx
+ movb @%ebx %cl
+ cmpb 0x00 %cl
+ je filename.
+ cmpb 0x2D %cl # -
+ je longopt.
+ cmpb 0x3F %cl # ?
+ je usage
+ cmpb 0x56 %cl # V
+ je print_version
+ jmp bad_usage
+
+L longopt
+ incl %ebx
+ movb @%ebx %cl
+ cmpb 0x00 %cl
+ je opts_end.
+ movl %ebx %eax
+ call strnul
+ pushl %eax
+ pushl %eax
+ movl flag_version %eax
+ movl flag_version_end %ecx
+ movl %ebx %edx
+ call streq
+ je print_version
+ movl flag_help %eax
+ movl flag_help_end %ecx
+ movl %ebx %edx
+ call streq
+ je usage
+ jmp bad_usage
+
+L opts_end
+ addl 4 %ebp
+ movl @%ebp %ebx
+ testl %ebx %ebx
+ jz done.
+L filename
+ movl @%ebp+4 %eax
+ testl %eax %eax
+ jnz bad_usage
+ movl @%ebp %ebx
+ movb @%ebx %cl
+ cmpb 0x2D %cl
+ jne open_file.
+ movb @%ebx %cl
+ cmpb 0x00 %cl
+ je done.
+L open_file
+ movl $NR_open %eax
+ xorl %ecx %ecx
+ int 0x80
+ testl %eax %eax
+ js open_failed.
+ movl %eax %edi
+ movl @heap_ptr %esi
+ call slurp
+ movl %edi %ebx
+ movl $NR_close %eax
+ int 0x80
+ movl %esi %ebx
+ jmp slurped.
+
+L open_failed
+ stderr 'Failed to open '
+ movl %ebx %eax
+ call strnul
+ movl %eax %ecx
+ movl %ebx %eax
+ call stderr
+ stderr '
+'
+ jmp error
+
+L done
+ # slurp(stdin)
+ xorl %eax %eax
+ movl @heap_ptr %ebx
+ call slurp
+L slurped
+ # parse(slurped code)
+ movl %ebx %eax
+ movl @heap_ptr %ecx
+ call parse
+ call ty_top
+ movl %eax %ebx
+ call ty_main
+ call ty_top
+ movl %ebx %ecx
+ call ty_eq
+ jne bad_main.
+ movl @heap_ptr %eax
+ jmp execute
+
+L bad_main
+ stderr 'Bad main type: '
+ movl %ebx %eax
+ call ty_stderr
+ stderr '
+'
+ jmp error
+
+label ty_main
+ # fix
+ movl 0 %eax
+ call ty_var
+ movl 1 %eax
+ call ty_var
+ call ty_arrow
+ movl 0 %eax
+ call ty_var
+ movl 1 %eax
+ call ty_var
+ call ty_arrow
+ call ty_arrow
+ movl 0 %eax
+ call ty_var
+ movl 1 %eax
+ call ty_var
+ call ty_arrow
+ call ty_arrow
+ call ty_forall
+ # read
+ movl 0 %eax
+ call ty_var
+ movl 0 %eax
+ call ty_var
+ movl 0 %eax
+ call ty_var
+ movl 0 %eax
+ call ty_var
+ call ty_arrow
+ call ty_arrow
+ call ty_arrow
+ # write0
+ movl 0 %eax
+ call ty_var
+ movl 0 %eax
+ call ty_var
+ call ty_arrow
+ # write1
+ movl 0 %eax
+ call ty_var
+ movl 0 %eax
+ call ty_var
+ call ty_arrow
+ # exit
+ movl 0 %eax
+ call ty_var
+ movl 0 %eax
+ call ty_var
+ call ty_arrow
+ call ty_arrow
+ call ty_arrow
+ call ty_arrow
+ call ty_arrow
+ call ty_forall
+ ret
+
+label slurp # (fd: i32) -> ()
+ pushl %ebx
+ movl %eax %ebx
+ # %ebx: file descriptor
+L start
+ movl @heap_ptr %ecx
+ movl @heap_end %edx
+L loop
+ subl %ecx %edx
+ jz alloc.
+ movl $NR_read %eax
+ int 0x80
+ addl %ecx %edx
+ testl %eax %eax
+ js fail.
+ jz done.
+ addl %eax %ecx
+ jmp loop^
+L alloc
+ movl %ecx @heap_ptr
+ call alloc
+ jmp start^
+L done
+ movl %ecx @heap_ptr
+ popl %ebx
+ ret
+L fail
+ stderr 'Failed to read program
+'
+ jmp error
+
+bss
+align
+label heap_ptr
+ long 0
+label heap_end
+ long 0
+
+text
+label init_heap # () -> ()
+ movl %ebx %ecx
+ xorl %ebx %ebx
+ movl $NR_brk %eax
+ int 0x80
+ movl %eax @heap_ptr
+ movl %eax @heap_end
+ movl %ecx %ebx
+ ret
+
+label align_heap # () -> ()
+ movl @heap_ptr %eax
+ addl 3 %eax
+ andl $((~3)) %eax
+ movl %eax @heap_ptr
+ ret
+
+label alloc # () -> ()
+ movl %ebx %ecx
+ movl @heap_end %ebx
+ addl 0x1000 %ebx
+ movl $NR_brk %eax
+ int 0x80
+ cmpl %eax %ebx
+ jne error
+ movl %eax @heap_end
+ movl %ecx %ebx
+ ret
+
+bss
+label buffer_start
+ skip 0x100
+label buffer_cap buffer_start
+align
+label buffer_pos
+ long 0
+label buffer_len
+ long 0
+text
+
+# -1: EOF
+# 0: 0
+# 1: 1
+label read # () -> (bit: i32)
+ movl @buffer_pos %ecx
+ movl %ecx %edx
+ shrl 3 %edx
+ cmpl @buffer_len %edx
+ je read.
+ xorl %eax %eax
+ movb @buffer_start+%edx %al
+ andl 7 %ecx
+ shrl %cl %eax
+ andl 1 %eax
+ incl @buffer_pos
+ ret
+
+L read
+ pushl %ebx
+ xorl %ebx %ebx
+ movl buffer_start %ecx
+ movl buffer_cap %edx
+ movl $NR_read %eax
+ int 0x80
+ popl %ebx
+ testl %eax %eax
+ js error.
+ jz eof.
+ movl %eax @buffer_len
+ movl 0 @buffer_pos
+ jmp read
+
+L eof
+ movl -1 %eax
+ ret
+
+L error
+ stderr 'Error reading from stdin
+'
+ jmp error
+
+bss
+label write_buf
+ byte 0
+label write_bit
+ byte 0
+text
+
+label write0
+ movl 0 %eax
+ jmp write.
+label write1
+ movl 1 %eax
+L write
+ xorl %ecx %ecx
+ movb @write_bit %cl
+ shll %cl %eax
+ orb %al @write_buf
+ incb %cl
+ cmpb 8 %cl
+ je do_write.
+ movb %cl @write_bit
+ ret
+L do_write
+ movb 0 @write_bit
+ pushl %ebx
+ movl 1 %ebx
+ movl write_buf %ecx
+ movl 1 %edx
+ movl $NR_write %eax
+ int 0x80
+ popl %ebx
+ movb 0 @write_buf
+ ret
+
+label exit
+ movl $NR_exit %eax
+ xorl %ebx %ebx
+ int 0x80
+
+label usage
+ call print_usage
+ jmp exit
+
+label bad_usage
+ call print_usage
+ jmp error
+
+label print_usage
+ movl 1 %ebx
+ movl usage_info %ecx
+ movl usage_info_len %edx
+ movl $NR_write %eax
+ int 0x80
+ ret
+
+label print_version
+ movl 1 %ebx
+ movl version_info %ecx
+ movl version_info_len %edx
+ movl $NR_write %eax
+ int 0x80
+ jmp exit
+
+label error
+ movl $NR_exit %eax
+ movl 1 %ebx
+ int 0x80
+
+label stderr
+ pushl %ebx
+ movl %ecx %edx
+ movl %eax %ecx
+ subl %eax %edx
+ movl 2 %ebx
+ movl $NR_write %eax
+ int 0x80
+ popl %ebx
+ ret
+
+label stderr_lineno
+ pushl %ebx
+ pushl %ebp
+ movl %esp %ebp
+ movl %esp %ebx
+ subl 0x20 %esp
+ subl 2 %ebx
+ movb 0x3A @%ebx
+ movb 0x20 @%ebx+1
+ movl @lineno %eax
+ movl 10 %ecx
+L loop
+ xorl %edx %edx
+ divl %ecx
+ addl 0x30 %edx
+ decl %ebx
+ movb %dl @%ebx
+ testl %eax %eax
+ jnz loop^
+ subl 5 %ebx
+ movb 0x4C @%ebx
+ movb 0x69 @%ebx+1
+ movb 0x6E @%ebx+2
+ movb 0x65 @%ebx+3
+ movb 0x20 @%ebx+4
+ movl %ebx %eax
+ movl %ebp %ecx
+ call stderr
+ movl %ebp %esp
+ popl %ebp
+ popl %ebx
+ ret
+
+label report_error
+ pushl %eax
+ pushl %ecx
+ call stderr_lineno
+ popl %ecx
+ popl %eax
+ call stderr
+ ret
+
+rodata
+string flag_version "version"
+string flag_help "help"
+
+string version_info "\
+sysf-i386 $SYSF_VERSION
+Copyright (C) 2026 Sebastian G. Kirmayer, GNU GPLv3+
+"
+
+string usage_info "\
+Usage:
+ sysf FILENAME
+ sysf --version
+"