https://github.com/akkartik/mu/blob/main/linux/306files.subx

      1 # Methods for constructing buffered-file objects.
      2 #
      3 # TODO: There are hard-coded parameters here for buffer sizes. When they
      4 # overflow, tracking down what's going on can get hairy.
      5 #
      6 # HACK: buffered-file stores naked addrs. This is safe because buffered-file
      7 # objects are opaque. But still sub-optimal; they'll be harder to reclaim when
      8 # we get around to that.
      9
     10 == code
     11
     12 open:  # filename: (addr array byte), write?: boolean, out: (addr handle buffered-file)
     13     # . prologue
     14     55/push-ebp
     15     89/<- %ebp 4/r32/esp
     16     # . save registers
     17     50/push-eax
     18     51/push-ecx
     19     # var new-fd/ecx: fd
     20     (open-fd *(ebp+8) *(ebp+0xc))  # => eax
     21     89/<- %ecx 0/r32/eax
     22     # if fd < 0 return
     23     3d/compare-eax-with 0/imm32
     24     7c/jump-if-< $open:end/disp8
     25     # allocate a buffered-file
     26     (allocate Heap 0x1010 *(ebp+0x10))  # file-buffer-size + 16 for other fields
     27     # var out-addr/eax: (addr buffered-file)
     28     8b/-> *(ebp+0x10) 0/r32/eax
     29     (lookup *eax *(eax+4))  # => eax
     30     # out-addr->size = 4KB
     31     c7 0/subop/copy *(eax+0xc) 0x1000/imm32/file-buffer-size  # Stream-size + 4 for fd
     32     # out-addr->fd = fd
     33     89/<- *eax 1/r32/ecx
     34 $open:end:
     35     # . restore registers
     36     59/pop-to-ecx
     37     58/pop-to-eax
     38     # . epilogue
     39     89/<- %esp 5/r32/ebp
     40     5d/pop-to-ebp
     41     c3/return
     42
     43 open-fd:  # filename: (addr array byte), write?: boolean -> result/eax: fd
     44     # . prologue
     45     55/push-ebp
     46     89/<- %ebp 4/r32/esp
     47     # . save registers
     48     51/push-ecx
     49     52/push-edx
     50     53/push-ebx
     51     56/push-esi
     52     # ecx = filename
     53     8b/-> *(ebp+8) 1/r32/ecx
     54     # var size/edx: int = filename->length + 1 for the trailing null character
     55     8b/-> *ecx 2/r32/edx
     56     42/increment-edx
     57     # var s/esi: (stream size)
     58     29/subtract-from %esp 2/r32/edx
     59     52/push-edx  # size
     60     68/push 0/imm32/read
     61     68/push 0/imm32/write
     62     89/<- %esi 4/r32/esp
     63     # copy filename and a final null character
     64     (clear-stream %esi)
     65     (write %esi %ecx)
     66     # spill edx
     67     52/push-edx
     68     # var fd/eax: fd = open(filename)
     69     8d/copy-address *(esi+0xc) 3/r32/ebx
     70     8b/-> *(ebp+0xc) 1/r32/ecx/flags
     71     ba/copy-to-edx 0x180/imm32/permissions
     72     e8/call syscall_open/disp32
     73     # restore edx
     74     5a/pop-to-edx
     75 $open-fd:end:
     76     # . reclaim locals
     77     01/add-to %esp 2/r32/edx
     78     81 0/subop/add %esp 0xc/imm32
     79     # . restore registers
     80     5e/pop-to-esi
     81     5b/pop-to-ebx
     82     5a/pop-to-edx
     83     59/pop-to-ecx
     84     # . epilogue
     85     89/<- %esp 5/r32/ebp
     86     5d/pop-to-ebp
     87     c3/return
     88
     89 populate-buffered-file-containing:  # contents: (addr array byte), out: (addr handle buffered-file)
     90     # . prologue
     91     55/push-ebp
     92     89/<- %ebp 4/r32/esp
     93     # . save registers
     94     50/push-eax
     95     51/push-ecx
     96     56/push-esi
     97     57/push-edi
     98     # esi = contents
     99     8b/-> *(ebp+8) 6/r32/esi
    100     # var n/ecx: int = len(contents)
    101     8b/-> *esi 1/r32/ecx
    102     # var stream/edi: (handle stream byte)
    103     68/push 0/imm32
    104     68/push 0/imm32
    105     89/<- %edi 4/r32/esp
    106     # allocate stream
    107     (new-stream Heap %ecx 1 %edi)
    108     # var stream-addr/edi: (addr stream byte) = lookup(stream)
    109     (lookup *edi *(edi+4))  # => eax
    110     89/<- %edi 0/r32/eax
    111     # write contents to stream
    112     (write %edi %esi)
    113     # allocate buffered-file
    114     (allocate Heap 0x110 *(ebp+0xc))
    115     # var out-addr/eax: (addr buffered-file)
    116     8b/-> *(ebp+0xc) 0/r32/eax
    117     (lookup *eax *(eax+4))  # => eax
    118     # out-addr->size = 256 bytes
    119     c7 0/subop/copy *(eax+0xc) 0x100/imm32/file-buffer-size
    120     # out-addr->fd = stream
    121     89/<- *eax 7/r32/edi
    122 $populate-buffered-file-containing:end:
    123     # . reclaim locals
    124     81 0/subop/add %esp 8/imm32
    125     # . restore registers
    126     5f/pop-to-edi
    127     5e/pop-to-esi
    128     59/pop-to-ecx
    129     58/pop-to-eax
    130     # . epilogue
    131     89/<- %esp 5/r32/ebp
    132     5d/pop-to-ebp
    133     c3/return
    134
    135 new-buffered-file:  # out: (addr handle buffered-file)
    136     # . prologue
    137     55/push-ebp
    138     89/<- %ebp 4/r32/esp
    139     # . save registers
    140     50/push-eax
    141     51/push-ecx
    142     # var stream/ecx: (handle stream byte)
    143     68/push 0/imm32
    144     68/push 0/imm32
    145     89/<- %ecx 4/r32/esp
    146     # allocate stream
    147     (new-stream Heap 0x100 1 %ecx)
    148     # var stream-addr/ecx: (addr stream byte) = lookup(stream)
    149     (lookup *ecx *(ecx+4))  # => eax
    150     89/<- %ecx 0/r32/eax
    151     # allocate buffered-file
    152     (allocate Heap 0x110 *(ebp+8))
    153     # var out-addr/eax: (addr buffered-file)
    154     8b/-> *(ebp+8) 0/r32/eax
    155     (lookup *eax *(eax+4))  # => eax
    156     # out-addr->size = 256 bytes
    157     c7 0/subop/copy *(eax+0xc) 0x100/imm32/file-buffer-size
    158     # out-addr->fd = stream
    159     89/<- *eax 1/r32/ecx
    160 $new-buffered-file:end:
    161     # . reclaim locals
    162     81 0/subop/add %esp 8/imm32
    163     # . restore registers
    164     59/pop-to-ecx
    165     58/pop-to-eax
    166     # . epilogue
    167     89/<- %esp 5/r32/ebp
    168     5d/pop-to-ebp
    169     c3/return