kvisc/ka/usr/cmd/dir.k

160 lines
2.6 KiB
Plaintext

; The OS/K Team licenses this file to you under the MIT license.
; See the LICENSE file in the project root for more information.
N := 11
builtins.dir:
push rbp
mov rbp, rsp
push r12
push r13
push r14
push r15
mov r12, zero # no. of files found
mov r13, zero # no. of directories found
mov r14, zero # total amount of bytes found
call print, .dirmsg
.first:
mov rax, Sys.FindFirst
mov ax0, .buf
mov ax1, FNAME_MAX
trap 0
jmp .list
.next:
mov rax, Sys.FindNext
mov ax0, .buf
mov ax1, FNAME_MAX
trap 0
.list:
jmp.axz .end
mov r15, rcx # file size
inc r14, rcx
; directory?
jmp.dxnz .is_dir
; found a file
inc r12, 1
; separate extension from file name
mov rcx, FNAME_MAX
mov rsi, .buf
mov rdi, rsi
scasb.rep.nz rsi, '.'
; print file name
sub rcx, rsi, rdi
prns.rep rdi
; calculate where to put extension
sub rdi, rsi, .buf
dec rdi, 1
.ext_pad:
; print at least N non-space characters before extension
b.ae rdi, N, .print_ext
prn ' '
inc rdi, 1
jmp .ext_pad
.print_ext:
; here we print at least 4 characters excluding '.'
mov rcx, 4
prn ' '
cmp b[rsi], '.'
inc.z rsi, 1
.print_ext.1:
b.z b[rsi], 0, .print_ext.2
; print and decrease rcx, unless it's already 0
prn b[rsi]
inc rsi, 1
dec.cxnz rcx, 1
jmp .print_ext.1
.print_ext.2:
; did we print at least 4 bytes?
jmp.cxz .print_bytes ; yes, carry on
prn.rep ' '
.print_bytes:
; print file size in bytes
mov rcx, 3
prn.rep ' '
shr rax, r15, 10
and r15, r15, 1023
push r15
push rax
call printf, .bytesstr
inc rsp, 16
.prepare_next:
; go find next entry
prn 10
jmp .next
.end:
shr rax, r14, 10
shr rdx, rax, 10
and rax, rax, 1023
and r14, r14, 1023
push r14
push rax
push rdx
call printf, .endstr0
inc rsp, 24
push r13
push r12
call printf, .endstr1
inc rsp, 16
pop r15
pop r14
pop r13
pop r12
leave
ret
; special case: direcory
.is_dir:
inc r13, 1
mov rcx, STRLEN_MAX
mov rdx, .buf
prns.rep.nz rdx
sub rcx, STRLEN_MAX, rcx
sub rcx, N, rcx
prn.rep ' '
call print, .dir_ext
jmp .print_bytes
.buf = [FNAME_MAX]
.dir_ext = " <DIR>"
.endstr0 = " total %dMB + %dKB + %dB\n"
.endstr1 = " found %d file(s), %d dir(s)\n"
.dirmsg = "Directory of C:\\\n\n"
.bytesstr = "%d kilobytes + %d bytes"
# .bytesstr = "%dMB + %dKB + %dB" # too soon