kvisc/vm/ob/command.k

1657 lines
26 KiB
Plaintext
Raw Normal View History

2019-08-21 18:47:03 +02:00
# 1 "command.k"
# 1 "<built-in>"
# 1 "<command-line>"
# 31 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 32 "<command-line>" 2
# 1 "command.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.
cmdstart:
jmp start
# 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:
2019-09-08 19:04:07 +02:00
mov ecx, ax1
2019-08-21 18:47:03 +02:00
scasb ax0, zero
2019-09-08 19:04:07 +02:00
sub eax, ax1, ecx
2019-08-21 18:47:03 +02:00
ret
;
; int strlen(char *)
;
strlen:
2019-09-08 19:04:07 +02:00
mov ecx, 0x7AFFFFFF
mov edx, ecx
2019-08-21 18:47:03 +02:00
scasb ax0, zero
2019-09-08 19:04:07 +02:00
sub eax, edx, ecx
2019-08-21 18:47:03 +02:00
ret
;
; void strcpy(char *, const char *)
;
strcpy:
.l:
2019-09-08 19:04:07 +02:00
mov ecx, b[ax1]
mov b[ax0], ecx
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
jecxz .r
2019-08-21 18:47:03 +02:00
inc ax0
inc ax1
jmp .l
.r:
ret
;
; void strncpy(char *, const char *, int)
;
strncpy:
2019-09-08 19:04:07 +02:00
mov ecx, ax2
jecxz .r
2019-08-21 18:47:03 +02:00
.l:
mov b[ax0], b[ax1]
inc ax0
inc ax1
loop .l
.r:
ret
;
; void strnzcpy(char *, const char *, int)
;
strnzcpy:
2019-09-08 19:04:07 +02:00
mov ecx, ax2
jecxz .r
2019-08-21 18:47:03 +02:00
.l:
2019-09-08 19:04:07 +02:00
mov eax, b[ax1]
mov b[ax0], eax
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
jeaxz .r
2019-08-21 18:47:03 +02:00
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:
2019-09-08 19:04:07 +02:00
nul esi
2019-08-21 18:47:03 +02:00
.l:
2019-09-08 19:04:07 +02:00
movzx eax, b[ax0+esi]
movzx edx, b[ax1+esi]
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
bne eax, edx, .r
2019-08-21 18:47:03 +02:00
; both zero?
2019-09-08 19:04:07 +02:00
add ecx, eax, edx
jecxz .r
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
inc esi
2019-08-21 18:47:03 +02:00
jmp .l
.r:
2019-09-08 19:04:07 +02:00
sub eax, edx
2019-08-21 18:47:03 +02:00
ret
;
; int strncmp(const char *str1, const char *str2, int maxn)
;
strncmp:
2019-09-08 19:04:07 +02:00
mov ecx, ax2
jecxz .r
2019-08-21 18:47:03 +02:00
.l:
2019-09-08 19:04:07 +02:00
movzx eax, b[ax0]
movzx edx, b[ax1]
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
bne eax, edx, .r
2019-08-21 18:47:03 +02:00
inc ax0
inc ax1
loop .l
.r:
2019-09-08 19:04:07 +02:00
sub eax, edx
2019-08-21 18:47:03 +02:00
ret
;
; char *strchrnul(const char *str, int ch)
;
strchrnul:
2019-09-08 19:04:07 +02:00
mov ecx, 0x7AFFFFFF
2019-08-21 18:47:03 +02:00
scasb ax0, ax1
2019-09-08 19:04:07 +02:00
mov eax, ax0
2019-08-21 18:47:03 +02:00
ret
;
; char *strchr(const char *str, int ch)
;
strchr:
2019-09-08 19:04:07 +02:00
mov ecx, 0x7AFFFFFF
2019-08-21 18:47:03 +02:00
scasb ax0, ax1
bnz b[ax0], .r
2019-09-08 19:04:07 +02:00
nul eax
2019-08-21 18:47:03 +02:00
ret
.r:
2019-09-08 19:04:07 +02:00
mov eax, ax0
2019-08-21 18:47:03 +02:00
ret
;
; void strrev(char *buf, const char *str)
;
; buf and src must NOT overlap
;
strrev:
bzr b[ax1], .z
; save str's location
2019-09-08 19:04:07 +02:00
mov esi, ax1
2019-08-21 18:47:03 +02:00
; go to str's end, just before
; the null terminator
2019-09-08 19:04:07 +02:00
mov ecx, 0x7AFFFFFF
2019-08-21 18:47:03 +02:00
scasb ax1, zero
dec ax1
.l:
; copy, going backward though str
; and forward through buf
mov b[ax0], b[ax1]
2019-09-08 19:04:07 +02:00
beq ax1, esi, .r
2019-08-21 18:47:03 +02:00
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
2019-09-08 19:04:07 +02:00
mov ecx, 0x7AFFFFFF
2019-08-21 18:47:03 +02:00
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:
2019-09-08 19:04:07 +02:00
mov ecx, ax2
jecxz .r
2019-08-21 18:47:03 +02:00
.l:
2019-09-08 19:04:07 +02:00
sub edx, ax2, ecx
mov b[ax0+edx], b[ax1+edx]
2019-08-21 18:47:03 +02:00
loop .l
.r:
ret
;
; void memzero(void *, int)
;
memzero:
2019-09-08 19:04:07 +02:00
mov ecx, ax1
jecxz .r
2019-08-21 18:47:03 +02:00
.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:
2019-09-08 19:04:07 +02:00
mov eax, 365
2019-08-21 18:47:03 +02:00
; divisible by 4?
2019-09-08 19:04:07 +02:00
rem ecx, ax0, 4
jecxnz .end
2019-08-21 18:47:03 +02:00
; divisible by 100?
2019-09-08 19:04:07 +02:00
rem ecx, ax0, 100
jecxnz .leap
2019-08-21 18:47:03 +02:00
; divisible by 400?
2019-09-08 19:04:07 +02:00
rem ecx, ax0, 400
jecxnz .end
2019-08-21 18:47:03 +02:00
.leap:
2019-09-08 19:04:07 +02:00
inc eax
2019-08-21 18:47:03 +02:00
.end:
ret
;
; TIME *GetTimeUTC(void)
;
GetTimeUTC:
ytime
2019-09-08 19:04:07 +02:00
mov edi, .buf
2019-08-21 18:47:03 +02:00
; seconds
2019-09-08 19:04:07 +02:00
rem esi, eax, 60
mov b[edi], esi
2019-08-21 18:47:03 +02:00
; minutes
2019-09-08 19:04:07 +02:00
div esi, eax, 60
rem esi, 60
mov b[edi+1], esi
2019-08-21 18:47:03 +02:00
; hours
2019-09-08 19:04:07 +02:00
div esi, eax, 3600
rem esi, 24
mov b[edi+2], esi
2019-08-21 18:47:03 +02:00
; month days
2019-09-08 19:04:07 +02:00
div esi, eax, 3600*24
mov b[edi+3], esi
2019-08-21 18:47:03 +02:00
; month
2019-09-08 19:04:07 +02:00
mov b[edi+4], rbx
2019-08-21 18:47:03 +02:00
; years
2019-09-08 19:04:07 +02:00
mov w[edi+6], ecx
2019-08-21 18:47:03 +02:00
;
; ydays (TODO)
;
2019-09-08 19:04:07 +02:00
mov eax, .buf
2019-08-21 18:47:03 +02:00
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:
2019-09-08 19:04:07 +02:00
mov eax, ax0
nul ecx
2019-08-21 18:47:03 +02:00
; 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
2019-09-08 19:04:07 +02:00
shr ecx, ax1, 63 ; extract ax1 sign
jecxz .conv
2019-08-21 18:47:03 +02:00
neg ax1 ; NEG if negative
; main loop
.conv:
bzr ax1, .fini
2019-09-08 19:04:07 +02:00
rem edx, ax1, ax2 ; ax1 % base
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
blt 9, edx, .nondec ; edx > 9 ?
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
add edx, '0'
2019-08-21 18:47:03 +02:00
jmp .next
.nondec:
2019-09-08 19:04:07 +02:00
add edx, 55 ; 'A' - 10
2019-08-21 18:47:03 +02:00
.next:
2019-09-08 19:04:07 +02:00
mov b[ax0], edx
2019-08-21 18:47:03 +02:00
inc ax0
div ax1, ax2
jmp .conv
; add minus flag, null-terminate and reverse
.fini:
2019-09-08 19:04:07 +02:00
jecxz .cxz
2019-08-21 18:47:03 +02:00
mov b[ax0], '-'
inc ax0
.cxz:
nul b[ax0]
2019-09-08 19:04:07 +02:00
call strrev2, eax
2019-08-21 18:47:03 +02:00
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)
;
2019-09-08 19:04:07 +02:00
; eax = integer extracted from str
; edx = pointer to first invalid byte
2019-08-21 18:47:03 +02:00
;
strtol:
mov ax2, 1
jmp strtoq
;
; int strtoul(const char *str, int base)
;
2019-09-08 19:04:07 +02:00
; eax = integer extracted from str
; edx = pointer to first invalid byte
2019-08-21 18:47:03 +02:00
;
strtoul:
nul ax2
jmp strtoq
;
; int strtoq(const char *str, int base, bool signed)
;
; guesses base when 'base'=0
;
strtoq:
2019-09-08 19:04:07 +02:00
nul eax, esi
mov edx, ax0
2019-08-21 18:47:03 +02:00
; make sure base is in [2, 32]
beq ax1, 1, .bad
bltu 36, ax1, .bad
; empty string?
2019-09-08 19:04:07 +02:00
bzr b[edx], .done
2019-08-21 18:47:03 +02:00
.skip_spc:
2019-09-08 19:04:07 +02:00
bne b[edx], ' ', .no_spc
inc edx
2019-08-21 18:47:03 +02:00
jmp .skip_spc
.no_spc:
; skip +
2019-09-08 19:04:07 +02:00
bne b[edx], '+', .no_plus
inc edx
2019-08-21 18:47:03 +02:00
.no_plus:
; unsigned?
bzr ax2, .unsigned
; parse '-'
2019-09-08 19:04:07 +02:00
bne b[edx], '-', .unsigned
inc edx
mov esi, 1
2019-08-21 18:47:03 +02:00
.unsigned:
; base 0
bzr ax1, .base_0
; base prefix?
2019-09-08 19:04:07 +02:00
bne b[edx], '0', .main_loop
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
inc edx
movzx ecx, b[edx]
2019-08-21 18:47:03 +02:00
; "0x"/"0b" prefix
2019-09-08 19:04:07 +02:00
jecxz .done ; "0"
beq ecx, 'x', .parsed_0x
beq ecx, 'b', .parsed_0b
2019-08-21 18:47:03 +02:00
; 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?
2019-09-08 19:04:07 +02:00
; if not, leave eax = 0 and *edx = 'x'
2019-08-21 18:47:03 +02:00
bne ax1, 16, .done
; else
2019-09-08 19:04:07 +02:00
inc edx
2019-08-21 18:47:03 +02:00
jmp .main_loop
.parsed_0b:
; are we in base 2?
2019-09-08 19:04:07 +02:00
; if not, leave eax = 0 and *edx = 'b'
2019-08-21 18:47:03 +02:00
bne ax1, 2, .done
; else
2019-09-08 19:04:07 +02:00
inc edx
2019-08-21 18:47:03 +02:00
jmp .main_loop
.base_0:
; guess base
2019-09-08 19:04:07 +02:00
beq b[edx], '0', .b0_not10
2019-08-21 18:47:03 +02:00
; must be base 10
mov ax1, 10
jmp .main_loop
.b0_not10:
2019-09-08 19:04:07 +02:00
inc edx
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
bne b[edx], 'x', .b0_not16
inc edx
2019-08-21 18:47:03 +02:00
mov ax1, 16
jmp .main_loop
.b0_not16:
2019-09-08 19:04:07 +02:00
bne b[edx], 'b', .b0_not2
inc edx
2019-08-21 18:47:03 +02:00
mov ax1, 2
jmp .main_loop
.b0_not2:
; take octal by default
mov ax1, 8
.main_loop:
2019-09-08 19:04:07 +02:00
movzx ecx, b[edx]
inc edx
2019-08-21 18:47:03 +02:00
; between 0 and 9?
2019-09-08 19:04:07 +02:00
bltu ecx, '0', .done
bltu '9', ecx, .not_digit10
2019-08-21 18:47:03 +02:00
; yes
2019-09-08 19:04:07 +02:00
sub ecx, '0'
2019-08-21 18:47:03 +02:00
jmp .next
.not_digit10:
2019-09-08 19:04:07 +02:00
bltu ecx, 'A', .done
bltu 'Z', ecx, .not_digitAZ
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
sub ecx, 55 ; 'A' - 10
2019-08-21 18:47:03 +02:00
jmp .next
.not_digitAZ:
2019-09-08 19:04:07 +02:00
bltu ecx, 'a', .done
bltu 'z', ecx, .done
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
sub ecx, 87 ; 'a' - 10
2019-08-21 18:47:03 +02:00
jmp .next
.next:
; too large for base?
2019-09-08 19:04:07 +02:00
blteu ax1, ecx, .done
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
mul eax, ax1
add eax, ecx
2019-08-21 18:47:03 +02:00
jmp .main_loop
.done:
; negative?
2019-09-08 19:04:07 +02:00
bzr esi, .r
2019-08-21 18:47:03 +02:00
; yes
2019-09-08 19:04:07 +02:00
neg eax
2019-08-21 18:47:03 +02:00
.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:
2019-09-08 19:04:07 +02:00
push ebp
mov ebp, esp
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
push nx0, nx1, nx2
push nx3, nx4, nx5
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
mov nx0, ax2 ; fmt
mov nx2, ax3 ; va_list
mov nx3, ax1 ; n
mov nx5, ax0 ; putc
nul nx4 ; return value
2019-08-21 18:47:03 +02:00
.main_loop:
; find '%' or null-terminator
2019-09-08 19:04:07 +02:00
mov ecx, 0x7AFFFFFF
mov nx1, nx0
scasb nx1, '%'
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
; everything below nx1 is a regular character; print it
2019-08-21 18:47:03 +02:00
.print_regular:
2019-09-08 19:04:07 +02:00
beq nx0, nx1, .check_modf
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
call .doput, b[nx0]
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
inc nx0
2019-08-21 18:47:03 +02:00
jmp .print_regular
.check_modf:
; did we find a '%' ?
; if not, then we found fmt's null-terminator; we're done
2019-09-08 19:04:07 +02:00
bne b[nx0], '%', .epilogue
2019-08-21 18:47:03 +02:00
; we did find a modifier / '%'
2019-09-08 19:04:07 +02:00
mov eax, b[nx0+1]
add nx0, 2
beq eax, 's', .modf_s
beq eax, 'c', .modf_c
beq eax, 'p', .modf_p
beq eax, 'x', .modf_x
beq eax, 'd', .modf_d
beq eax, 'o', .modf_o
beq eax, 'b', .modf_b
beq eax, '%', .modf_percent
2019-08-21 18:47:03 +02:00
; unrecognized
jmp .bad_modifier
.modf_s:
; get string address
2019-09-08 19:04:07 +02:00
mov nx1, q[nx2]
add nx2, 8
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
bzr nx1, .nullstring
2019-08-21 18:47:03 +02:00
.print_string:
2019-09-08 19:04:07 +02:00
movzx ax0, b[nx1]
2019-08-21 18:47:03 +02:00
bzr ax0, .main_loop
2019-09-08 19:04:07 +02:00
inc nx1
2019-08-21 18:47:03 +02:00
call .doput
jmp .print_string
.modf_c:
2019-09-08 19:04:07 +02:00
call .doput, q[nx2]
add nx2, 8
2019-08-21 18:47:03 +02:00
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
2019-09-08 19:04:07 +02:00
sub esp, 80
mov nx1, esp
2019-08-21 18:47:03 +02:00
; assume modifier already set up ax2
2019-09-08 19:04:07 +02:00
call itoa, esp, q[nx2]
add nx2, 8
2019-08-21 18:47:03 +02:00
.print_itoa_buf:
2019-09-08 19:04:07 +02:00
movzx ax0, b[nx1]
2019-08-21 18:47:03 +02:00
bzr ax0, .pib_end_loop
2019-09-08 19:04:07 +02:00
inc nx1
2019-08-21 18:47:03 +02:00
call .doput
jmp .print_itoa_buf
.pib_end_loop:
2019-09-08 19:04:07 +02:00
add esp, 80
2019-08-21 18:47:03 +02:00
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:
2019-09-08 19:04:07 +02:00
mov eax, nx4
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
pop nx5, nx4
pop nx3, nx2
pop nx1, nx0
2019-08-21 18:47:03 +02:00
leave
ret
;
; prints ax0
;
.doput:
; update print count
2019-09-08 19:04:07 +02:00
inc nx4
2019-08-21 18:47:03 +02:00
; 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
2019-09-08 19:04:07 +02:00
bzr nx3, .r
2019-08-21 18:47:03 +02:00
; decrement n and print
2019-09-08 19:04:07 +02:00
dec nx3
call nx5
2019-08-21 18:47:03 +02:00
; did putc fail?
2019-09-08 19:04:07 +02:00
jeaxz .r
2019-08-21 18:47:03 +02:00
; yes, so artificially set n=0
2019-09-08 19:04:07 +02:00
nul nx3
2019-08-21 18:47:03 +02:00
.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
2019-09-08 19:04:07 +02:00
nul eax
2019-08-21 18:47:03 +02:00
ret
;
; int printf(const char *fmt, ...)
;
printf:
mov ax2, ax0
mov ax0, putc
mov ax1, 0x7AFFFFFF
2019-09-08 19:04:07 +02:00
add ax3, esp, 8
2019-08-21 18:47:03 +02:00
jmp doprnt
;
; int nprintf(const char *fmt, int n, ...)
;
nprintf:
mov ax2, ax0
mov ax0, putc
2019-09-08 19:04:07 +02:00
add ax3, esp, 8
2019-08-21 18:47:03 +02:00
jmp doprnt
;
; Print a string
2019-09-08 19:04:07 +02:00
; Guaranteed to only affect ecx and ax0
2019-08-21 18:47:03 +02:00
;
print:
.l:
2019-09-08 19:04:07 +02:00
movzx eax, b[ax0]
jeaxz .r
2019-08-21 18:47:03 +02:00
2019-09-08 19:04:07 +02:00
prn eax
2019-08-21 18:47:03 +02:00
inc ax0
jmp .l
.r:
ret
;
; Print exactly ax1 characters
;
nprint:
2019-09-08 19:04:07 +02:00
mov ecx, ax1
jecxz .r
2019-08-21 18:47:03 +02:00
.l:
prn b[ax0]
inc ax0
loop .l
2019-09-03 09:06:58 +02:00
2019-08-21 18:47:03 +02:00
.r:
ret
# 51 "crt/crt.k" 2
exit:
2019-09-08 19:04:07 +02:00
mov eax, Sys.Exit
2019-08-21 18:47:03 +02:00
trap 0
abort:
crash
# 8 "command.k" 2
; COMMAND.COM guarantees that programs
; are always loaded on a 16KB boundary
; This is guaranteed to be the case
2019-09-07 16:45:03 +02:00
; in all future veesions as well
2019-08-21 18:47:03 +02:00
start:
2019-09-07 16:45:03 +02:00
mov esp, 0x104000
mov ebp, zero
2019-08-21 18:47:03 +02:00
call main
2019-09-07 16:45:03 +02:00
mov eax, Sys.EnterHaltMode
2019-08-21 18:47:03 +02:00
trap 0
crash
2019-09-07 16:45:03 +02:00
cmd.veesionstr = "COMMAND.COM, veesion 0.1 (KVISC)\nCopyright (C) 2019, The OS/K Team\nMIT license (permissive), see LICENCE file in source tree"
2019-08-21 18:47:03 +02:00
argbuf.size := 256
argbuf = [argbuf.size]
argv0 = [argbuf.size]
argv1pos = 0
stdin_echoing = 1
prompt = [32]
main:
2019-09-07 16:45:03 +02:00
mov esi, prompt
mov b[esi+0], 'C'
mov b[esi+1], ':'
mov b[esi+2], '\'
mov b[esi+3], '>'
mov b[esi+4], ' '
2019-08-21 18:47:03 +02:00
.print_prompt:
call print, prompt
; empty stuff
call memzero, argbuf, argbuf.size
call memzero, argv0, argbuf.size
nul q[argv1pos]
; call nprint, argv0, argbuf.size
; iterator through argbuf
2019-09-07 16:45:03 +02:00
nul ecx
2019-08-21 18:47:03 +02:00
.input_loop:
pause
pause
pause
; Fill .buf with user input
2019-09-07 16:45:03 +02:00
scan eax
2019-09-08 19:04:07 +02:00
jeaxz .input_loop
2019-08-21 18:47:03 +02:00
; ESC key pressed?
2019-09-07 16:45:03 +02:00
beq eax, 0x1B, .handle_EXIT
2019-08-21 18:47:03 +02:00
; backspace character?
2019-09-07 16:45:03 +02:00
bne eax, 8, .handle_input
2019-08-21 18:47:03 +02:00
; anything to delete?
2019-09-08 19:04:07 +02:00
jecxz .input_loop ; no
2019-08-21 18:47:03 +02:00
; yes, delete it
2019-09-07 16:45:03 +02:00
dec ecx
add edx, ecx, argbuf
nul b[edx]
2019-08-21 18:47:03 +02:00
; update screen
bzr b[stdin_echoing], .input_loop
prn 8
jmp .input_loop
.handle_input:
bzr b[stdin_echoing], .se.z
2019-09-07 16:45:03 +02:00
prn eax
2019-08-21 18:47:03 +02:00
.se.z:
2019-09-07 16:45:03 +02:00
beq eax, 10, .extract_argv0
2019-08-21 18:47:03 +02:00
; when max line length is reached,
; force a newline
2019-09-07 16:45:03 +02:00
beq ecx, argbuf.size, .extract_argv0
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
; add character to buffer and increase iterator (ecx)
add edx, ecx, argbuf
mov b[edx], eax
inc ecx
2019-08-21 18:47:03 +02:00
; another one
jmp .input_loop
.extract_argv0:
; did we read anything at all?
; if not, just go back to waiting input
2019-09-08 19:04:07 +02:00
jecxz .print_prompt
2019-08-21 18:47:03 +02:00
; find first whitespace or null-terminator
2019-09-07 16:45:03 +02:00
mov ecx, argbuf.size
mov edx, argbuf
scasb edx, ' '
2019-08-21 18:47:03 +02:00
; argv1 exists? if so, save its position
2019-09-07 16:45:03 +02:00
mov esi, edx
2019-08-21 18:47:03 +02:00
.next_space:
2019-09-07 16:45:03 +02:00
mov ecx, b[esi]
2019-09-08 19:04:07 +02:00
jecxz .do_extract
2019-08-21 18:47:03 +02:00
; skip spaces
2019-09-07 16:45:03 +02:00
bne ecx, ' ', .not_a_space
inc esi
2019-08-21 18:47:03 +02:00
jmp .next_space
.not_a_space:
; if we're here, we found a
; non-zero non-space character
2019-09-07 16:45:03 +02:00
mov q[argv1pos], esi
2019-08-21 18:47:03 +02:00
; fallthrough
.do_extract:
; how much do we copy?
2019-09-07 16:45:03 +02:00
sub ecx, edx, argbuf
2019-09-08 19:04:07 +02:00
jecxz .detect_builtin
2019-09-07 16:45:03 +02:00
dec ecx
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
mov edi, argbuf
mov esi, argv0
2019-08-21 18:47:03 +02:00
.copy_loop:
2019-09-07 16:45:03 +02:00
mov b[esi], b[edi]
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
inc edi
inc esi
2019-08-21 18:47:03 +02:00
loop .copy_loop
.detect_builtin:
.builtin_cls = "cls"
call strcmp, argv0, .builtin_cls
2019-09-08 19:04:07 +02:00
jeaxz .handle_CLS
2019-08-21 18:47:03 +02:00
.builtin_crash = "crash"
call strcmp, argv0, .builtin_crash
2019-09-08 19:04:07 +02:00
jeaxz .handle_CRASH
2019-08-21 18:47:03 +02:00
.builtin_date = "date"
call strcmp, argv0, .builtin_date
2019-09-08 19:04:07 +02:00
jeaxz .handle_DATE
2019-08-21 18:47:03 +02:00
.builtin_dir = "dir"
call strcmp, argv0, .builtin_dir
2019-09-08 19:04:07 +02:00
jeaxz .handle_DIR
2019-08-21 18:47:03 +02:00
.builtin_dump = "dump"
call strcmp, argv0, .builtin_dump
2019-09-08 19:04:07 +02:00
jeaxz .handle_DUMP
2019-08-21 18:47:03 +02:00
.builtin_echo = "echo"
call strcmp, argv0, .builtin_echo
2019-09-08 19:04:07 +02:00
jeaxz .handle_ECHO
2019-08-21 18:47:03 +02:00
.builtin_erase = "erase"
call strcmp, argv0, .builtin_erase
2019-09-08 19:04:07 +02:00
jeaxz .handle_ERASE
2019-08-21 18:47:03 +02:00
.builtin_exit = "exit"
call strcmp, argv0, .builtin_exit
2019-09-08 19:04:07 +02:00
jeaxz .handle_EXIT
2019-08-21 18:47:03 +02:00
.builtin_help = "help"
call strcmp, argv0, .builtin_help
2019-09-08 19:04:07 +02:00
jeaxz .handle_HELP
2019-08-21 18:47:03 +02:00
.builtin_halt = "halt"
call strcmp, argv0, .builtin_halt
2019-09-08 19:04:07 +02:00
jeaxz .handle_HALT
2019-08-21 18:47:03 +02:00
.builtin_make = "make"
call strcmp, argv0, .builtin_make
2019-09-08 19:04:07 +02:00
jeaxz .handle_MAKE
2019-08-21 18:47:03 +02:00
.builtin_print = "print"
call strcmp, argv0, .builtin_print
2019-09-08 19:04:07 +02:00
jeaxz .handle_PRINT
2019-08-21 18:47:03 +02:00
.builtin_prompt = "prompt"
call strcmp, argv0, .builtin_prompt
2019-09-08 19:04:07 +02:00
jeaxz .handle_PROMPT
2019-08-21 18:47:03 +02:00
.builtin_remove = "remove"
call strcmp, argv0, .builtin_remove
2019-09-08 19:04:07 +02:00
jeaxz .handle_REMOVE
2019-08-21 18:47:03 +02:00
.builtin_time = "time"
call strcmp, argv0, .builtin_time
2019-09-08 19:04:07 +02:00
jeaxz .handle_TIME
2019-08-21 18:47:03 +02:00
.builtin_vers = "vers"
call strcmp, argv0, .builtin_vers
2019-09-08 19:04:07 +02:00
jeaxz .handle_VERS
2019-08-21 18:47:03 +02:00
jmp .try_exec
;
; call builtins
;
# 1 "usr/cmd-dir.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.
2019-08-21 19:10:26 +02:00
2019-08-21 18:47:03 +02:00
.handle_DIR:
2019-09-07 16:45:03 +02:00
push ebp
mov ebp, esp
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
push nx0, nx1
push nx2, nx3
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
nul nx0 ; no. of files found
nul nx1 ; no. of directories found
nul nx2 ; total amount of bytes found
2019-08-21 18:47:03 +02:00
call print, .dirmsg
2019-09-03 09:06:58 +02:00
.dir_first:
2019-09-07 16:45:03 +02:00
mov eax, Sys.FindFirst
2019-09-03 09:06:58 +02:00
mov ax0, .dir_buf
2019-08-21 18:47:03 +02:00
mov ax1, 0x80
trap 0
2019-09-03 09:06:58 +02:00
jmp .dir_list
2019-08-21 18:47:03 +02:00
2019-09-03 09:06:58 +02:00
.dir_next:
2019-09-07 16:45:03 +02:00
mov eax, Sys.FindNext
2019-09-03 09:06:58 +02:00
mov ax0, .dir_buf
2019-08-21 18:47:03 +02:00
mov ax1, 0x80
trap 0
2019-09-03 09:06:58 +02:00
.dir_list:
2019-09-08 19:04:07 +02:00
jeaxz .dir_end
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
mov nx3, ecx ; file size
add nx2, ecx
2019-08-21 18:47:03 +02:00
; directory?
2019-09-07 16:45:03 +02:00
bnz edx, .dir_is_dir
2019-08-21 18:47:03 +02:00
; found a file
2019-09-07 16:45:03 +02:00
inc nx0
2019-08-21 18:47:03 +02:00
; separate extension from file name
2019-09-07 16:45:03 +02:00
mov ecx, 0x80
mov esi, .dir_buf
mov edi, esi
scasb esi, '.'
2019-08-21 18:47:03 +02:00
; print file name
2019-09-07 16:45:03 +02:00
sub ax1, esi, edi
2019-08-21 18:47:03 +02:00
dec ax1
2019-09-07 16:45:03 +02:00
call nprint, edi
2019-08-21 18:47:03 +02:00
; calculate where to put extension
2019-09-07 16:45:03 +02:00
sub edi, esi, .dir_buf
dec edi
2019-08-21 18:47:03 +02:00
2019-09-03 09:06:58 +02:00
.dir_ext_pad:
2019-08-21 19:10:26 +02:00
; print at least 11 non-space characters before extension
2019-09-07 16:45:03 +02:00
blte 11, edi, .dir_print_ext
2019-08-21 18:47:03 +02:00
prn ' '
2019-09-07 16:45:03 +02:00
inc edi
2019-09-03 09:06:58 +02:00
jmp .dir_ext_pad
2019-08-21 18:47:03 +02:00
2019-09-03 09:06:58 +02:00
.dir_print_ext:
2019-08-21 18:47:03 +02:00
prn ' '
; here we print at least 4 characters excluding '.'
2019-09-07 16:45:03 +02:00
mov ecx, 4
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
bne b[esi], '.', .dir_print_ext.1
inc esi
2019-08-21 18:47:03 +02:00
2019-09-03 09:06:58 +02:00
.dir_print_ext.1:
2019-09-07 16:45:03 +02:00
bzr b[esi], .dir_print_ext.2
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
; print and decrease ecx, unless it's already 0
prn b[esi]
inc esi
2019-09-08 19:04:07 +02:00
jecxz .dir_print_ext.1
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
dec ecx
2019-09-03 09:06:58 +02:00
jmp .dir_print_ext.1
2019-08-21 18:47:03 +02:00
2019-09-03 09:06:58 +02:00
.dir_print_ext.2:
2019-08-21 18:47:03 +02:00
; did we print at least 4 bytes?
2019-09-08 19:04:07 +02:00
jecxz .dir_print_bytes ; yes, carry on
2019-08-21 18:47:03 +02:00
2019-09-03 09:06:58 +02:00
.dir_pe2.l:
2019-08-21 18:47:03 +02:00
prn ' '
2019-09-03 09:06:58 +02:00
loop .dir_pe2.l
2019-08-21 18:47:03 +02:00
2019-09-03 09:06:58 +02:00
.dir_print_bytes:
2019-08-21 18:47:03 +02:00
; print file size in bytes
prn ' '
prn ' '
prn ' '
2019-09-07 16:45:03 +02:00
shr eax, nx3, 10
and nx3, 1023
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
push nx3, eax
2019-09-03 09:06:58 +02:00
call printf, .dir_bytesstr
2019-09-07 16:45:03 +02:00
add esp, 16
2019-08-21 18:47:03 +02:00
2019-09-03 09:06:58 +02:00
.dir_prepare_next:
2019-08-21 18:47:03 +02:00
; go find next entry
prn 10
2019-09-03 09:06:58 +02:00
jmp .dir_next
2019-08-21 18:47:03 +02:00
2019-09-03 09:06:58 +02:00
.dir_end:
2019-09-07 16:45:03 +02:00
shr eax, nx2, 10
shr edx, eax, 10
and eax, 1023
and nx2, 1023
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
push nx2, eax, edx
2019-09-03 09:06:58 +02:00
call printf, .dir_endstr0
2019-09-07 16:45:03 +02:00
add esp, 24
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
push nx1, nx0
2019-09-03 09:06:58 +02:00
call printf, .dir_endstr1
2019-09-07 16:45:03 +02:00
add esp, 16
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
pop nx3, nx2
pop nx1, nx0
2019-08-21 18:47:03 +02:00
leave
jmp .print_prompt
; special case: direcory
2019-09-03 09:06:58 +02:00
.dir_is_dir:
2019-09-07 16:45:03 +02:00
inc nx1
2019-08-21 18:47:03 +02:00
; use printf instead of print
2019-08-21 19:10:26 +02:00
; because it returns the # of
; printed characters
2019-09-03 09:06:58 +02:00
call printf, .dir_buf
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
blte 11, eax, .dir_no_pad
sub ecx, 11, eax
dec ecx
2019-08-21 18:47:03 +02:00
.dir.l:
prn ' '
loop .dir.l
.dir_no_pad:
call print, .dir_ext
2019-09-03 09:06:58 +02:00
jmp .dir_print_bytes
2019-08-21 18:47:03 +02:00
2019-09-03 09:06:58 +02:00
.dir_buf = [0x80]
2019-08-21 18:47:03 +02:00
.dir_ext = " <DIR> "
2019-09-03 09:06:58 +02:00
.dir_endstr0 = " total %dMB + %dKB + %dB\n"
.dir_endstr1 = " found %d file(s), %d dir(s)\n"
2019-08-21 18:47:03 +02:00
.dirmsg = "Directory of C:\\\n\n"
2019-09-03 09:06:58 +02:00
.dir_bytesstr = "%d kilobytes + %d bytes"
; .dir_bytesstr = "%dMB + %dKB + %dB" # too soon
2019-08-21 18:47:03 +02:00
# 228 "command.k" 2
# 1 "usr/cmd-exec.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.
.try_exec:
; try without appending ".com"
2019-09-07 16:45:03 +02:00
mov eax, Sys.OpenFile
2019-08-21 18:47:03 +02:00
mov ax0, argv0
trap 0
; we good?
2019-09-07 16:45:03 +02:00
blte zero, eax, .do_exec
2019-08-21 18:47:03 +02:00
; nope, append ".com" and try again
2019-09-07 16:45:03 +02:00
sub ecx, argbuf.size, 5
2019-08-21 18:47:03 +02:00
scasb ax0, zero ; find null-term
mov b[ax0+0], '.' ; ".com"
mov b[ax0+1], 'c'
mov b[ax0+2], 'o'
mov b[ax0+3], 'm'
nul b[ax0+4]
; try again
2019-09-07 16:45:03 +02:00
mov eax, Sys.OpenFile
2019-08-21 18:47:03 +02:00
mov ax0, argv0
trap 0
; still no good?
2019-09-07 16:45:03 +02:00
bltz eax, .exec_not_found
2019-08-21 18:47:03 +02:00
.do_exec:
; load file into memory
2019-09-07 16:45:03 +02:00
mov ax0, eax
2019-09-03 09:06:58 +02:00
mov ax1, 0x108000
2019-08-21 18:47:03 +02:00
mov ax2, 0x8000
2019-09-07 16:45:03 +02:00
mov eax, Sys.ReadFile
2019-08-21 18:47:03 +02:00
trap 0
; save load address
2019-09-07 16:45:03 +02:00
mov ecx, eax
2019-08-21 18:47:03 +02:00
; close file
2019-09-07 16:45:03 +02:00
mov eax, Sys.CloseFile
2019-08-21 18:47:03 +02:00
trap 0
; read anything?
2019-09-07 16:45:03 +02:00
bltz ecx, .couldnt_read
2019-09-08 19:04:07 +02:00
jecxz .empty_file
2019-08-21 18:47:03 +02:00
; all good, let's go
2019-09-07 16:45:03 +02:00
mov eax, Sys.ExecuteInFrame
2019-09-03 09:06:58 +02:00
mov ax0, 0x108000
2019-08-21 18:47:03 +02:00
mov ax1, 5
trap 0
; unreachable
jmp abort
# 229 "command.k" 2
# 1 "usr/cmd-fsmisc.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.
.handle_ERASE:
2019-09-07 16:45:03 +02:00
mov eax, Sys.RemoveFile
2019-08-21 18:47:03 +02:00
mov ax0, q[argv1pos]
bzr ax0, .need_params
trap 0
2019-09-07 16:45:03 +02:00
bltz eax, .couldnt_remove
2019-08-21 18:47:03 +02:00
jmp .handle_MAKE ; re-create it back
.handle_MAKE:
2019-09-07 16:45:03 +02:00
mov eax, Sys.CreateFile
2019-08-21 18:47:03 +02:00
mov ax0, q[argv1pos]
bzr ax0, .need_params
trap 0
2019-09-07 16:45:03 +02:00
bltz eax, .couldnt_open
2019-08-21 18:47:03 +02:00
jmp .print_prompt
.handle_PRINT:
2019-09-07 16:45:03 +02:00
mov eax, Sys.OpenFile
2019-08-21 18:47:03 +02:00
mov ax0, q[argv1pos]
bzr ax0, .need_params
trap 0
2019-09-07 16:45:03 +02:00
bltz eax, .file_not_found
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
mov ax0, eax
2019-09-03 09:06:58 +02:00
mov ax1, 0x108000
2019-08-21 18:47:03 +02:00
mov ax2, 0x8000
2019-09-07 16:45:03 +02:00
mov eax, Sys.ReadFile
2019-08-21 18:47:03 +02:00
trap 0
2019-09-07 16:45:03 +02:00
mov ecx, eax
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
mov eax, Sys.CloseFile
2019-08-21 18:47:03 +02:00
trap 0
2019-09-07 16:45:03 +02:00
bltz ecx, .couldnt_read
2019-09-08 19:04:07 +02:00
jecxz .empty_file
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
call nprint, 0x108000, ecx
2019-08-21 18:47:03 +02:00
jmp .print_prompt
.handle_REMOVE:
2019-09-07 16:45:03 +02:00
mov eax, Sys.RemoveFile
2019-08-21 18:47:03 +02:00
mov ax0, q[argv1pos]
bzr ax0, .need_params
trap 0
2019-09-07 16:45:03 +02:00
bltz eax, .couldnt_remove
2019-08-21 18:47:03 +02:00
jmp .print_prompt
# 230 "command.k" 2
.handle_CLS:
prn 0x8BF00001
jmp .print_prompt
.handle_CRASH:
jmp abort
.handle_DATE:
call GetTimeUTC
2019-09-07 16:45:03 +02:00
mov ecx, b[eax+4]
inc ecx
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
push b[eax+3], ecx, w[eax+6]
2019-08-21 18:47:03 +02:00
call printf, .datefmt
2019-09-07 16:45:03 +02:00
add esp, 40
2019-08-21 18:47:03 +02:00
jmp .print_prompt
.datefmt = "%d/%d/%d\n"
.handle_DUMP:
dump
jmp .print_prompt
.handle_ECHO:
2019-09-07 16:45:03 +02:00
mov eax, q[argv1pos]
2019-09-08 19:04:07 +02:00
jeaxz .echo.end
2019-08-21 18:47:03 +02:00
2019-09-07 16:45:03 +02:00
call print, eax
2019-08-21 18:47:03 +02:00
.echo.end:
prn 10
jmp .print_prompt
.handle_EXIT:
2019-09-07 16:45:03 +02:00
mov eax, Sys.Shutdown
2019-08-21 18:47:03 +02:00
trap 0
jmp .print_prompt
.handle_HALT:
2019-09-07 16:45:03 +02:00
mov eax, Sys.EnterHaltMode
2019-08-21 18:47:03 +02:00
trap 0
jmp .print_prompt
.handle_PROMPT:
mov ax0, prompt
mov ax1, q[argv1pos]
bzr ax1, .need_params
call strcpy
jmp .print_prompt
.handle_TIME:
call GetTimeUTC
2019-09-07 16:45:03 +02:00
push b[eax], b[eax+1], b[eax+2]
2019-08-21 18:47:03 +02:00
call printf, .timefmt
2019-09-07 16:45:03 +02:00
add esp, 24
2019-08-21 18:47:03 +02:00
jmp .print_prompt
.timefmt = "%d:%d:%d\n"
.handle_VERS:
2019-09-07 16:45:03 +02:00
call print, cmd.veesionstr
2019-08-21 18:47:03 +02:00
prn 10
jmp .print_prompt
.handle_HELP:
call print, .helpmsg
call print, .helpmsg.cls
call print, .helpmsg.date
call print, .helpmsg.dir
call print, .helpmsg.dump
call print, .helpmsg.echo
call print, .helpmsg.erase
call print, .helpmsg.exit
call print, .helpmsg.help
call print, .helpmsg.halt
call print, .helpmsg.make
call print, .helpmsg.print
call print, .helpmsg.prompt
call print, .helpmsg.remove
call print, .helpmsg.time
call print, .helpmsg.ver
jmp .print_prompt
.helpmsg = "The following commands are built-in:\n"
.helpmsg.cls = " CLS Clear screen\n"
.helpmsg.date = " DATE Display current date\n"
.helpmsg.dir = " DIR Print contents of current directory\n"
.helpmsg.dump = " DUMP Toggles debug instruction dumping\n"
.helpmsg.echo = " ECHO Write arguments to standard output\n"
.helpmsg.erase = " ERASE Clear a file, making it blank\n"
.helpmsg.exit = " EXIT Initiate machine shutdown\n"
.helpmsg.help = " HELP Display these messages\n"
.helpmsg.halt = " HALT Put processor in halt mode\n"
.helpmsg.make = " MAKE Create an empty file\n"
.helpmsg.print = " PRINT Display contents of text file\n"
.helpmsg.prompt = " PROMPT Change the command line prompt\n"
.helpmsg.remove = " REMOVE Delete a file (permanently)\n"
.helpmsg.time = " TIME Display current time of day\n"
2019-09-07 16:45:03 +02:00
.helpmsg.ver = " VERS Display current COMMAND.COM veesion\n"
2019-08-21 18:47:03 +02:00
.exec_not_found:
push argv0
call printf, .enf_errmsg
2019-09-07 16:45:03 +02:00
add esp, 8
2019-08-21 18:47:03 +02:00
jmp .print_prompt
.enf_errmsg = "%s: file not found\n"
.file_not_found:
push q[argv1pos], argv0
call printf, .fnf_errmsg
2019-09-07 16:45:03 +02:00
add esp, 16
2019-08-21 18:47:03 +02:00
jmp .print_prompt
.fnf_errmsg = "%s: %s: file not found\n"
.empty_file:
push q[argv1pos], argv0
call printf, .ef_errmsg
2019-09-07 16:45:03 +02:00
add esp, 16
2019-08-21 18:47:03 +02:00
jmp .print_prompt
.ef_errmsg = "%s: %s: file was empty\n"
.couldnt_open:
push q[argv1pos], argv0
call printf, .cno_errmsg
2019-09-07 16:45:03 +02:00
add esp, 16
2019-08-21 18:47:03 +02:00
jmp .print_prompt
.cno_errmsg = "%s: %s: an error occured while opening file\n"
.couldnt_remove:
push q[argv1pos], argv0
call printf, .cne_errmsg
2019-09-07 16:45:03 +02:00
add esp, 16
2019-08-21 18:47:03 +02:00
jmp .print_prompt
.cne_errmsg = "%s: %s: an error occured while removing file\n"
.couldnt_read:
push q[argv1pos], argv0
call printf, .cnr_errmsg
2019-09-07 16:45:03 +02:00
add esp, 16
2019-08-21 18:47:03 +02:00
jmp .print_prompt
.cnr_errmsg = "%s: %s: an error occured while reading file\n"
.need_params:
call print, argv0
call print, .np_errmsg
jmp .print_prompt
.np_errmsg = ": need more parameters\n"