This commit is contained in:
julianb0 2019-08-21 19:10:55 +02:00
parent aa192abe6d
commit d221e17ec9
No known key found for this signature in database
GPG Key ID: 9C7ACF0C053FB8A1
3 changed files with 0 additions and 4279 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,995 +0,0 @@
# 1 "hello.k"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "hello.k"
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
start:
jmp main
# 1 "crt/crt.k" 1
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
;
; Limits
;
# 31 "crt/crt.k"
;
; Magic numbers
;
;
; CRT librairies
;
# 1 "./crt/sys.k" 1
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
;
; SHUTDOWN syscall
;
; End virtual machine
;
Sys.Shutdown := 0x00
;
; EXIT syscall
;
; Return to COMMAND.COM
;
Sys.Exit := 0x01
;
; EXEC syscall
;
; IN
; ax0 = new RIP to load
; ax1 = frame ID to switch to
;
; New frame ID must be higher than current
; frame ID, and cannot be below 5
;
; New CR1 is set so that new RIP corresponds to 1MB
;
Sys.ExecuteInFrame := 0x02
; FIND syscalls
;
; Find file on disk
;
; IN
; ax0 = address of name buffer
; ax1 = size of name buffer
;
; OUT
; rax = # of bytes written in name buffer
; rdx = size of file
;
;
Sys.FindFirst := 0x20
Sys.FindNext := 0x21
;
; OPEN syscall
;
; IN
; ax0 = name string
;
; OUT
; rax = handle of file, or <0 if couldn't open
;
Sys.OpenFile := 0x30
;
; CREATE syscall
;
; IN
; ax0 = name string
;
; OUT
; rax = 0 on success, or <0 if couldn't open
;
Sys.CreateFile := 0x31
;
; REMOVE syscall
;
; IN
; ax0 = name string
;
; OUT
; rax = 0 on success, or <0 if couldn't open
;
Sys.RemoveFile := 0x32
;
; CLOSE syscall
;
; IN
; ax0 = file handle
;
Sys.CloseFile := 0x35
;
; READ syscall
;
; IN
; ax0 = file handle
; ax1 = buffer address
; ax2 = buffer size
;
; OUT
; rax = number of bytes read, <0 on error
;
Sys.ReadFile := 0x38
; Halt mode
Sys.EnterHaltMode := 0x999
# 43 "crt/crt.k" 2
# 1 "./crt/str.k" 1
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
;
; int strnlen(char *, int)
;
strnlen:
mov rcx, ax1
scasb ax0, zero
sub rax, ax1, rcx
ret
;
; int strlen(char *)
;
strlen:
mov rcx, 0x7AFFFFFF
mov rdx, rcx
scasb ax0, zero
sub rax, rdx, rcx
ret
;
; void strcpy(char *, const char *)
;
strcpy:
.l:
mov rcx, b[ax1]
mov b[ax0], rcx
jrcxz .r
inc ax0
inc ax1
jmp .l
.r:
ret
;
; void strncpy(char *, const char *, int)
;
strncpy:
mov rcx, ax2
jrcxz .r
.l:
mov b[ax0], b[ax1]
inc ax0
inc ax1
loop .l
.r:
ret
;
; void strnzcpy(char *, const char *, int)
;
strnzcpy:
mov rcx, ax2
jrcxz .r
.l:
mov rax, b[ax1]
mov b[ax0], rax
jraxz .r
inc ax0
inc ax1
loop .l
.z:
nul b[ax0]
.r:
ret
;
; int strcmp(const char *str1, const char *str2)
;
; Returns:
; 0 if the contents of both strings are equal
; >0 if the first character that does not match has a greater value in str1 than in str2
; <0 if the first character that does not match has a lower value in str1 than in str2
;
strcmp:
nul rsi
.l:
movzx rax, b[ax0+rsi]
movzx rdx, b[ax1+rsi]
bne rax, rdx, .r
; both zero?
add rcx, rax, rdx
jrcxz .r
inc rsi
jmp .l
.r:
sub rax, rdx
ret
;
; int strncmp(const char *str1, const char *str2, int maxn)
;
strncmp:
mov rcx, ax2
jrcxz .r
.l:
movzx rax, b[ax0]
movzx rdx, b[ax1]
bne rax, rdx, .r
inc ax0
inc ax1
loop .l
.r:
sub rax, rdx
ret
;
; char *strchrnul(const char *str, int ch)
;
strchrnul:
mov rcx, 0x7AFFFFFF
scasb ax0, ax1
mov rax, ax0
ret
;
; char *strchr(const char *str, int ch)
;
strchr:
mov rcx, 0x7AFFFFFF
scasb ax0, ax1
bnz b[ax0], .r
nul rax
ret
.r:
mov rax, ax0
ret
;
; void strrev(char *buf, const char *str)
;
; buf and src must NOT overlap
;
strrev:
bzr b[ax1], .z
; save str's location
mov rsi, ax1
; go to str's end, just before
; the null terminator
mov rcx, 0x7AFFFFFF
scasb ax1, zero
dec ax1
.l:
; copy, going backward though str
; and forward through buf
mov b[ax0], b[ax1]
beq ax1, rsi, .r
inc ax0
dec ax1
jmp .l
.r:
nul b[ax0+1]
ret
.z:
nul b[ax0]
ret
;
; void strrev2(char *str)
;
; Inverses str
;
strrev2:
bzr b[ax0], .r
mov ax1, ax0
; go to str's end, just before
; the null terminator
mov rcx, 0x7AFFFFFF
scasb ax1, zero
dec ax1
; increase ax0 while decreasing ax1, performing exchanges
.l:
blteu ax1, ax0, .r
xchg b[ax0], b[ax1]
inc ax0
dec ax1
jmp .l
.r:
ret
# 44 "crt/crt.k" 2
# 1 "./crt/mem.k" 1
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
;
; void memcpy(void *, const void *, int)
;
memcpy:
mov rcx, ax2
jrcxz .r
.l:
sub rdx, ax2, rcx
mov b[ax0+rdx], b[ax1+rdx]
loop .l
.r:
ret
;
; void memzero(void *, int)
;
memzero:
mov rcx, ax1
jrcxz .r
.l:
nul b[ax0]
inc ax0
loop .l
.r:
ret
# 45 "crt/crt.k" 2
# 1 "./crt/time.k" 1
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
;
; struct TIME
; {
; byte sec; +0 (0-59)
; byte min; +1 (0-59)
; byte hour; +2 (0-23)
; byte mday; +3 (0-31)
; byte month; +4 (0-11)
; byte; +5 (pad)
; word year; +6 (0-65536)
; word yday; +8 (0-365)
; word; +10 (pad)
; dword; +12 (pad)
; } 16 bytes
;
;
; int DaysInYear(int year)
;
DaysInYear:
mov rax, 365
; divisible by 4?
rem rcx, ax0, 4
jrcxnz .end
; divisible by 100?
rem rcx, ax0, 100
jrcxnz .leap
; divisible by 400?
rem rcx, ax0, 400
jrcxnz .end
.leap:
inc rax, 1
.end:
ret
;
; TIME *GetTimeUTC(void)
;
GetTimeUTC:
ytime
mov rdi, .buf
; seconds
rem rsi, rax, 60
mov b[rdi], rsi
; minutes
div rsi, rax, 60
rem rsi, 60
mov b[rdi+1], rsi
; hours
div rsi, rax, 3600
rem rsi, 24
mov b[rdi+2], rsi
; month days
div rsi, rax, 3600*24
mov b[rdi+3], rsi
; month
mov b[rdi+4], rbx
; years
mov w[rdi+6], rcx
;
; ydays (TODO)
;
mov rax, .buf
ret
.buf = [24]
# 46 "crt/crt.k" 2
# 1 "./crt/fmt/ltostr.k" 1
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
;
; void itoa(char *buf, int num, int base)
;
itoa:
mov ax3, 1
jmp ltostr
;
; void utoa(char *buf, int num, int base)
;
utoa:
nul ax3
jmp ltostr
;
; void ltostr(char *buf, int num, int base, bool signed)
;
ltostr:
mov rax, ax0
nul rcx
; make sure base is in [2, 32]
bltu ax2, 2, .bad
bltu 36, ax2, .bad
; deal with zero
bzr ax1, .is_zero
; deal with base 10 signedness
bzr ax3, .conv
bne ax2, 10, .conv ; base 10
shr rcx, ax1, 63 ; extract ax1 sign
jrcxz .conv
neg ax1 ; NEG if negative
; main loop
.conv:
bzr ax1, .fini
rem rdx, ax1, ax2 ; ax1 % base
blt 9, rdx, .nondec ; rdx > 9 ?
inc rdx, '0'
jmp .next
.nondec:
inc rdx, 55 ; 'A' - 10
.next:
mov b[ax0], rdx
inc ax0
div ax1, ax2
jmp .conv
; add minus flag, null-terminate and reverse
.fini:
jrcxz .cxz
mov b[ax0], '-'
inc ax0
.cxz:
nul b[ax0]
call strrev2, rax
ret
;
; exceptional cases
;
.bad:
mov b[ax0], 0
ret
.is_zero:
mov b[ax0], 48 ; '0'
mov b[ax0+1], 0
ret
# 48 "crt/crt.k" 2
# 1 "./crt/fmt/strtol.k" 1
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
;
; int strtol(const char *str, int base)
;
; rax = integer extracted from str
; rdx = pointer to first invalid byte
;
strtol:
mov ax2, 1
jmp strtoq
;
; int strtoul(const char *str, int base)
;
; rax = integer extracted from str
; rdx = pointer to first invalid byte
;
strtoul:
nul ax2
jmp strtoq
;
; int strtoq(const char *str, int base, bool signed)
;
; guesses base when 'base'=0
;
strtoq:
nul rax, rsi
mov rdx, ax0
; make sure base is in [2, 32]
beq ax1, 1, .bad
bltu 36, ax1, .bad
; empty string?
bzr b[rdx], .done
.skip_spc:
bne b[rdx], ' ', .no_spc
inc rdx
jmp .skip_spc
.no_spc:
; skip +
bne b[rdx], '+', .no_plus
inc rdx
.no_plus:
; unsigned?
bzr ax2, .unsigned
; parse '-'
bne b[rdx], '-', .unsigned
inc rdx
mov rsi, 1
.unsigned:
; base 0
bzr ax1, .base_0
; base prefix?
bne b[rdx], '0', .main_loop
inc rdx
movzx rcx, b[rdx]
; "0x"/"0b" prefix
jrcxz .done ; "0"
beq rcx, 'x', .parsed_0x
beq rcx, 'b', .parsed_0b
; may be octal, but we don't care
; we accept "0110101010" (despite base=2) for instance
jmp .main_loop
.parsed_0x:
; are we in base 16?
; if not, leave rax = 0 and *rdx = 'x'
bne ax1, 16, .done
; else
inc rdx, 1
jmp .main_loop
.parsed_0b:
; are we in base 2?
; if not, leave rax = 0 and *rdx = 'b'
bne ax1, 2, .done
; else
inc rdx
jmp .main_loop
.base_0:
; guess base
beq b[rdx], '0', .b0_not10
; must be base 10
mov ax1, 10
jmp .main_loop
.b0_not10:
inc rdx
bne b[rdx], 'x', .b0_not16
inc rdx
mov ax1, 16
jmp .main_loop
.b0_not16:
bne b[rdx], 'b', .b0_not2
inc rdx
mov ax1, 2
jmp .main_loop
.b0_not2:
; take octal by default
mov ax1, 8
.main_loop:
movzx rcx, b[rdx]
inc rdx
; between 0 and 9?
bltu rcx, '0', .done
bltu '9', rcx, .not_digit10
; yes
sub rcx, '0'
jmp .next
.not_digit10:
bltu rcx, 'A', .done
bltu 'Z', rcx, .not_digitAZ
sub rcx, 55 ; 'A' - 10
jmp .next
.not_digitAZ:
bltu rcx, 'a', .done
bltu 'z', rcx, .done
sub rcx, 87 ; 'a' - 10
jmp .next
.next:
; too large for base?
blteu ax1, rcx, .done
mul rax, ax1
inc rax, rcx
jmp .main_loop
.done:
; negative?
bzr rsi, .r
; yes
neg rax
.r:
ret
.bad:
ret
# 49 "crt/crt.k" 2
# 1 "./crt/fmt/doprnt.k" 1
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
;
; typedef int (*PUTC)(int ch)
; int doprnt(PUTC putc, int n, const char *fmt, va_list ap)
;
doprnt:
push rbp
mov rbp, rsp
push r12, r13, r14
push r15, r16, r17
mov r12, ax2 ; fmt
mov r14, ax3 ; va_list
mov r15, ax1 ; n
mov r17, ax0 ; putc
nul r16 ; return value
.main_loop:
; find '%' or null-terminator
mov rcx, 0x7AFFFFFF
mov r13, r12
scasb r13, '%'
; everything below r13 is a regular character; print it
.print_regular:
beq r12, r13, .check_modf
call .doput, b[r12]
inc r12, 1
jmp .print_regular
.check_modf:
; did we find a '%' ?
; if not, then we found fmt's null-terminator; we're done
bne b[r12], '%', .epilogue
; we did find a modifier / '%'
mov rax, b[r12+1]
inc r12, 2
beq rax, 's', .modf_s
beq rax, 'c', .modf_c
beq rax, 'p', .modf_p
beq rax, 'x', .modf_x
beq rax, 'd', .modf_d
beq rax, 'o', .modf_o
beq rax, 'b', .modf_b
beq rax, '%', .modf_percent
; unrecognized
jmp .bad_modifier
.modf_s:
; get string address
mov r13, q[r14]
inc r14, 8
bzr r13, .nullstring
.print_string:
movzx ax0, b[r13]
bzr ax0, .main_loop
inc r13
call .doput
jmp .print_string
.modf_c:
call .doput, q[r14]
inc r14, 8
jmp .main_loop
.modf_p:
call .doput, '0'
call .doput, 'x'
; Fallthrough
.modf_x:
mov ax2, 16
jmp .print_number
.modf_d:
mov ax2, 10
jmp .print_number
.modf_o:
mov ax2, 8
jmp .print_number
.modf_b:
mov ax2, 2
jmp .print_number
.print_number:
; allocate itoa conversion buffer
sub rsp, 80
mov r13, rsp
; assume modifier already set up ax2
call itoa, rsp, q[r14]
inc r14, 8
.print_itoa_buf:
movzx ax0, b[r13]
bzr ax0, .pib_end_loop
inc r13
call .doput
jmp .print_itoa_buf
.pib_end_loop:
inc rsp, 80
jmp .main_loop
.modf_percent:
call .doput, '%'
jmp .main_loop
.bad_modifier:
; print "%?" to clearly indicate that something is wrong
call .doput, '%'
call .doput, '?'
jmp .main_loop
.nullstring:
; %s was passed a NULL
call .doput, '('
call .doput, 'n'
call .doput, 'u'
call .doput, 'l'
call .doput, 'l'
call .doput, ')'
jmp .main_loop
.epilogue:
mov rax, r16
pop r17, r16
pop r15, r14
pop r13, r12
leave
ret
;
; prints ax0
;
.doput:
; update print count
inc r16
; if n==0, don't print
; we follow the C convention that sprintf()-like functions
; should return the number of characters that would have
; been printed/written if 'n' were big enough
bzr r15, .r
; decrement n and print
dec r15
call r17
; did putc fail?
jraxz .r
; yes, so artificially set n=0
nul r15
.r:
ret
# 50 "crt/crt.k" 2
# 1 "./crt/fmt/printf.k" 1
; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
;
; int putc(int ch)
;
putc:
prn ax0
nul rax
ret
;
; int printf(const char *fmt, ...)
;
printf:
mov ax2, ax0
mov ax0, putc
mov ax1, 0x7AFFFFFF
add ax3, rsp, 8
jmp doprnt
;
; int nprintf(const char *fmt, int n, ...)
;
nprintf:
mov ax2, ax0
mov ax0, putc
add ax3, rsp, 8
jmp doprnt
;
; Print a string
; Guaranteed to only affect rcx and ax0
;
print:
.l:
movzx rax, b[ax0]
jraxz .r
prn rax
inc ax0
jmp .l
.r:
ret
;
; Print exactly ax1 characters
;
nprint:
mov rcx, ax1
jrcxz .r
.l:
prn b[ax0]
inc ax0
loop .l
.r:
ret
# 51 "crt/crt.k" 2
exit:
mov rax, Sys.Exit
trap 0
abort:
crash
# 8 "hello.k" 2
main:
mov rsp, 0x104000
nul rbp
call print, .hellow
jmp exit
.hellow = "Hello World!\n"