https://github.com/akkartik/mu/blob/main/baremetal/309stream.subx
  1 # Some unsafe methods not intended to be used directly in SubX, only through
  2 # Mu after proper type-checking.
  3 
  4 == code
  5 
  6 stream-empty?:  # s: (addr stream _) -> result/eax: boolean
  7     # . prologue
  8     55/push-ebp
  9     89/<- %ebp 4/r32/esp
 10     # . save registers
 11     51/push-ecx
 12     56/push-esi
 13     # result = false
 14     b8/copy-to-eax 0/imm32/false
 15     # esi = s
 16     8b/-> *(ebp+8) 6/r32/esi
 17     # return s->read >= s->write
 18     8b/-> *esi 1/r32/ecx
 19     39/compare-with *(esi+4) 1/r32/ecx
 20     0f 9d/set-if->= %al
 21 $stream-empty?:end:
 22     # . restore registers
 23     5e/pop-to-esi
 24     59/pop-to-ecx
 25     # . epilogue
 26     89/<- %esp 5/r32/ebp
 27     5d/pop-to-ebp
 28     c3/return
 29 
 30 stream-full?:  # s: (addr stream _) -> result/eax: boolean
 31     # . prologue
 32     55/push-ebp
 33     89/<- %ebp 4/r32/esp
 34     # . save registers
 35     51/push-ecx
 36     56/push-esi
 37     # result = false
 38     b8/copy-to-eax 0/imm32/false
 39     # esi = s
 40     8b/-> *(ebp+8) 6/r32/esi
 41     # return s->write >= s->size
 42     8b/-> *(esi+8) 1/r32/ecx
 43     39/compare-with *esi 1/r32/ecx
 44     0f 9d/set-if->= %al
 45 $stream-full?:end:
 46     # . restore registers
 47     5e/pop-to-esi
 48     59/pop-to-ecx
 49     # . epilogue
 50     89/<- %esp 5/r32/ebp
 51     5d/pop-to-ebp
 52     c3/return
 53 
 54 write-to-stream:  # s: (addr stream _), in: (addr byte), n: int
 55     # . prologue
 56     55/push-ebp
 57     89/<- %ebp 4/r32/esp
 58     # . save registers
 59     50/push-eax
 60     51/push-ecx
 61     52/push-edx
 62     53/push-ebx
 63     57/push-edi
 64     # edi = s
 65     8b/-> *(ebp+8) 7/r32/edi
 66     # var swrite/edx: int = s->write
 67     8b/-> *edi 2/r32/edx
 68     # if (swrite + n > s->size) abort
 69     8b/-> *(ebp+0x10) 1/r32/ecx
 70     01/add-to %ecx 2/r32/edx
 71     3b/compare 1/r32/ecx *(edi+8)
 72     0f 8f/jump-if-> $write-to-stream:abort/disp32
 73     # var out/edx: (addr byte) = s->data + s->write
 74     8d/copy-address *(edi+edx+0xc) 2/r32/edx
 75     # var outend/ebx: (addr byte) = out + n
 76     8b/-> *(ebp+0x10) 3/r32/ebx
 77     8d/copy-address *(edx+ebx) 3/r32/ebx
 78     # eax = in
 79     8b/-> *(ebp+0xc) 0/r32/eax
 80     # var inend/ecx: (addr byte) = in + n
 81     8b/-> *(ebp+0x10) 1/r32/ecx
 82     8d/copy-address *(eax+ecx) 1/r32/ecx
 83     #
 84     (_append-4  %edx %ebx  %eax %ecx)  # => eax
 85     # s->write += n
 86     8b/-> *(ebp+0x10) 1/r32/ecx
 87     01/add-to *edi 1/r32/ecx
 88 $write-to-stream:end:
 89     # . restore registers
 90     5f/pop-to-edi
 91     5b/pop-to-ebx
 92     5a/pop-to-edx
 93     59/pop-to-ecx
 94     58/pop-to-eax
 95     # . epilogue
 96     89/<- %esp 5/r32/ebp
 97     5d/pop-to-ebp
 98     c3/return
 99 
