https://github.com/akkartik/mu/blob/main/baremetal/107trace.subx
 1 #   instruction                     effective address                                                   register    displacement    immediate
 2 # . op          subop               mod             rm32          base        index         scale       r32
 3 # . 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
 4 
 5 # 3-argument variant of _append
 6 _append-3:  # out: (addr byte), outend: (addr byte), s: (addr array byte) -> num_bytes_appended/eax
 7     # . prologue
 8     55/push-ebp
 9     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
10     # . save registers
11     51/push-ecx
12     # eax = _append-4(out, outend, &s->data[0], &s->data[s->size])
13     # . . push &s->data[s->size]
14     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .                         0/r32/eax   0x10/disp8      .                 # copy *(ebp+16) to eax
15     8b/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy *eax to ecx
16     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/eax  1/index/ecx   .           1/r32/ecx   4/disp8         .                 # copy eax+ecx+4 to ecx
17     51/push-ecx
18     # . . push &s->data[0]
19     8d/copy-address                 1/mod/*+disp8   0/rm32/eax    .           .             .           1/r32/ecx   4/disp8         .                 # copy eax+4 to ecx
20     51/push-ecx
21     # . . push outend
22     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           0xc/disp8       .                 # push *(ebp+12)
23     # . . push out
24     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
25     # . . call
26     e8/call  _append-4/disp32
27     # . . discard args
28     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               0x10/imm32        # add to esp
29 $_append-3:end:
30     # . restore registers
31     59/pop-to-ecx
32     # . epilogue
33     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
34     5d/pop-to-ebp
35     c3/return
36 
37 # 4-argument variant of _append
38 _append-4:  # out: (addr byte), outend: (addr byte), in: (addr byte), inend: (addr byte) -> num_bytes_appended/eax: int
39     # . prologue
40     55/push-ebp
41     89/copy                         3/mod/direct    5/rm32/ebp    .           .             .           4/r32/esp   .               .                 # copy esp to ebp
42     # . save registers
43     51/push-ecx
44     52/push-edx
45     53/push-ebx
46     56/push-esi
47     57/push-edi
48     # num_bytes_appended = 0
49     b8/copy-to-eax  0/imm32
50     # edi = out
51     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           7/r32/edi   8/disp8         .                 # copy *(ebp+8) to edi
52     # edx = outend
53     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   0xc/disp8       .                 # copy *(ebp+12) to edx
54     # esi = in
55     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           6/r32/esi   0x10/disp8      .                 # copy *(ebp+16) to esi
56     # ecx = inend
57     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           1/r32/ecx   0x14/disp8      .                 # copy *(ebp+20) to ecx
58 $_append-4:loop:
59     # if (in >= inend) break
60     39/compare                      3/mod/direct    6/rm32/esi    .           .             .           1/r32/ecx   .               .                 # compare esi with ecx
61     73/jump-if-addr>=  $_append-4:end/disp8
62     # if (out >= outend) abort  # just to catch test failures fast
63     39/compare                      3/mod/direct    7/rm32/edi    .           .             .           2/r32/edx   .               .                 # compare edi with edx
64     73/jump-if-addr>=  $_append-4:end/disp8  # TODO: abort
65     # *out = *in
66     8a/copy-byte                    0/mod/indirect  6/rm32/esi    .           .             .           3/r32/BL    .               .                 # copy byte at *esi to BL
67     88/copy-byte                    0/mod/indirect  7/rm32/edi    .           .             .           3/r32/BL    .               .                 # copy byte at BL to *edi
68     # ++num_bytes_appended
69     40/increment-eax
70     # ++in
71     46/increment-esi
72     # ++out
73     47/increment-edi
74     eb/jump  $_append-4:loop/disp8
75 $_append-4:end:
76     # . restore registers
77     5f/pop-to-edi
78     5e/pop-to-esi
79     5b/pop-to-ebx
80     5a/pop-to-edx
81     59/pop-to-ecx
82     # . epilogue
83     89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
84     5d/pop-to-ebp
85     c3/return
86 
87 # . . vim:nowrap:textwidth=0