mu/linux/306files.subx
Kartik K. Agaram 71e4f38129 7842 - new directory organization
Baremetal is now the default build target and therefore has its sources
at the top-level. Baremetal programs build using the phase-2 Mu toolchain
that requires a Linux kernel. This phase-2 codebase which used to be at
the top-level is now under the linux/ directory. Finally, the phase-2 toolchain,
while self-hosting, has a way to bootstrap from a C implementation, which
is now stored in linux/bootstrap. The bootstrap C implementation uses some
literate programming tools that are now in linux/bootstrap/tools.

So the whole thing has gotten inverted. Each directory should build one
artifact and include the main sources (along with standard library). Tools
used for building it are relegated to sub-directories, even though those
tools are often useful in their own right, and have had lots of interesting
programs written using them.

A couple of things have gotten dropped in this process:
  - I had old ways to run on just a Linux kernel, or with a Soso kernel.
    No more.
  - I had some old tooling for running a single test at the cursor. I haven't
    used that lately. Maybe I'll bring it back one day.

The reorg isn't done yet. Still to do:
  - redo documentation everywhere. All the README files, all other markdown,
    particularly vocabulary.md.
  - clean up how-to-run comments at the start of programs everywhere
  - rethink what to do with the html/ directory. Do we even want to keep
    supporting it?

In spite of these shortcomings, all the scripts at the top-level, linux/
and linux/bootstrap are working. The names of the scripts also feel reasonable.
This is a good milestone to take stock at.
2021-03-03 22:21:03 -08:00

170 lines
4.7 KiB
Plaintext

# Methods for constructing buffered-file objects.
#
# TODO: There are hard-coded parameters here for buffer sizes. When they
# overflow, tracking down what's going on can get hairy.
#
# HACK: buffered-file stores naked addrs. This is safe because buffered-file
# objects are opaque. But still sub-optimal; they'll be harder to reclaim when
# we get around to that.
== code
open: # filename: (addr array byte), write?: boolean, out: (addr handle buffered-file)
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
# . save registers
50/push-eax
51/push-ecx
# var new-fd/ecx: fd
(open-fd *(ebp+8) *(ebp+0xc)) # => eax
89/<- %ecx 0/r32/eax
# if fd < 0 return
3d/compare-eax-with 0/imm32
7c/jump-if-< $open:end/disp8
# allocate a buffered-file
(allocate Heap 0x1010 *(ebp+0x10)) # file-buffer-size + 16 for other fields
# var out-addr/eax: (addr buffered-file)
8b/-> *(ebp+0x10) 0/r32/eax
(lookup *eax *(eax+4)) # => eax
# out-addr->size = 4KB
c7 0/subop/copy *(eax+0xc) 0x1000/imm32/file-buffer-size # Stream-size + 4 for fd
# out-addr->fd = fd
89/<- *eax 1/r32/ecx
$open:end:
# . restore registers
59/pop-to-ecx
58/pop-to-eax
# . epilogue
89/<- %esp 5/r32/ebp
5d/pop-to-ebp
c3/return
open-fd: # filename: (addr array byte), write?: boolean -> result/eax: fd
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
# . save registers
51/push-ecx
52/push-edx
53/push-ebx
56/push-esi
# ecx = filename
8b/-> *(ebp+8) 1/r32/ecx
# var size/edx: int = filename->length + 1 for the trailing null character
8b/-> *ecx 2/r32/edx
42/increment-edx
# var s/esi: (stream size)
29/subtract-from %esp 2/r32/edx
52/push-edx # size
68/push 0/imm32/read
68/push 0/imm32/write
89/<- %esi 4/r32/esp
# copy filename and a final null character
(clear-stream %esi)
(write %esi %ecx)
# spill edx
52/push-edx
# var fd/eax: fd = open(filename)
8d/copy-address *(esi+0xc) 3/r32/ebx
8b/-> *(ebp+0xc) 1/r32/ecx/flags
ba/copy-to-edx 0x180/imm32/permissions
e8/call syscall_open/disp32
# restore edx
5a/pop-to-edx
$open-fd:end:
# . reclaim locals
01/add-to %esp 2/r32/edx
81 0/subop/add %esp 0xc/imm32
# . restore registers
5e/pop-to-esi
5b/pop-to-ebx
5a/pop-to-edx
59/pop-to-ecx
# . epilogue
89/<- %esp 5/r32/ebp
5d/pop-to-ebp
c3/return
populate-buffered-file-containing: # contents: (addr array byte), out: (addr handle buffered-file)
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
# . save registers
50/push-eax
51/push-ecx
56/push-esi
57/push-edi
# esi = contents
8b/-> *(ebp+8) 6/r32/esi
# var n/ecx: int = len(contents)
8b/-> *esi 1/r32/ecx
# var stream/edi: (handle stream byte)
68/push 0/imm32
68/push 0/imm32
89/<- %edi 4/r32/esp
# allocate stream
(new-stream Heap %ecx 1 %edi)
# var stream-addr/edi: (addr stream byte) = lookup(stream)
(lookup *edi *(edi+4)) # => eax
89/<- %edi 0/r32/eax
# write contents to stream
(write %edi %esi)
# allocate buffered-file
(allocate Heap 0x110 *(ebp+0xc))
# var out-addr/eax: (addr buffered-file)
8b/-> *(ebp+0xc) 0/r32/eax
(lookup *eax *(eax+4)) # => eax
# out-addr->size = 256 bytes
c7 0/subop/copy *(eax+0xc) 0x100/imm32/file-buffer-size
# out-addr->fd = stream
89/<- *eax 7/r32/edi
$populate-buffered-file-containing:end:
# . reclaim locals
81 0/subop/add %esp 8/imm32
# . restore registers
5f/pop-to-edi
5e/pop-to-esi
59/pop-to-ecx
58/pop-to-eax
# . epilogue
89/<- %esp 5/r32/ebp
5d/pop-to-ebp
c3/return
new-buffered-file: # out: (addr handle buffered-file)
# . prologue
55/push-ebp
89/<- %ebp 4/r32/esp
# . save registers
50/push-eax
51/push-ecx
# var stream/ecx: (handle stream byte)
68/push 0/imm32
68/push 0/imm32
89/<- %ecx 4/r32/esp
# allocate stream
(new-stream Heap 0x100 1 %ecx)
# var stream-addr/ecx: (addr stream byte) = lookup(stream)
(lookup *ecx *(ecx+4)) # => eax
89/<- %ecx 0/r32/eax
# allocate buffered-file
(allocate Heap 0x110 *(ebp+8))
# var out-addr/eax: (addr buffered-file)
8b/-> *(ebp+8) 0/r32/eax
(lookup *eax *(eax+4)) # => eax
# out-addr->size = 256 bytes
c7 0/subop/copy *(eax+0xc) 0x100/imm32/file-buffer-size
# out-addr->fd = stream
89/<- *eax 1/r32/ecx
$new-buffered-file:end:
# . reclaim locals
81 0/subop/add %esp 8/imm32
# . restore registers
59/pop-to-ecx
58/pop-to-eax
# . epilogue
89/<- %esp 5/r32/ebp
5d/pop-to-ebp
c3/return