https://github.com/akkartik/mu/blob/main/112read-byte.subx
  1 # Read a single byte from a stream.
  2 #
  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.
  5 
  6 == code
  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
 10 
 11 # Return next byte value in eax, with top 3 bytes cleared.
 12 # Abort on reaching end of stream.
 13 read-byte:  # s: (addr stream byte) -> result/eax: byte
 14     # . prologue
 15     55/push-ebp
 16     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
 17     # . save registers
 18     51/push-ecx
 19     56/push-esi
 20     # esi = s
 21     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   8/disp8         .                 # copy *(ebp+8) to esi
 22     # ecx = s->read
 23     8b/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           1/r32/ecx   4/disp8         .                 # copy *(esi+4) to ecx
 24     # if (f->read >= f->write) abort
 25     3b/compare                      0/mod/indirect  6/rm32/esi    .           .             .           1/r32/ecx   .               .                 # compare ecx with *esi
 26     0f 8d/jump-if->=  $read-byte:abort/disp32
 27     # result = f->data[f->read]
 28     31/xor                          3/mod/direct    0/rm32/eax    .           .             .           0/r32/eax   .               .                 # clear eax
 29     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/esi  1/index/ecx   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(esi+ecx+12) to AL
 30     # ++f->read
 31     ff          0/subop/increment   1/mod/*+disp8   6/rm32/esi    .           .             .           .           4/disp8         .                 # increment *(esi+4)
 32 $read-byte:end:
 33     # . restore registers
 34     5e/pop-to-esi
 35     59/pop-to-ecx
 36     # . epilogue
 37     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
 38     5d/pop-to-ebp
 39     c3/return
 40 
 41 $read-byte:abort:
 42     (draw-text-wrapping-right-then-down-from-cursor-over-full-screen 0 "read-byte: empty stream" 3 0)  # 3=cyan
 43     {
 44       eb/jump loop/disp8
 45     }
 46     # never gets here
 47 
 48 == data
 49 
 50 _test-input-stream:  # (stream byte)
 51     # current write index
 52     0/imm32
 53     # current read index
 54     0/imm32
 55     # size
 56     0x400/imm32  # 1024 bytes
 57     # data (64 lines x 16 bytes/line)
 58     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 59     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 60     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 61     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 62     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 63     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 64     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 65     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 66     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 67     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 68     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 69     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 70     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 71     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 72     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 73     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 74     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 75     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 76     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 77     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 78     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 79     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 80     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 81     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 82     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 83     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 84     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 85     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 86     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 87     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 88     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 89     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 90     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 91     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 92     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 93     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 94     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 95     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 96     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 97     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 98     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
 99     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
100     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
101     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
102     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
103     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
104     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
105     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
106     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
107     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
108     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
109     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
110     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
111     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
112     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
113     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
114     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
115     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
116     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
117     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
118     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
119     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
120     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
121     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
122 
123 # . . vim:nowrap:textwidth=0