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     # if fd < 0 return
 48     3d/compare-eax-with 0/imm32
 49     7c/jump-if-< $open:end/disp8
 50     # allocate a buffered-file
 51     (allocate Heap 0x1010 *(ebp+0x10))  # file-buffer-size + 16 for other fields
 52     # var out-addr/edi: (addr buffered-file)
 53     8b/-> *(ebp+0x10) 7/r32/edi
 54     (lookup *edi *(edi+4))  # => eax
 55     89/<- %edi 0/r32/eax
 56     # out-addr->size = 4KB
 57     c7 0/subop/copy *(edi+0xc) 0x1000/imm32/file-buffer-size  # Stream-size + 4 for fd
 58     # out-addr->fd = fd
 59     89/<- *edi 1/r32/ecx
 60 $open:end:
 61     # . reclaim locals
 62     01/add-to %esp 2/r32/edx
 63     81 0/subop/add %esp 0xc/imm32
 64     # . restore registers
 65     5f/pop-to-edi
 66     5e/pop-to-esi
 67     5b/pop-to-ebx
 68     5a/pop-to-edx
 69     59/pop-to-ecx
 70     58/pop-to-eax
 71     # . epilogue
 72     89/<- %esp 5/r32/ebp
 73     5d/pop-to-ebp
 74     c3/return
 75 
 76 populate-buffered-file-containing:  # contents: (addr array byte), out: (addr handle buffered-file)
 77     # . prologue
 78     55/push-ebp
 79     89/<- %ebp 4/r32/esp
 80     # . save registers
 81     50/push-eax
 82     51/push-ecx
 83     56/push-esi
 84     57/push-edi
 85     # esi = contents
 86     8b/-> *(ebp+8) 6/r32/esi
 87     # var n/ecx: int = len(contents)
 88     8b/-> *esi 1/r32/ecx
 89     # var stream/edi: (handle stream byte)
 90     68/push 0/imm32
 91     68/push 0/imm32
 92     89/<- %edi 4/r32/esp
 93     # allocate stream
 94     (new-stream Heap %ecx 1 %edi)
 95     # var stream-addr/edi: (addr stream byte) = lookup(stream)
 96     (lookup *edi *(edi+4))  # => eax
 97     89/<- %edi 0/r32/eax
 98     # write contents to stream
 99     (write %edi %esi)
100     # allocate buffered-file
101     (allocate Heap 0x110 *(ebp+0xc))
102     # var out-addr/eax: (addr buffered-file)
103     8b/-> *(ebp+0xc) 0/r32/eax
104     (lookup *eax *(eax+4))  # => eax
105     # out-addr->size = 256 bytes
106     c7 0/subop/copy *(eax+0xc) 0x100/imm32/file-buffer-size
107     # out-addr->fd = stream
108     89/<- *eax 7/r32/edi
109 $populate-buffered-file-containing:end:
110     # . reclaim locals
111     81 0/subop/add %esp 8/imm32
112     # . restore registers
113     5f/pop-to-edi
114     5e/pop-to-esi
115     59/pop-to-ecx
116     58/pop-to-eax
117     # . epilogue
118     89/<- %esp 5/r32/ebp
119     5d/pop-to-ebp
120     c3/return
121 
122 new-buffered-file:  # out: (addr handle buffered-file)
123     # . prologue
124     55/push-ebp
125     89/<- %ebp 4/r32/esp
126     # . save registers
127     50/push-eax
128     51/push-ecx
129     # var stream/ecx: (handle stream byte)
130     68/push 0/imm32
131     68/push 0/imm32
132     89/<- %ecx 4/r32/esp
133     # allocate stream
134     (new-stream Heap 0x100 1 %ecx)
135     # var stream-addr/ecx: (addr stream byte) = lookup(stream)
136     (lookup *ecx *(ecx+4))  # => eax
137     89/<- %ecx 0/r32/eax
138     # allocate buffered-file
139     (allocate Heap 0x110 *(ebp+8))
140     # var out-addr/eax: (addr buffered-file)
141     8b/-> *(ebp+8) 0/r32/eax
142     (lookup *eax *(eax+4))  # => eax
143     # out-addr->size = 256 bytes
144     c7 0/subop/copy *(eax+0xc) 0x100/imm32/file-buffer-size
145     # out-addr->fd = stream
146     89/<- *eax 1/r32/ecx
147 $new-buffered-file:end:
148     # . reclaim locals
149     81 0/subop/add %esp 8/imm32
150     # . restore registers
151     59/pop-to-ecx
152     58/pop-to-eax
153     # . epilogue
154     89/<- %esp 5/r32/ebp
155     5d/pop-to-ebp
156     c3/return