https://github.com/akkartik/mu/blob/master/310copy-bytes.subx
  1 # Fill a region of memory with zeroes.
  2 
  3 == code
  4 
  5 copy-bytes:  # src: (addr byte), dest: (addr byte), size: int
  6     # pseudocode:
  7     #   curr-src/esi = src
  8     #   curr-dest/edi = dest
  9     #   i/ecx = 0
 10     #   while true
 11     #     if (i >= size) break
 12     #     *curr-dest = *curr-src
 13     #     ++curr-src
 14     #     ++curr-dest
 15     #     ++i
 16     #
 17     # . prologue
 18     55/push-ebp
 19     89/<- %ebp 4/r32/esp
 20     # . save registers
 21     50/push-eax
 22     51/push-ecx
 23     52/push-edx
 24     56/push-esi
 25     57/push-edi
 26     # curr-src/esi = src
 27     8b/-> *(ebp+8) 6/r32/esi
 28     # curr-dest/edi = dest
 29     8b/-> *(ebp+0xc) 7/r32/edi
 30     # var i/ecx: int = 0
 31     b9/copy-to-ecx 0/imm32
 32     # edx = size
 33     8b/-> *(ebp+0x10) 2/r32/edx
 34     {
 35       # if (i >= size) break
 36       39/compare %ecx 2/r32/edx
 37       7d/jump-if->=  break/disp8
 38       # *curr-dest = *curr-src
 39       8a/byte-> *esi 0/r32/AL
 40       88/byte<- *edi 0/r32/AL
 41       # update
 42       46/increment-esi
 43       47/increment-edi
 44       41/increment-ecx
 45       eb/jump loop/disp8
 46     }
 47 $copy-bytes:end:
 48     # . restore registers
 49     5f/pop-to-edi
 50     5e/pop-to-esi
 51     5a/pop-to-edx
 52     59/pop-to-ecx
 53     58/pop-to-eax
 54     # . epilogue
 55     89/<- %esp 5/r32/ebp
 56     5d/pop-to-ebp
 57     c3/return
 58 
 59 stream-to-string:  # in: (addr stream _), out: (addr handle array _)
 60     # . prologue
 61     55/push-ebp
 62     89/<- %ebp 4/r32/esp
 63     # . save registers
 64     50/push-eax
 65     51/push-ecx
 66     52/push-edx
 67     56/push-esi
 68     # esi = s
 69     8b/-> *(ebp+8) 6/r32/esi
 70     # var len/ecx: int = s->write - s->read
 71     8b/-> *esi 1/r32/ecx
 72     2b/subtract *(esi+4) 1/r32/ecx
 73     # allocate
 74     (allocate-array Heap %ecx *(ebp+0xc))
 75     # var in/edx: (addr byte) = s->data + s->read
 76     8b/-> *(esi+4) 2/r32/edx
 77     8d/copy-address *(esi+edx+0xc) 2/r32/edx
 78     # var dest/eax: (addr byte) = data for out
 79     8b/-> *(ebp+0xc) 0/r32/eax
 80     (lookup *eax *(eax+4))  # => eax
 81     8d/copy-address *(eax+4) 0/r32/eax
 82     #
 83     (copy-bytes %edx %eax %ecx)
 84 $stream-to-string:end:
 85     # . restore registers
 86     5e/pop-to-esi
 87     5a/pop-to-edx
 88     59/pop-to-ecx
 89     58/pop-to-eax
 90     # . epilogue
 91     89/<- %esp 5/r32/ebp
 92     5d/pop-to-ebp
 93     c3/return
 94 
 95 test-stream-to-string:
 96     # . prologue
 97     55/push-ebp
 98     89/<- %ebp 4/r32/esp
 99     # setup
100     (clear-stream _test-input-stream)
101     (write _test-input-stream "abc")
102     # skip something
103     (read-byte _test-input-stream)  # => eax
104     # var out/ecx: (handle array byte)
105     68/push 0/imm32
106     68/push 0/imm32
107     89/<- %ecx 4/r32/esp
108     #
109     (stream-to-string _test-input-stream %ecx)
110     (lookup *ecx *(ecx+4))  # => eax
111     (check-strings-equal %eax "bc")
112     # . epilogue
113     89/<- %esp 5/r32/ebp
114     5d/pop-to-ebp
115     c3/return