100 $write-to-stream:abort:
101     (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "write-to-stream: stream full" 3)  # 3=cyan
102     {
103       eb/jump loop/disp8
104     }
105     # never gets here
106 
107 read-from-stream:  # s: (addr stream _), out: (addr byte), n: int
108     # . prologue
109     55/push-ebp
110     89/<- %ebp 4/r32/esp
111     # . save registers
112     50/push-eax
113     51/push-ecx
114     52/push-edx
115     53/push-ebx
116     56/push-esi
117     # esi = s
118     8b/-> *(ebp+8) 6/r32/esi
119     # var sread/edx: int = s->read
120     8b/-> *(esi+4) 2/r32/edx
121     # if (sread + n > s->write) abort
122     8b/-> *(ebp+0x10) 1/r32/ecx
123     01/add-to %ecx 2/r32/edx
124     3b/compare 1/r32/ecx *esi
125     0f 8f/jump-if-> $read-from-stream:abort/disp32
126     # var in/edx: (addr byte) = s->data + s->read
127     8d/copy-address *(esi+edx+0xc) 2/r32/edx
128     # var inend/ebx: (addr byte) = in + n
129     8b/-> *(ebp+0x10) 3/r32/ebx
130     8d/copy-address *(edx+ebx) 3/r32/ebx
131     # eax = out
132     8b/-> *(ebp+0xc) 0/r32/eax
133     # var outend/ecx: (addr byte) = out + n
134     8b/-> *(ebp+0x10) 1/r32/ecx
135     8d/copy-address *(eax+ecx) 1/r32/ecx
136     #
137     (_append-4  %eax %ecx  %edx %ebx)  # => eax
138     # s->read += n
139     8b/-> *(ebp+0x10) 1/r32/ecx
140     01/add-to *(esi+4) 1/r32/ecx
141 $read-from-stream:end:
142     # . restore registers
143     5e/pop-to-esi
144     5b/pop-to-ebx
145     5a/pop-to-edx
146     59/pop-to-ecx
147     58/pop-to-eax
148     # . epilogue
149     89/<- %esp 5/r32/ebp
150     5d/pop-to-ebp
151     c3/return
152 
153 $read-from-stream:abort:
154     (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "read-from-stream: stream empty" 3)  # 3=cyan
155     {
156       eb/jump loop/disp8
157     }
158     # never gets here
159 
160 stream-first:  # s: (addr stream byte) -> result/eax: byte
161     # . prologue
162     55/push-ebp
163     89/<- %ebp 4/r32/esp
164     # . save registers
165     51/push-ecx
166     56/push-esi
167     # result = false
168     b8/copy-to-eax 0/imm32
169     # esi = s
170     8b/-> *(ebp+8) 6/r32/esi
171     # var idx/ecx: int = s->read
172     8b/-> *(esi+4) 1/r32/ecx
173     # if idx >= s->write return 0
174     3b/compare-with 1/r32/ecx *esi
175     7d/jump-if->= $stream-first:end/disp8
176     # result = s->data[idx]
177     8a/byte-> *(esi+ecx+0xc) 0/r32/AL
178 $stream-first:end:
179     # . restore registers
180     5e/pop-to-esi
181     59/pop-to-ecx
182     # . epilogue
183     89/<- %esp 5/r32/ebp
184     5d/pop-to-ebp
185     c3/return
186 
187 stream-final:  # s: (addr stream byte) -> result/eax: byte
188     # . prologue
189     55/push-ebp
190     89/<- %ebp 4/r32/esp
191     # . save registers
192     51/push-ecx
193     56/push-esi
194     # result = false
195     b8/copy-to-eax 0/imm32
196     # esi = s
197     8b/-> *(ebp+8) 6/r32/esi
198     # var max/ecx: int = s->write
199     8b/-> *esi 1/r32/ecx
200     # if s->read >= max return 0
201     39/compare-with *(esi+4) 1/r32/ecx
202     7d/jump-if->= $stream-final:end/disp8
203     # var idx/ecx: int = max - 1
204     49/decrement-ecx
205     # result = s->data[idx]
206     8a/byte-> *(esi+ecx+0xc) 0/r32/AL
207 $stream-final:end:
208     # . restore registers
209     5e/pop-to-esi
210     59/pop-to-ecx
211     # . epilogue
212     89/<- %esp 5/r32/ebp
213     5d/pop-to-ebp
214     c3/return