https://github.com/akkartik/mu/blob/main/113write-stream.subx

      1 # write-stream: like write, but write streams rather than strings
      2
      3 == code
      4 #   instruction                     effective address                                                   register    displacement    immediate
      5 # . op          subop               mod             rm32          base        index         scale       r32
      6 # . 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
      7
      8 write-stream:  # f: (addr stream byte), s: (addr stream byte)
      9     # . prologue
     10     55/push-ebp
     11     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
     12     # . save registers
     13     50/push-eax
     14     56/push-esi
     15     57/push-edi
     16     # edi = f
     17     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         7/r32/edi   8/disp8         .                 # copy *(ebp+8) to edi
     18     # esi = s
     19     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         6/r32/esi   0xc/disp8       .                 # copy *(ebp+12) to esi
     20     # eax = _append-4(&f->data[f->write], &f->data[f->size], &s->data[s->read], &s->data[s->write])
     21     # . . push &s->data[s->write]
     22     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy *esi to eax
     23     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/esi  0/index/eax   .           0/r32/eax   0xc/disp8       .                 # copy esi+eax+12 to eax
     24     50/push-eax
     25     # . . push &s->data[s->read]
     26     8b/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           0/r32/eax   4/disp8         .                 # copy *(esi+4) to eax
     27     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/esi  0/index/eax   .           0/r32/eax   0xc/disp8       .                 # copy esi+eax+12 to eax
     28     50/push-eax
     29     # . . push &f->data[f->size]
     30     8b/copy                         1/mod/*+disp8   7/rm32/edi    .           .             .           0/r32/eax   8/disp8         .                 # copy *(edi+8) to eax
     31     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    7/base/edi  0/index/eax   .           0/r32/eax   0xc/disp8       .                 # copy edi+eax+12 to eax
     32     50/push-eax
     33     # . . push &f->data[f->write]
     34     8b/copy                         0/mod/indirect  7/rm32/edi    .           .             .           0/r32/eax   .               .                 # copy *edi to eax
     35     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    7/base/edi  0/index/eax   .           0/r32/eax   0xc/disp8       .                 # copy edi+eax+12 to eax
     36     50/push-eax
     37     # . . call
     38     e8/call  _append-4/disp32
     39     # . . discard args
     40     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
     41     # f->write += eax
     42     01/add                          0/mod/indirect  7/rm32/edi    .           .             .           0/r32/eax   .               .                 # add eax to *edi
     43     # s->read += eax
     44     01/add                          1/mod/*+disp8   6/rm32/esi    .           .             .           0/r32/eax   4/disp8         .                 # add eax to *(esi+4)
     45 $write-stream:end:
     46     # . restore registers
     47     5f/pop-to-edi
     48     5e/pop-to-esi
     49     58/pop-to-eax
     50     # . epilogue
     51     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
     52     5d/pop-to-ebp
     53     c3/return
     54
     55 test-write-stream-single:
     56     # setup
     57     # . clear-stream(_test-stream)
     58     # . . push args
     59     68/push  _test-stream/imm32
     60     # . . call
     61     e8/call  clear-stream/disp32
     62     # . . discard args
     63     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
     64     # . clear-stream(_test-stream2)
     65     # . . push args
     66     68/push  _test-stream2/imm32
     67     # . . call
     68     e8/call  clear-stream/disp32
     69     # . . discard args
     70     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
     71     # . write(_test-stream2, "Ab")
     72     # . . push args
     73     68/push  "Ab"/imm32
     74     68/push  _test-stream2/imm32
     75     # . . call
     76     e8/call  write/disp32
     77     # . . discard args
     78     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
     79     # write-stream(_test-stream, _test-stream2)
     80     # . . push args
     81     68/push  _test-stream2/imm32
     82     68/push  _test-stream/imm32
     83     # . . call
     84     e8/call  write-stream/disp32
     85     # . . discard args
     86     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
     87     # check-stream-equal(_test-stream, "Ab", msg)
     88     # . . push args
     89     68/push  "F - test-write-stream-single"/imm32
     90     68/push  "Ab"/imm32
     91     68/push  _test-stream/imm32
     92     # . . call
     93     e8/call  check-stream-equal/disp32
     94     # . . discard args
     95     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
     96     # . end
     97     c3/return
     98
     99 test-write-stream-appends:
    100     # setup
    101     # . clear-stream(_test-stream)
    102     # . . push args
    103     68/push  _test-stream/imm32
    104     # . . call
    105     e8/call  clear-stream/disp32
    106     # . . discard args
    107     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
    108     # . clear-stream(_test-stream2)
    109     # . . push args
    110     68/push  _test-stream2/imm32
    111     # . . call
    112     e8/call  clear-stream/disp32
    113     # . . discard args
    114     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # add to esp
    115     # . write(_test-stream2, "C")
    116     # . . push args
    117     68/push  "C"/imm32
    118     68/push  _test-stream2/imm32
    119     # . . call
    120     e8/call  write/disp32
    121     # . . discard args
    122     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
    123     # first write
    124     # . write-stream(_test-stream, _test-stream2)
    125     # . . push args
    126     68/push  _test-stream2/imm32
    127     68/push  _test-stream/imm32
    128     # . . call
    129     e8/call  write-stream/disp32
    130     # . . discard args
    131     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
    132     # second write
    133     # . write(_test-stream2, "D")
    134     # . . push args
    135     68/push  "D"/imm32
    136     68/push  _test-stream2/imm32
    137     # . . call
    138     e8/call  write/disp32
    139     # . . discard args
    140     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
    141     # . write-stream(_test-stream, _test-stream2)
    142     # . . push args
    143     68/push  _test-stream2/imm32
    144     68/push  _test-stream/imm32
    145     # . . call
    146     e8/call  write-stream/disp32
    147     # . . discard args
    148     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
    149     # check-stream-equal(_test-stream, "CD", msg)
    150     # . . push args
    151     68/push  "F - test-write-stream-appends"/imm32
    152     68/push  "CD"/imm32
    153     68/push  _test-stream/imm32
    154     # . . call
    155     e8/call  check-stream-equal/disp32
    156     # . . discard args
    157     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0xc/imm32         # add to esp
    158     # . end
    159     c3/return
    160
    161 # like write-stream, but don't update s->read
    162 # is there a better name for this?
    163 write-stream-immutable:  # f: (addr stream byte), s: (addr stream byte)
    164     # . prologue
    165     55/push-ebp
    166     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
    167     # . save registers
    168     50/push-eax
    169     56/push-esi
    170     57/push-edi
    171     # edi = f
    172     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         7/r32/edi   8/disp8         .                 # copy *(ebp+8) to edi
    173     # esi = s
    174     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         6/r32/esi   0xc/disp8       .                 # copy *(ebp+12) to esi
    175     # eax = _append-4(&f->data[f->write], &f->data[f->size], &s->data[s->read], &s->data[s->write])
    176     # . . push &s->data[s->write]
    177     8b/copy                         0/mod/indirect  6/rm32/esi    .           .             .           0/r32/eax   .               .                 # copy *esi to eax
    178     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/esi  0/index/eax   .           0/r32/eax   0xc/disp8       .                 # copy esi+eax+12 to eax
    179     50/push-eax
    180     # . . push &s->data[s->read]
    181     8b/copy                         1/mod/*+disp8   6/rm32/esi    .           .             .           0/r32/eax   4/disp8         .                 # copy *(esi+4) to eax
    182     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/esi  0/index/eax   .           0/r32/eax   0xc/disp8       .                 # copy esi+eax+12 to eax
    183     50/push-eax
    184     # . . push &f->data[f->size]
    185     8b/copy                         1/mod/*+disp8   7/rm32/edi    .           .             .           0/r32/eax   8/disp8         .                 # copy *(edi+8) to eax
    186     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    7/base/edi  0/index/eax   .           0/r32/eax   0xc/disp8       .                 # copy edi+eax+12 to eax
    187     50/push-eax
    188     # . . push &f->data[f->write]
    189     8b/copy                         0/mod/indirect  7/rm32/edi    .           .             .           0/r32/eax   .               .                 # copy *edi to eax
    190     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    7/base/edi  0/index/eax   .           0/r32/eax   0xc/disp8       .                 # copy edi+eax+12 to eax
    191     50/push-eax
    192     # . . call
    193     e8/call  _append-4/disp32
    194     # . . discard args
    195     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
    196     # f->write += eax
    197     01/add                          0/mod/indirect  7/rm32/edi    .           .             .           0/r32/eax   .               .                 # add eax to *edi
    198 $write-stream-immutable:end:
    199     # . restore registers
    200     5f/pop-to-edi
    201     5e/pop-to-esi
    202     58/pop-to-eax
    203     # . epilogue
    204     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
    205     5d/pop-to-ebp
    206     c3/return
    207
    208 == data
    209
    210 _test-stream2:  # (stream byte)
    211     # current write index
    212     4/imm32
    213     # current read index
    214     1/imm32
    215     # size
    216     8/imm32
    217     # data
    218     41/A 42/B 43/C 44/D 00 00 00 00  # 8 bytes
    219
    220 # . . vim:nowrap:textwidth=0