1 # Comparing 'regular' size-prefixed strings.
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
8 string-equal?: # s: (addr array byte), benchmark: (addr array byte) -> result/eax: boolean
10 # if (s->size != benchmark->size) return false
11 # return string-starts-with?(s, benchmark)
15 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
21 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
23 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi
25 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx
27 # if (ecx != benchmark->size) return false
28 39/compare 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # compare *edi and ecx
29 b8/copy-to-eax 0/imm32/false
30 75/jump-if-!= $string-equal?:end/disp8
31 $string-equal?:contents:
32 # string-starts-with?(s, benchmark)
34 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
35 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8)
37 e8/call string-starts-with?/disp32
39 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
46 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
50 string-starts-with?: # s: (addr array byte), benchmark: (addr array byte) -> result/eax: boolean
52 # if (s->size < benchmark->size) return false
54 # currb = benchmark->data
55 # maxb = &benchmark->data[benchmark->size]
59 # if (c1 != c2) return false
72 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
79 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi
81 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi
82 # var bsize/ecx: int = benchmark->size
83 8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # copy *edi to ecx
84 $string-starts-with?:sizes:
85 # if (s->size < bsize) return false
86 39/compare 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # compare *esi with ecx
87 7c/jump-if-< $string-starts-with?:false/disp8
88 # var currs/esi: (addr byte) = s->data
89 81 0/subop/add 3/mod/direct 6/rm32/esi . . . . . 4/imm32 # add to esi
90 # var currb/edi: (addr byte) = benchmark->data
91 81 0/subop/add 3/mod/direct 7/rm32/edi . . . . . 4/imm32 # add to edi
92 # var maxb/ecx: (addr byte) = &benchmark->data[benchmark->size]
93 01/add 3/mod/direct 1/rm32/ecx . . . 7/r32/edi . . # add edi to ecx
94 # var c1/eax: byte = 0
95 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax
96 # var c2/edx: byte = 0
97 31/xor 3/mod/direct 2/rm32/edx . . . 2/r32/edx . . # clear edx
98 $string-starts-with?:loop:
99 # if (currs >= maxs) return true
100 39/compare 3/mod/direct 7/rm32/edi . . . 1/r32/ecx . . # compare edi with ecx
101 73/jump-if-addr>= $string-starts-with?:true/disp8
103 8a/copy-byte 0/mod/indirect 6/rm32/esi . . . 0/r32/AL . . # copy byte at *esi to AL
105 8a/copy-byte 0/mod/indirect 7/rm32/edi . . . 2/r32/DL . . # copy byte at *edi to DL
106 # if (c1 != c2) return false
107 39/compare 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # compare eax and edx
108 75/jump-if-!= $string-starts-with?:false/disp8
113 eb/jump $string-starts-with?:loop/disp8
114 $string-starts-with?:true:
115 b8/copy-to-eax 1/imm32
116 eb/jump $string-starts-with?:end/disp8
117 $string-starts-with?:false:
118 b8/copy-to-eax 0/imm32
119 $string-starts-with?:end:
120 # . restore registers
126 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
132 test-compare-empty-with-empty-string:
133 # eax = string-equal?("", "")
138 e8/call string-equal?/disp32
140 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
141 # check-ints-equal(eax, 1, msg)
143 68/push "F - test-compare-empty-with-empty-string"/imm32
147 e8/call check-ints-equal/disp32
149 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
152 test-compare-empty-with-non-empty-string: # also checks size-mismatch code path
153 # eax = string-equal?("", "Abc")
158 e8/call string-equal?/disp32
160 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
161 # check-ints-equal(eax, 0, msg)
163 68/push "F - test-compare-empty-with-non-empty-string"/imm32
164 68/push 0/imm32/false
167 e8/call check-ints-equal/disp32
169 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
172 test-compare-equal-strings:
173 # eax = string-equal?("Abc", "Abc")
178 e8/call string-equal?/disp32
180 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
181 # check-ints-equal(eax, 1, msg)
183 68/push "F - test-compare-equal-strings"/imm32
187 e8/call check-ints-equal/disp32
189 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
192 test-compare-inequal-strings-equal-sizes:
193 # eax = string-equal?("Abc", "Adc")
198 e8/call string-equal?/disp32
200 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
201 # check-ints-equal(eax, 0, msg)
203 68/push "F - test-compare-inequal-strings-equal-sizes"/imm32
204 68/push 0/imm32/false
207 e8/call check-ints-equal/disp32
209 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
212 # helper for later tests
213 check-strings-equal: # s: (addr array byte), expected: (addr array byte), msg: (addr array byte)
216 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp
219 # var eax: boolean = string-equal?(s, expected)
221 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12)
222 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8)
224 e8/call string-equal?/disp32
226 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
227 # check-ints-equal(eax, 1, msg)
229 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16)
233 e8/call check-ints-equal/disp32
235 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp
236 $check-strings-equal:end:
237 # . restore registers
240 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp
245 test-check-strings-equal:
246 # check-strings-equal("Abc", "Abc")
251 e8/call check-strings-equal/disp32
253 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp
256 # . . vim:nowrap:textwidth=0