start C compiler
This commit is contained in:
parent
262824b214
commit
5d6b490cce
7 changed files with 528 additions and 0 deletions
357
05/util.b
Normal file
357
05/util.b
Normal file
|
@ -0,0 +1,357 @@
|
|||
|
||||
function file_error
|
||||
argument name
|
||||
fputs(2, .str_file_error)
|
||||
fputs(2, name)
|
||||
fputc(2, 10)
|
||||
exit(1)
|
||||
|
||||
:str_file_error
|
||||
string Error opening file:
|
||||
byte 32
|
||||
byte 0
|
||||
|
||||
function malloc
|
||||
argument size
|
||||
local total_size
|
||||
local memory
|
||||
total_size = size + 8
|
||||
memory = syscall(9, 0, total_size, 3, 0x22, -1, 0)
|
||||
if memory ] 0xffffffffffff0000 goto malloc_failed
|
||||
*8memory = total_size
|
||||
return memory + 8
|
||||
|
||||
:malloc_failed
|
||||
fputs(2, .str_out_of_memory)
|
||||
exit(1)
|
||||
|
||||
:str_out_of_memory
|
||||
string Out of memory.
|
||||
byte 10
|
||||
byte 0
|
||||
|
||||
function free
|
||||
argument memory
|
||||
local psize
|
||||
local size
|
||||
psize = memory - 8
|
||||
size = *8psize
|
||||
syscall(11, psize, size)
|
||||
return
|
||||
|
||||
; returns a pointer to a null-terminated string containing the number given
|
||||
function itos
|
||||
global 32 itos_string
|
||||
argument x
|
||||
local c
|
||||
local p
|
||||
p = &itos_string
|
||||
p += 30
|
||||
:itos_loop
|
||||
c = x % 10
|
||||
c += '0
|
||||
*1p = c
|
||||
x /= 10
|
||||
if x == 0 goto itos_loop_end
|
||||
p -= 1
|
||||
goto itos_loop
|
||||
:itos_loop_end
|
||||
return p
|
||||
|
||||
|
||||
; returns the number at the start of the given string
|
||||
function stoi
|
||||
argument s
|
||||
local p
|
||||
local n
|
||||
local c
|
||||
n = 0
|
||||
p = s
|
||||
:stoi_loop
|
||||
c = *1p
|
||||
if c < '0 goto stoi_loop_end
|
||||
if c > '9 goto stoi_loop_end
|
||||
n *= 10
|
||||
n += c - '0
|
||||
p += 1
|
||||
goto stoi_loop
|
||||
:stoi_loop_end
|
||||
return n
|
||||
|
||||
function memchr
|
||||
argument mem
|
||||
argument c
|
||||
local p
|
||||
local a
|
||||
p = mem
|
||||
:memchr_loop
|
||||
a = *1p
|
||||
if a == c goto memchr_loop_end
|
||||
p += 1
|
||||
goto memchr_loop
|
||||
:memchr_loop_end
|
||||
return p
|
||||
|
||||
function strlen
|
||||
argument s
|
||||
local c
|
||||
local p
|
||||
p = s
|
||||
:strlen_loop
|
||||
c = *1p
|
||||
if c == 0 goto strlen_loop_end
|
||||
p += 1
|
||||
goto strlen_loop
|
||||
:strlen_loop_end
|
||||
return p - s
|
||||
|
||||
function strcpy
|
||||
argument dest
|
||||
argument src
|
||||
local p
|
||||
local q
|
||||
local c
|
||||
p = dest
|
||||
q = src
|
||||
:strcpy_loop
|
||||
c = *1q
|
||||
*1p = c
|
||||
if c == 0 goto strcpy_loop_end
|
||||
p += 1
|
||||
q += 1
|
||||
goto strcpy_loop
|
||||
:strcpy_loop_end
|
||||
return p
|
||||
|
||||
function str_startswith
|
||||
argument s
|
||||
argument prefix
|
||||
local p
|
||||
local q
|
||||
local c1
|
||||
local c2
|
||||
p = s
|
||||
q = prefix
|
||||
:str_startswith_loop
|
||||
c1 = *1p
|
||||
c2 = *1q
|
||||
if c2 == 0 goto return_1
|
||||
if c1 != c2 goto return_0
|
||||
p += 1
|
||||
q += 1
|
||||
goto str_startswith_loop
|
||||
|
||||
function fputs
|
||||
argument fd
|
||||
argument s
|
||||
local length
|
||||
length = strlen(s)
|
||||
syscall(1, fd, s, length)
|
||||
return
|
||||
|
||||
function puts
|
||||
argument s
|
||||
fputs(1, s)
|
||||
return
|
||||
|
||||
function fputn
|
||||
argument fd
|
||||
argument n
|
||||
local s
|
||||
s = itos(n)
|
||||
fputs(fd, s)
|
||||
return
|
||||
|
||||
function fputc
|
||||
argument fd
|
||||
argument c
|
||||
local p
|
||||
p = &c
|
||||
syscall(1, fd, p, 1)
|
||||
return
|
||||
|
||||
function putc
|
||||
argument c
|
||||
fputc(1, c)
|
||||
return
|
||||
|
||||
; returns 0 at end of file
|
||||
function fgetc
|
||||
argument fd
|
||||
local c
|
||||
local p
|
||||
c = 0
|
||||
p = &c
|
||||
syscall(0, fd, p, 1)
|
||||
return c
|
||||
|
||||
; read a line from fd as a null-terminated string
|
||||
; returns 0 at end of file, 1 otherwise
|
||||
function fgets
|
||||
argument fd
|
||||
argument buf
|
||||
argument size
|
||||
local p
|
||||
local end
|
||||
local c
|
||||
p = buf
|
||||
end = buf + size
|
||||
|
||||
:fgets_loop
|
||||
c = fgetc(fd)
|
||||
if c == 0 goto fgets_eof
|
||||
if c == 10 goto fgets_eol
|
||||
*1p = c
|
||||
p += 1
|
||||
if p == end goto fgets_eob
|
||||
goto fgets_loop
|
||||
|
||||
:fgets_eol ; end of line
|
||||
*1p = 0
|
||||
return 1
|
||||
:fgets_eof ; end of file
|
||||
*1p = 0
|
||||
return 0
|
||||
:fgets_eob ; end of buffer
|
||||
p -= 1
|
||||
*1p = 0
|
||||
return 1
|
||||
|
||||
; open the given file for reading
|
||||
function open_r
|
||||
argument filename
|
||||
local fd
|
||||
fd = syscall(2, filename, 0)
|
||||
if fd < 0 goto open_r_error
|
||||
return fd
|
||||
:open_r_error
|
||||
file_error(filename)
|
||||
return -1
|
||||
|
||||
; open the given file for writing with the given mode
|
||||
function open_w
|
||||
argument filename
|
||||
argument mode
|
||||
local fd
|
||||
fd = syscall(2, filename, 0x241, mode)
|
||||
if fd < 0 goto open_w_error
|
||||
return fd
|
||||
:open_w_error
|
||||
file_error(filename)
|
||||
return -1
|
||||
|
||||
function close
|
||||
argument fd
|
||||
syscall(3, fd)
|
||||
return
|
||||
|
||||
function isupper
|
||||
argument c
|
||||
if c < 'A goto return_0
|
||||
if c <= 'Z goto return_1
|
||||
goto return_0
|
||||
|
||||
function exit
|
||||
argument status_code
|
||||
syscall(0x3c, status_code)
|
||||
|
||||
:return_0
|
||||
return 0
|
||||
:return_1
|
||||
return 1
|
||||
|
||||
function syscall
|
||||
; I've done some testing, and this should be okay even if
|
||||
; rbp-56 goes beyond the end of the stack.
|
||||
; mov rax, [rbp-16]
|
||||
byte 0x48
|
||||
byte 0x8b
|
||||
byte 0x85
|
||||
byte 0xf0
|
||||
byte 0xff
|
||||
byte 0xff
|
||||
byte 0xff
|
||||
; mov rdi, rax
|
||||
byte 0x48
|
||||
byte 0x89
|
||||
byte 0xc7
|
||||
|
||||
; mov rax, [rbp-24]
|
||||
byte 0x48
|
||||
byte 0x8b
|
||||
byte 0x85
|
||||
byte 0xe8
|
||||
byte 0xff
|
||||
byte 0xff
|
||||
byte 0xff
|
||||
; mov rsi, rax
|
||||
byte 0x48
|
||||
byte 0x89
|
||||
byte 0xc6
|
||||
|
||||
; mov rax, [rbp-32]
|
||||
byte 0x48
|
||||
byte 0x8b
|
||||
byte 0x85
|
||||
byte 0xe0
|
||||
byte 0xff
|
||||
byte 0xff
|
||||
byte 0xff
|
||||
; mov rdx, rax
|
||||
byte 0x48
|
||||
byte 0x89
|
||||
byte 0xc2
|
||||
|
||||
; mov rax, [rbp-40]
|
||||
byte 0x48
|
||||
byte 0x8b
|
||||
byte 0x85
|
||||
byte 0xd8
|
||||
byte 0xff
|
||||
byte 0xff
|
||||
byte 0xff
|
||||
; mov r10, rax
|
||||
byte 0x49
|
||||
byte 0x89
|
||||
byte 0xc2
|
||||
|
||||
; mov rax, [rbp-48]
|
||||
byte 0x48
|
||||
byte 0x8b
|
||||
byte 0x85
|
||||
byte 0xd0
|
||||
byte 0xff
|
||||
byte 0xff
|
||||
byte 0xff
|
||||
; mov r8, rax
|
||||
byte 0x49
|
||||
byte 0x89
|
||||
byte 0xc0
|
||||
|
||||
; mov rax, [rbp-56]
|
||||
byte 0x48
|
||||
byte 0x8b
|
||||
byte 0x85
|
||||
byte 0xc8
|
||||
byte 0xff
|
||||
byte 0xff
|
||||
byte 0xff
|
||||
; mov r9, rax
|
||||
byte 0x49
|
||||
byte 0x89
|
||||
byte 0xc1
|
||||
|
||||
; mov rax, [rbp-8]
|
||||
byte 0x48
|
||||
byte 0x8b
|
||||
byte 0x85
|
||||
byte 0xf8
|
||||
byte 0xff
|
||||
byte 0xff
|
||||
byte 0xff
|
||||
|
||||
; syscall
|
||||
byte 0x0f
|
||||
byte 0x05
|
||||
|
||||
return
|
Loading…
Add table
Add a link
Reference in a new issue