c95648c960
The Mu shell has no string literals, only streams. No random access, only sequential access. But I've been playing fast and loose with its read pointer until now. Hopefully things are cleaned up now.
162 lines
4.1 KiB
Plaintext
162 lines
4.1 KiB
Plaintext
# Some helpers for copying non-overlapping regions of memory.
|
|
# Really only intended to be called from code generated by mu.subx.
|
|
|
|
== code
|
|
|
|
copy-bytes: # src: (addr byte), dest: (addr byte), size: int
|
|
# pseudocode:
|
|
# curr-src/esi = src
|
|
# curr-dest/edi = dest
|
|
# i/ecx = 0
|
|
# while true
|
|
# if (i >= size) break
|
|
# *curr-dest = *curr-src
|
|
# ++curr-src
|
|
# ++curr-dest
|
|
# ++i
|
|
#
|
|
# . prologue
|
|
55/push-ebp
|
|
89/<- %ebp 4/r32/esp
|
|
# . save registers
|
|
50/push-eax
|
|
51/push-ecx
|
|
52/push-edx
|
|
56/push-esi
|
|
57/push-edi
|
|
# curr-src/esi = src
|
|
8b/-> *(ebp+8) 6/r32/esi
|
|
# curr-dest/edi = dest
|
|
8b/-> *(ebp+0xc) 7/r32/edi
|
|
# var i/ecx: int = 0
|
|
b9/copy-to-ecx 0/imm32
|
|
# edx = size
|
|
8b/-> *(ebp+0x10) 2/r32/edx
|
|
{
|
|
# if (i >= size) break
|
|
39/compare %ecx 2/r32/edx
|
|
7d/jump-if->= break/disp8
|
|
# *curr-dest = *curr-src
|
|
8a/byte-> *esi 0/r32/AL
|
|
88/byte<- *edi 0/r32/AL
|
|
# update
|
|
46/increment-esi
|
|
47/increment-edi
|
|
41/increment-ecx
|
|
eb/jump loop/disp8
|
|
}
|
|
$copy-bytes:end:
|
|
# . restore registers
|
|
5f/pop-to-edi
|
|
5e/pop-to-esi
|
|
5a/pop-to-edx
|
|
59/pop-to-ecx
|
|
58/pop-to-eax
|
|
# . epilogue
|
|
89/<- %esp 5/r32/ebp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
stream-to-array: # in: (addr stream _), out: (addr handle array _)
|
|
# . prologue
|
|
55/push-ebp
|
|
89/<- %ebp 4/r32/esp
|
|
# . save registers
|
|
50/push-eax
|
|
51/push-ecx
|
|
52/push-edx
|
|
56/push-esi
|
|
# esi = s
|
|
8b/-> *(ebp+8) 6/r32/esi
|
|
# var len/ecx: int = s->write - s->read
|
|
8b/-> *esi 1/r32/ecx
|
|
2b/subtract *(esi+4) 1/r32/ecx
|
|
# allocate
|
|
(allocate-array Heap %ecx *(ebp+0xc))
|
|
# var in/edx: (addr byte) = s->data + s->read
|
|
8b/-> *(esi+4) 2/r32/edx
|
|
8d/copy-address *(esi+edx+0xc) 2/r32/edx
|
|
# var dest/eax: (addr byte) = data for out
|
|
8b/-> *(ebp+0xc) 0/r32/eax
|
|
(lookup *eax *(eax+4)) # => eax
|
|
8d/copy-address *(eax+4) 0/r32/eax
|
|
#
|
|
(copy-bytes %edx %eax %ecx)
|
|
$stream-to-array:end:
|
|
# . restore registers
|
|
5e/pop-to-esi
|
|
5a/pop-to-edx
|
|
59/pop-to-ecx
|
|
58/pop-to-eax
|
|
# . epilogue
|
|
89/<- %esp 5/r32/ebp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
test-stream-to-array:
|
|
# . prologue
|
|
55/push-ebp
|
|
89/<- %ebp 4/r32/esp
|
|
# setup
|
|
(clear-stream _test-input-stream)
|
|
(write _test-input-stream "abc")
|
|
# skip something
|
|
(read-byte _test-input-stream) # => eax
|
|
8b/-> *$_test-input-stream->read 0/r32/eax
|
|
(check-ints-equal %eax 1 "F - test-stream-to-array/pre")
|
|
# var out/ecx: (handle array byte)
|
|
68/push 0/imm32
|
|
68/push 0/imm32
|
|
89/<- %ecx 4/r32/esp
|
|
#
|
|
(stream-to-array _test-input-stream %ecx)
|
|
(lookup *ecx *(ecx+4)) # => eax
|
|
(check-strings-equal %eax "bc" "F - test-stream-to-array")
|
|
8b/-> *$_test-input-stream->read 0/r32/eax
|
|
(check-ints-equal %eax 1 "F - test-stream-to-array/read-pointer-not-perturbed")
|
|
# . epilogue
|
|
89/<- %esp 5/r32/ebp
|
|
5d/pop-to-ebp
|
|
c3/return
|
|
|
|
# like stream-to-array but ignore surrounding quotes
|
|
# we might do other stuff here later
|
|
unquote-stream-to-array: # in: (addr stream _), out: (addr handle array _)
|
|
# . prologue
|
|
55/push-ebp
|
|
89/<- %ebp 4/r32/esp
|
|
# . save registers
|
|
50/push-eax
|
|
51/push-ecx
|
|
52/push-edx
|
|
56/push-esi
|
|
# esi = s
|
|
8b/-> *(ebp+8) 6/r32/esi
|
|
# var len/ecx: int = s->write - s->read - 2
|
|
8b/-> *esi 1/r32/ecx
|
|
2b/subtract *(esi+4) 1/r32/ecx
|
|
81 7/subop/compare %ecx 2/imm32
|
|
7c/jump-if-< $unquote-stream-to-array:end/disp8
|
|
81 5/subop/subtract %ecx 2/imm32
|
|
# allocate
|
|
(allocate-array Heap %ecx *(ebp+0xc))
|
|
# var in/edx: (addr byte) = s->data + s->read + 1
|
|
8b/-> *(esi+4) 2/r32/edx
|
|
8d/copy-address *(esi+edx+0xd) 2/r32/edx # Stream-data + 1
|
|
# var dest/eax: (addr byte) = data for out
|
|
8b/-> *(ebp+0xc) 0/r32/eax
|
|
(lookup *eax *(eax+4)) # => eax
|
|
8d/copy-address *(eax+4) 0/r32/eax
|
|
#
|
|
(copy-bytes %edx %eax %ecx)
|
|
$unquote-stream-to-array:end:
|
|
# . restore registers
|
|
5e/pop-to-esi
|
|
5a/pop-to-edx
|
|
59/pop-to-ecx
|
|
58/pop-to-eax
|
|
# . epilogue
|
|
89/<- %esp 5/r32/ebp
|
|
5d/pop-to-ebp
|
|
c3/return
|