https://github.com/akkartik/mu/blob/master/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     52/push-edx
 20     53/push-ebx
 21     56/push-esi
 22     57/push-edi
 23     # ecx = filename
 24     8b/-> *(ebp+8) 1/r32/ecx
 25     # var size/edx: int = filename->length + 1 for the trailing null character
 26     8b/-> *ecx 2/r32/edx
 27     42/increment-edx
 28     # var s/esi: (stream size)
 29     29/subtract-from %esp 2/r32/edx
 30     52/push-edx  # size
 31     68/push 0/imm32/read
 32     68/push 0/imm32/write
 33     89/<- %esi 4/r32/esp
 34     # copy filename and a final null character
 35     (clear-stream %esi)
 36     (write %esi %ecx)
 37     # spill edx
 38     52/push-edx
 39     # var fd/ecx: fd = open(filename)
 40     8d/copy-address *(esi+0xc) 3/r32/ebx
 41     8b/-> *(ebp+0xc) 1/r32/ecx/flags
 42     ba/copy-to-edx 0x180/imm32/permissions
 43     e8/call syscall_open/disp32
 44     89/<- %ecx 0/r32/eax
 45     # restore edx
 46     5a/pop-to-edx
 47     # allocate a buffered-file
 48     (allocate Heap 0x1010 *(ebp+0x10))  # file-buffer-size + 16 for other fields
 49     # var out-addr/edi: (addr buffered-file)
 50     8b/-> *(ebp+0x10) 7/r32/edi
 51     (lookup *edi *(edi+4))  # => eax
 52     89/<- %edi 0/r32/eax
 53     # out-addr->size = 4KB
 54     c7 0/subop/copy *(edi+0xc) 0x1000/imm32/file-buffer-size  # Stream-size + 4 for fd
 55     # out-addr->fd = fd
 56     89/<- *edi 1/r32/ecx
 57 $open:end:
 58     # . reclaim locals
 59     01/add-to %esp 2/r32/edx
 60     81 0/subop/add %esp 0xc/imm32
 61     # . restore registers
 62     5f/pop-to-edi
 63     5e/pop-to-esi
 64     5b/pop-to-ebx
 65     5a/pop-to-edx
 66     59/pop-to-ecx
 67     58/pop-to-eax
 68     # . epilogue
 69     89/<- %esp 5/r32/ebp
 70     5d/pop-to-ebp
 71     c3/return
 72 
 73 populate-buffered-file-containing:  # contents: (addr array byte), out: (addr handle buffered-file)
 74     # . prologue
 75     55/push-ebp
 76     89/<- %ebp 4/r32/esp
 77     # . save registers
 78     50/push-eax
 79     51/push-ecx
 80     56/push-esi
 81     57/push-edi
 82     # esi = contents
 83     8b/-> *(ebp+8) 6/r32/esi
 84     # var n/ecx: int = len(contents)
 85     8b/-> *esi 1/r32/ecx
 86     # var stream/edi: (handle stream byte)
 87     68/push 0/imm32
 88     68/push 0/imm32
 89     89/<- %edi 4/r32/esp
 90     # allocate stream
 91     (new-stream Heap %ecx 1 %edi)
 92     # var stream-addr/edi: (addr stream byte) = lookup(stream)
 93     (lookup *edi *(edi+4))  # => eax
 94     89/<- %edi 0/r32/eax
 95     # write contents to stream
 96     (write %edi %esi)
 97     # allocate buffered-file
 98     (allocate Heap 0x110 *(ebp+0xc))
 99     # var out-addr/eax: (addr buffered-file)
100     8b/-> *(ebp+0xc) 0/r32/eax
101     (lookup *eax *(eax+4))  # => eax
102     # out-addr->size = 256 bytes
103     c7 0/subop/copy *(eax+0xc) 0x100/imm32/file-buffer-size
104     # out-addr->fd = stream
105     89/<- *eax 7/r32/edi
106 $populate-buffered-file-containing:end:
107     # . reclaim locals
108     81 0/subop/add %esp 8/imm32
109     # . restore registers
110     5f/pop-to-edi
111     5e/pop-to-esi
112     59/pop-to-ecx
113     58/pop-to-eax
114     # . epilogue
115     89/<- %esp 5/r32/ebp
116     5d/pop-to-ebp
117     c3/return
118 
119 new-buffered-file:  # out: (addr handle buffered-file)
120     # . prologue
121     55/push-ebp
122     89/<- %ebp 4/r32/esp
123     # . save registers
124     50/push-eax
125     51/push-ecx
126     # var stream/ecx: (handle stream byte)
127     68/push 0/imm32
128     68/push 0/imm32
129     89/<- %ecx 4/r32/esp
130     # allocate stream
131     (new-stream Heap 0x100 1 %ecx)
132     # var stream-addr/ecx: (addr stream byte) = lookup(stream)
133     (lookup *ecx *(ecx+4))  # => eax
134     89/<- %ecx 0/r32/eax
135     # allocate buffered-file
136     (allocate Heap 0x110 *(ebp+8))
137     # var out-addr/eax: (addr buffered-file)
138     8b/-> *(ebp+8) 0/r32/eax
139     (lookup *eax *(eax+4))  # => eax
140     # out-addr->size = 256 bytes
141     c7 0/subop/copy *(eax+0xc) 0x100/imm32/file-buffer-size
142     # out-addr->fd = stream
143     89/<- *eax 1/r32/ecx
144 $new-buffered-file:end:
145     # . reclaim locals
146     81 0/subop/add %esp 8/imm32
147     # . restore registers
148     59/pop-to-ecx
149     58/pop-to-eax
150     # . epilogue
151     89/<- %esp 5/r32/ebp
152     5d/pop-to-ebp
153     c3/return