-
Notifications
You must be signed in to change notification settings - Fork 45
/
310copy-bytes.subx
157 lines (152 loc) · 3.88 KB
/
310copy-bytes.subx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# 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
# 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")
# . 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