1 # write-byte-buffered: add a single byte to a buffered-file.
2 # flush: write out any buffered writes to disk.
4 # TODO: Come up with a way to signal failure to write to disk. This is hard
5 # since the failure may impact previous calls that were buffered.
9 # The buffered file for standard output.
10 Stdout: # buffered-file
11 # file descriptor or (addr stream byte)
12 1/imm32 # standard output
14 # inlined fields for a stream
22 00 00 00 00 00 00 00 00 # 8 bytes
24 # TODO: 8 bytes is too small. We'll need to grow the buffer for efficiency. But
25 # I don't want to type in 1024 bytes here.
28 # instruction effective address register displacement immediate
29 # . op subop mod rm32 base index scale r32
30 # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes
32 # Write lower byte of 'n' to 'f'.
33 write-byte-buffered: # f: (addr buffered-file), n: int
36 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
41 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi
43 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 4/disp8 . # copy *(edi+4) to ecx
44 # if (f->write >= f->size) flush and clear f's stream
45 3b/compare 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 0xc/disp8 . # compare ecx with *(edi+12)
46 7c/jump-if-< $write-byte-buffered:to-stream/disp8
53 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
54 # . clear-stream(stream = f+4)
56 8d/copy-address 1/mod/*+disp8 7/rm32/edi . . . 0/r32/eax 4/disp8 . # copy edi+4 to eax
59 e8/call clear-stream/disp32
61 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
62 # . f->write must now be 0; update its cache at ecx
63 31/xor 3/mod/direct 1/rm32/ecx . . . 1/r32/ecx . . # clear ecx
64 $write-byte-buffered:to-stream:
66 # f->data[f->write] = LSB(n)
67 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
68 8a/copy-byte 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/AL 0xc/disp8 . # copy byte at *(ebp+12) to AL
69 88/copy-byte 1/mod/*+disp8 4/rm32/sib 7/base/edi 1/index/ecx . 0/r32/AL 0x10/disp8 . # copy AL to *(edi+ecx+16)
71 ff 0/subop/increment 1/mod/*+disp8 7/rm32/edi . . . . 4/disp8 . # increment *(edi+4)
72 $write-byte-buffered:end:
77 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
81 flush: # f: (addr buffered-file)
84 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
89 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax
90 # write-stream(f->fd, data = f+4)
92 8d/copy-address 1/mod/*+disp8 0/rm32/eax . . . 1/r32/ecx 4/disp8 . # copy eax+4 to ecx
94 ff 6/subop/push 0/mod/indirect 0/rm32/eax . . . . . . # push *eax
96 e8/call write-stream/disp32
98 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
100 # . restore registers
104 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
108 test-write-byte-buffered-single:
109 # - check that write-byte-buffered writes to first byte of 'file'
111 # . clear-stream(_test-stream)
113 68/push _test-stream/imm32
115 e8/call clear-stream/disp32
117 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
118 # . clear-stream($_test-buffered-file->buffer)
120 68/push $_test-buffered-file->buffer/imm32
122 e8/call clear-stream/disp32
124 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
125 # write-byte-buffered(_test-buffered-file, 'A')
128 68/push _test-buffered-file/imm32
130 e8/call write-byte-buffered/disp32
132 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
133 # flush(_test-buffered-file)
135 68/push _test-buffered-file/imm32
139 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
140 # check-stream-equal(_test-stream, "A", msg)
142 68/push "F - test-write-byte-buffered-single"/imm32
144 68/push _test-stream/imm32
146 e8/call check-stream-equal/disp32
148 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
152 test-write-byte-buffered-multiple-flushes:
153 # - check that write-byte-buffered correctly flushes buffered data
155 # . clear-stream(_test-stream)
157 68/push _test-stream/imm32
159 e8/call clear-stream/disp32
161 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
162 # . clear-stream($_test-buffered-file->buffer)
164 68/push $_test-buffered-file->buffer/imm32
166 e8/call clear-stream/disp32
168 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
169 # fill up the buffer for _test-buffered-file
170 # . write($_test-buffered-file->buffer, "abcdef")
172 68/push "abcdef"/imm32
173 68/push $_test-buffered-file->buffer/imm32
177 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
178 # write-byte-buffered(_test-buffered-file, 'g')
181 68/push _test-buffered-file/imm32
183 e8/call write-byte-buffered/disp32
185 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
186 # flush(_test-buffered-file)
188 68/push _test-buffered-file/imm32
192 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
193 # check-stream-equal(_test-stream, "abcdefg", msg)
195 68/push "F - test-write-byte-buffered-multiple-flushes"/imm32
196 68/push "abcdefg"/imm32
197 68/push _test-stream/imm32
199 e8/call check-stream-equal/disp32
201 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
205 # - variant without buffering
207 # Write lower byte of 'n' to 'f'.
208 append-byte: # f: (addr stream byte), n: int
211 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
217 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi
219 8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # copy *edi to ecx
220 # if (f->write >= f->size) abort
221 3b/compare 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 8/disp8 . # compare ecx with *(edi+8)
222 7d/jump-if->= $append-byte:abort/disp8
223 $append-byte:to-stream:
225 # f->data[f->write] = LSB(n)
226 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
227 8a/copy-byte 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/AL 0xc/disp8 . # copy byte at *(ebp+12) to AL
228 88/copy-byte 1/mod/*+disp8 4/rm32/sib 7/base/edi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy AL to *(edi+ecx+12)
230 ff 0/subop/increment 0/mod/indirect 7/rm32/edi . . . . . . # increment *edi
232 # . restore registers
237 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
242 # . _write(2/stderr, error)
244 68/push "append-byte: out of space\n"/imm32
245 68/push 2/imm32/stderr
247 e8/call _write/disp32
249 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
251 bb/copy-to-ebx 1/imm32
252 e8/call syscall_exit/disp32
255 test-append-byte-single:
256 # - check that append-byte writes to first byte of 'file'
258 # . clear-stream(_test-stream)
260 68/push _test-stream/imm32
262 e8/call clear-stream/disp32
264 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
265 # append-byte(_test-stream, 'A')
268 68/push _test-stream/imm32
270 e8/call append-byte/disp32
272 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
273 # check-stream-equal(_test-stream, "A", msg)
275 68/push "F - test-append-byte-single"/imm32
277 68/push _test-stream/imm32
279 e8/call check-stream-equal/disp32
281 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
287 _test-output-stream: # (stream byte)
288 # current write index
293 0x800/imm32 # 2048 bytes
294 # data (128 lines x 16 bytes/line)
295 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
296 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
297 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
298 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
299 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
301 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
302 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
303 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
304 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
305 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
306 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
307 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
308 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
309 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
311 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
312 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
313 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
314 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
315 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
316 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
317 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
318 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
319 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
321 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
322 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
323 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
324 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
325 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
326 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
327 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
328 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
329 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
331 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
332 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
333 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
334 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
335 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
336 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
337 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
338 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
339 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
341 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
342 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
343 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
344 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
345 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
346 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
347 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
348 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
349 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
351 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
352 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
353 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
354 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
355 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
356 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
357 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
358 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
359 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
361 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
362 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
363 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
364 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
365 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
366 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
367 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
368 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
369 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
370 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
371 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
372 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
373 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
374 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
375 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
376 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
377 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
378 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
379 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
380 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
381 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
382 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
383 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
384 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
385 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
386 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
387 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
388 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
389 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
390 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
391 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
392 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
393 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
394 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
395 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
396 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
397 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
398 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
399 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
401 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
402 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
403 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
404 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
405 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
406 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
407 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
408 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
409 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
410 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
411 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
412 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
413 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
414 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
415 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
416 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
417 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
418 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
419 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
420 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
421 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
422 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
424 # a test buffered file for _test-output-stream
425 _test-output-buffered-file: # buffered-file
426 # file descriptor or (addr stream byte)
427 _test-output-stream/imm32
428 $_test-output-buffered-file->buffer:
429 # current write index
436 00 00 00 00 00 00 # 6 bytes
438 _test-error-stream: # (stream byte)
439 # current write index
444 0x100/imm32 # 256 bytes
445 # data (16 lines x 16 bytes/line)
446 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
447 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
448 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
449 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
451 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
452 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
453 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
454 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
455 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
456 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
457 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
458 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
459 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
460 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
461 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
463 # a test buffered file for _test-error-stream
464 _test-error-buffered-file: # buffered-file
465 # file descriptor or (addr stream byte)
466 _test-error-stream/imm32
467 $_test-error-buffered-file->buffer:
468 # current write index
475 00 00 00 00 00 00 # 6 bytes
477 # . . vim:nowrap:textwidth=0