# Copyright (C) 2026 Sebastian G. Kirmayer # # 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 . # # 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 "