1 # Write a single byte to a stream.
3 # We need to do this in machine code because streams need to be opaque types,
4 # and we don't yet support opaque types in Mu.
7 # instruction effective address register displacement immediate
8 # . op subop mod rm32 base index scale r32
9 # . 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
11 # Write lower byte of 'n' to 'f'.
12 append-byte: # f: (addr stream byte), n: int
15 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
21 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 8/disp8 . # copy *(ebp+8) to edi
23 8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # copy *edi to ecx
24 # if (f->write >= f->size) abort
25 3b/compare 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 8/disp8 . # compare ecx with *(edi+8)
26 7d/jump-if->= $append-byte:abort/disp8
27 $append-byte:to-stream:
29 # f->data[f->write] = LSB(n)
30 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
31 8a/copy-byte 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/AL 0xc/disp8 . # copy byte at *(ebp+12) to AL
32 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)
34 ff 0/subop/increment 0/mod/indirect 7/rm32/edi . . . . . . # increment *edi
41 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
46 (abort "append-byte: out of space")
49 test-append-byte-single:
50 # - check that append-byte writes to first byte of 'file'
52 # . clear-stream(_test-stream)
54 68/push _test-stream/imm32
56 e8/call clear-stream/disp32
58 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp
59 # append-byte(_test-stream, 'A')
62 68/push _test-stream/imm32
64 e8/call append-byte/disp32
66 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
67 # check-stream-equal(_test-stream, "A", msg)
69 68/push "F - test-append-byte-single"/imm32
71 68/push _test-stream/imm32
73 e8/call check-stream-equal/disp32
75 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
79 undo-append-byte: # f: (addr stream byte)
82 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
86 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax
87 # if (f->write <= 0) abort
88 81 7/subop/compare 0/mod/indirect 0/rm32/eax . . . . . 0/imm32 # compare *eax
89 7e/jump-if-<= $undo-append-byte:abort/disp8
91 ff 1/subop/decrement 0/mod/indirect 0/rm32/eax . . . . . . # decrement *eax
92 $undo-append-byte:end:
96 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
100 $undo-append-byte:abort:
101 (abort "undo-append-byte: empty stream")
104 # . . vim:nowrap:textwidth=0