1 # Some tokenization primitives. 2 3 == code 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 7 8 # extract the next run of characters that are different from a given 'delimiter' (skipping multiple delimiters if necessary) 9 # on reaching end of file, return an empty interval 10 next-token: # in: (addr stream byte), delimiter: byte, out: (addr slice) 11 # . prologue 12 55/push-ebp 13 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 14 # . save registers 15 50/push-eax 16 51/push-ecx 17 56/push-esi 18 57/push-edi 19 # esi = in 20 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi 21 # edi = out 22 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0x10/disp8 . # copy *(ebp+16) to edi 23 # skip-chars-matching(in, delimiter) 24 # . . push args 25 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 26 56/push-esi 27 # . . call 28 e8/call skip-chars-matching/disp32 29 # . . discard args 30 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 31 # out->start = &in->data[in->read] 32 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx 33 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/eax 0xc/disp8 . # copy esi+ecx+12 to eax 34 89/copy 0/mod/indirect 7/rm32/edi . . . 0/r32/eax . . # copy eax to *edi 35 # skip-chars-not-matching(in, delimiter) 36 # . . push args 37 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 38 56/push-esi 39 # . . call 40 e8/call skip-chars-not-matching/disp32 41 # . . discard args 42 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 43 # out->end = &in->data[in->read] 44 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx 45 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/eax 0xc/disp8 . # copy esi+ecx+12 to eax 46 89/copy 1/mod/*+disp8 7/rm32/edi . . . 0/r32/eax 4/disp8 . # copy eax to *(edi+4) 47 # . restore registers 48 5f/pop-to-edi 49 5e/pop-to-esi 50 59/pop-to-ecx 51 58/pop-to-eax 52 # . epilogue 53 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 54 5d/pop-to-ebp 55 c3/return 56 57 test-next-token: 58 # . prologue 59 55/push-ebp 60 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 61 # setup 62 # . clear-stream(_test-stream) 63 # . . push args 64 68/push _test-stream/imm32 65 # . . call 66 e8/call clear-stream/disp32 67 # . . discard args 68 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 69 # var slice/ecx: slice 70 68/push 0/imm32/end 71 68/push 0/imm32/start 72 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 73 # write(_test-stream, " ab") 74 # . . push args 75 68/push " ab"/imm32 76 68/push _test-stream/imm32 77 # . . call 78 e8/call write/disp32 79 # . . discard args 80 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 81 # next-token(_test-stream, 0x20/space, slice) 82 # . . push args 83 51/push-ecx 84 68/push 0x20/imm32 85 68/push _test-stream/imm32 86 # . . call 87 e8/call next-token/disp32 88 # . . discard args 89 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 90 # check-ints-equal(slice->start - _test-stream->data, 2, msg) 91 # . check-ints-equal(slice->start - _test-stream, 14, msg) 92 # . . push args 93 68/push "F - test-next-token: start"/imm32 94 68/push 0xe/imm32 95 # . . push slice->start - _test-stream 96 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax 97 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-stream/imm32 # subtract from eax 98 50/push-eax 99 # . . call 100 e8/call check-ints-equal/disp32 101 # . . discard args 102 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 103 # check-ints-equal(slice->end - _test-stream->data, 4, msg) 104 # . check-ints-equal(slice->end - _test-stream, 16, msg) 105 # . . push args 106 68/push "F - test-next-token: end"/imm32 107 68/push 0x10/imm32 108 # . . push slice->end - _test-stream 109 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax 110 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-stream/imm32 # subtract from eax 111 50/push-eax 112 # . . call 113 e8/call check-ints-equal/disp32 114 # . . discard args 115 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 116 # . epilogue 117 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 118 5d/pop-to-ebp 119 c3/return 120 121 test-next-token-Eof: 122 # . prologue 123 55/push-ebp 124 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 125 # setup 126 # . clear-stream(_test-stream) 127 # . . push args 128 68/push _test-stream/imm32 129 # . . call 130 e8/call clear-stream/disp32 131 # . . discard args 132 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 133 # var slice/ecx: slice 134 68/push 0/imm32/end 135 68/push 0/imm32/start 136 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 137 # write nothing to _test-stream 138 # next-token(_test-stream, 0x20/space, slice) 139 # . . push args 140 51/push-ecx 141 68/push 0x20/imm32 142 68/push _test-stream/imm32 143 # . . call 144 e8/call next-token/disp32 145 # . . discard args 146 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 147 # check-ints-equal(slice->end, slice->start, msg) 148 # . . push args 149 68/push "F - test-next-token-Eof"/imm32 150 ff 6/subop/push 1/mod/*+disp8 1/rm32/ecx . . . . 4/disp8 . # push *(ecx+4) 151 ff 6/subop/push 0/mod/indirect 1/rm32/ecx . . . . . . # push *ecx 152 # . . call 153 e8/call check-ints-equal/disp32 154 # . . discard args 155 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 156 # . epilogue 157 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 158 5d/pop-to-ebp 159 c3/return 160 161 # extract the next run of characters that are different from a given 'delimiter' (skipping multiple delimiters if necessary) 162 # on reaching end of file, return an empty interval 163 next-token-from-slice: # start: (addr byte), end: (addr byte), delimiter: byte, out: (addr slice) 164 # . prologue 165 55/push-ebp 166 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 167 # . save registers 168 50/push-eax 169 51/push-ecx 170 52/push-edx 171 57/push-edi 172 # ecx = end 173 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx 174 # edx = delimiter 175 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0x10/disp8 . # copy *(ebp+16) to edx 176 # edi = out 177 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0x14/disp8 . # copy *(ebp+20) to edi 178 # eax = skip-chars-matching-in-slice(start, end, delimiter) 179 # . . push args 180 52/push-edx 181 51/push-ecx 182 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 183 # . . call 184 e8/call skip-chars-matching-in-slice/disp32 185 # . . discard args 186 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 187 # out->start = eax 188 89/copy 0/mod/indirect 7/rm32/edi . . . 0/r32/eax . . # copy eax to *edi 189 # eax = skip-chars-not-matching-in-slice(eax, end, delimiter) 190 # . . push args 191 52/push-edx 192 51/push-ecx 193 50/push-eax 194 # . . call 195 e8/call skip-chars-not-matching-in-slice/disp32 196 # . . discard args 197 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 198 # out->end = eax 199 89/copy 1/mod/*+disp8 7/rm32/edi . . . 0/r32/eax 4/disp8 . # copy eax to *(edi+4) 200 # . restore registers 201 5f/pop-to-edi 202 5a/pop-to-edx 203 59/pop-to-ecx 204 58/pop-to-eax 205 # . epilogue 206 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 207 5d/pop-to-ebp 208 c3/return 209 210 test-next-token-from-slice: 211 # . prologue 212 55/push-ebp 213 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 214 # (eax..ecx) = " ab" 215 b8/copy-to-eax " ab"/imm32 216 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 217 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 218 05/add-to-eax 4/imm32 219 # var out/edi: slice 220 68/push 0/imm32/end 221 68/push 0/imm32/start 222 89/copy 3/mod/direct 7/rm32/edi . . . 4/r32/esp . . # copy esp to edi 223 # next-token-from-slice(eax, ecx, 0x20/space, out) 224 # . . push args 225 57/push-edi 226 68/push 0x20/imm32 227 51/push-ecx 228 50/push-eax 229 # . . call 230 e8/call next-token-from-slice/disp32 231 # . . discard args 232 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp 233 # out->start should be at the 'a' 234 # . check-ints-equal(out->start - in->start, 2, msg) 235 # . . push args 236 68/push "F - test-next-token-from-slice: start"/imm32 237 68/push 2/imm32 238 # . . push out->start - in->start 239 8b/copy 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # copy *edi to ecx 240 2b/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract eax from ecx 241 51/push-ecx 242 # . . call 243 e8/call check-ints-equal/disp32 244 # . . discard args 245 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 246 # out->end should be after the 'b' 247 # check-ints-equal(out->end - in->start, 4, msg) 248 # . . push args 249 68/push "F - test-next-token-from-slice: end"/imm32 250 68/push 4/imm32 251 # . . push out->end - in->start 252 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 4/disp8 . # copy *(edi+4) to ecx 253 2b/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract eax from ecx 254 51/push-ecx 255 # . . call 256 e8/call check-ints-equal/disp32 257 # . . discard args 258 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 259 # . epilogue 260 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 261 5d/pop-to-ebp 262 c3/return 263 264 test-next-token-from-slice-Eof: 265 # . prologue 266 55/push-ebp 267 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 268 # var out/edi: slice 269 68/push 0/imm32/end 270 68/push 0/imm32/start 271 89/copy 3/mod/direct 7/rm32/edi . . . 4/r32/esp . . # copy esp to edi 272 # next-token-from-slice(0, 0, 0x20/space, out) 273 # . . push args 274 57/push-edi 275 68/push 0x20/imm32 276 68/push 0/imm32 277 68/push 0/imm32 278 # . . call 279 e8/call next-token-from-slice/disp32 280 # . . discard args 281 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp 282 # out should be empty 283 # . check-ints-equal(out->end - out->start, 0, msg) 284 # . . push args 285 68/push "F - test-next-token-from-slice-Eof"/imm32 286 68/push 0/imm32 287 # . . push out->start - in->start 288 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 4/disp8 . # copy *(edi+4) to ecx 289 2b/subtract 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # subtract *edi from ecx 290 51/push-ecx 291 # . . call 292 e8/call check-ints-equal/disp32 293 # . . discard args 294 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 295 # . epilogue 296 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 297 5d/pop-to-ebp 298 c3/return 299 300 test-next-token-from-slice-nothing: 301 # . prologue 302 55/push-ebp 303 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 304 # (eax..ecx) = " " 305 b8/copy-to-eax " "/imm32 306 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 307 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 308 05/add-to-eax 4/imm32 309 # var out/edi: slice 310 68/push 0/imm32/end 311 68/push 0/imm32/start 312 89/copy 3/mod/direct 7/rm32/edi . . . 4/r32/esp . . # copy esp to edi 313 # next-token-from-slice(in, 0x20/space, out) 314 # . . push args 315 57/push-edi 316 68/push 0x20/imm32 317 51/push-ecx 318 50/push-eax 319 # . . call 320 e8/call next-token-from-slice/disp32 321 # . . discard args 322 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp 323 # out should be empty 324 # . check-ints-equal(out->end - out->start, 0, msg) 325 # . . push args 326 68/push "F - test-next-token-from-slice-Eof"/imm32 327 68/push 0/imm32 328 # . . push out->start - in->start 329 8b/copy 1/mod/*+disp8 7/rm32/edi . . . 1/r32/ecx 4/disp8 . # copy *(edi+4) to ecx 330 2b/subtract 0/mod/indirect 7/rm32/edi . . . 1/r32/ecx . . # subtract *edi from ecx 331 51/push-ecx 332 # . . call 333 e8/call check-ints-equal/disp32 334 # . . discard args 335 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 336 # . epilogue 337 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 338 5d/pop-to-ebp 339 c3/return 340 341 skip-chars-matching: # in: (addr stream byte), delimiter: byte 342 # . prologue 343 55/push-ebp 344 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 345 # . save registers 346 50/push-eax 347 51/push-ecx 348 52/push-edx 349 53/push-ebx 350 56/push-esi 351 # esi = in 352 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi 353 # ecx = in->read 354 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx 355 # ebx = in->write 356 8b/copy 0/mod/indirect 6/rm32/esi . . . 3/r32/ebx . . # copy *esi to ebx 357 # edx = delimiter 358 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx 359 $skip-chars-matching:loop: 360 # if (in->read >= in->write) break 361 39/compare 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx . . # compare ecx with ebx 362 7d/jump-if->= $skip-chars-matching:end/disp8 363 # eax = in->data[in->read] 364 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 365 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL 366 # if (eax != delimiter) break 367 39/compare 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # compare eax and edx 368 75/jump-if-!= $skip-chars-matching:end/disp8 369 # ++in->read 370 41/increment-ecx 371 eb/jump $skip-chars-matching:loop/disp8 372 $skip-chars-matching:end: 373 # persist in->read 374 89/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy ecx to *(esi+4) 375 # . restore registers 376 5e/pop-to-esi 377 5b/pop-to-ebx 378 5a/pop-to-edx 379 59/pop-to-ecx 380 58/pop-to-eax 381 # . epilogue 382 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 383 5d/pop-to-ebp 384 c3/return 385 386 test-skip-chars-matching: 387 # setup 388 # . clear-stream(_test-stream) 389 # . . push args 390 68/push _test-stream/imm32 391 # . . call 392 e8/call clear-stream/disp32 393 # . . discard args 394 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 395 # write(_test-stream, " ab") 396 # . . push args 397 68/push " ab"/imm32 398 68/push _test-stream/imm32 399 # . . call 400 e8/call write/disp32 401 # . . discard args 402 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 403 # skip-chars-matching(_test-stream, 0x20/space) 404 # . . push args 405 68/push 0x20/imm32 406 68/push _test-stream/imm32 407 # . . call 408 e8/call skip-chars-matching/disp32 409 # . . discard args 410 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 411 # check-ints-equal(_test-stream->read, 2, msg) 412 # . . push args 413 68/push "F - test-skip-chars-matching"/imm32 414 68/push 2/imm32 415 # . . push *_test-stream->read 416 b8/copy-to-eax _test-stream/imm32 417 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) 418 # . . call 419 e8/call check-ints-equal/disp32 420 # . . discard args 421 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 422 # end 423 c3/return 424 425 test-skip-chars-matching-none: 426 # setup 427 # . clear-stream(_test-stream) 428 # . . push args 429 68/push _test-stream/imm32 430 # . . call 431 e8/call clear-stream/disp32 432 # . . discard args 433 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 434 # write(_test-stream, "ab") 435 # . . push args 436 68/push "ab"/imm32 437 68/push _test-stream/imm32 438 # . . call 439 e8/call write/disp32 440 # . . discard args 441 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 442 # skip-chars-matching(_test-stream, 0x20/space) 443 # . . push args 444 68/push 0x20/imm32 445 68/push _test-stream/imm32 446 # . . call 447 e8/call skip-chars-matching/disp32 448 # . . discard args 449 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 450 # check-ints-equal(_test-stream->read, 0, msg) 451 # . . push args 452 68/push "F - test-skip-chars-matching-none"/imm32 453 68/push 0/imm32 454 # . . push *_test-stream->read 455 b8/copy-to-eax _test-stream/imm32 456 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) 457 # . . call 458 e8/call check-ints-equal/disp32 459 # . . discard args 460 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 461 # end 462 c3/return 463 464 skip-chars-matching-whitespace: # in: (addr stream byte) 465 # . prologue 466 55/push-ebp 467 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 468 # . save registers 469 50/push-eax 470 51/push-ecx 471 53/push-ebx 472 56/push-esi 473 # esi = in 474 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi 475 # ecx = in->read 476 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx 477 # ebx = in->write 478 8b/copy 0/mod/indirect 6/rm32/esi . . . 3/r32/ebx . . # copy *esi to ebx 479 $skip-chars-matching-whitespace:loop: 480 # if (in->read >= in->write) break 481 39/compare 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx . . # compare ecx with ebx 482 7d/jump-if->= $skip-chars-matching-whitespace:end/disp8 483 # eax = in->data[in->read] 484 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 485 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL 486 # if (eax == ' ') goto body 487 3d/compare-eax-and 0x20/imm32/space 488 74/jump-if-= $skip-chars-matching-whitespace:body/disp8 489 # if (eax == '\n') goto body 490 3d/compare-eax-and 0x0a/imm32/newline 491 74/jump-if-= $skip-chars-matching-whitespace:body/disp8 492 # if (eax == '\t') goto body 493 3d/compare-eax-and 0x09/imm32/tab 494 74/jump-if-= $skip-chars-matching-whitespace:body/disp8 495 # if (eax != '\r') break 496 3d/compare-eax-and 0x0d/imm32/cr 497 75/jump-if-!= $skip-chars-matching-whitespace:end/disp8 498 $skip-chars-matching-whitespace:body: 499 # ++in->read 500 41/increment-ecx 501 eb/jump $skip-chars-matching-whitespace:loop/disp8 502 $skip-chars-matching-whitespace:end: 503 # persist in->read 504 89/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy ecx to *(esi+4) 505 # . restore registers 506 5e/pop-to-esi 507 5b/pop-to-ebx 508 59/pop-to-ecx 509 58/pop-to-eax 510 # . epilogue 511 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 512 5d/pop-to-ebp 513 c3/return 514 515 test-skip-chars-matching-whitespace: 516 # setup 517 # . clear-stream(_test-stream) 518 # . . push args 519 68/push _test-stream/imm32 520 # . . call 521 e8/call clear-stream/disp32 522 # . . discard args 523 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 524 # write(_test-stream, " \nab") 525 # . . push args 526 68/push " \nab"/imm32 527 68/push _test-stream/imm32 528 # . . call 529 e8/call write/disp32 530 # . . discard args 531 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 532 # skip-chars-matching-whitespace(_test-stream) 533 # . . push args 534 68/push _test-stream/imm32 535 # . . call 536 e8/call skip-chars-matching-whitespace/disp32 537 # . . discard args 538 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 539 # check-ints-equal(_test-stream->read, 2, msg) 540 # . . push args 541 68/push "F - test-skip-chars-matching-whitespace"/imm32 542 68/push 2/imm32 543 # . . push *_test-stream->read 544 b8/copy-to-eax _test-stream/imm32 545 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) 546 # . . call 547 e8/call check-ints-equal/disp32 548 # . . discard args 549 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 550 # end 551 c3/return 552 553 # minor fork of 'skip-chars-matching' 554 skip-chars-not-matching: # in: (addr stream byte), delimiter: byte 555 # . prologue 556 55/push-ebp 557 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 558 # . save registers 559 50/push-eax 560 51/push-ecx 561 52/push-edx 562 53/push-ebx 563 56/push-esi 564 # esi = in 565 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi 566 # ecx = in->read 567 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx 568 # ebx = in->write 569 8b/copy 0/mod/indirect 6/rm32/esi . . . 3/r32/ebx . . # copy *esi to ebx 570 # edx = delimiter 571 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx 572 $skip-chars-not-matching:loop: 573 # if (in->read >= in->write) break 574 39/compare 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx . . # compare ecx with ebx 575 7d/jump-if->= $skip-chars-not-matching:end/disp8 576 # eax = in->data[in->read] 577 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 578 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL 579 # if (eax == delimiter) break 580 39/compare 3/mod/direct 0/rm32/eax . . . 2/r32/edx . . # compare eax and edx 581 74/jump-if-= $skip-chars-not-matching:end/disp8 582 # ++in->read 583 41/increment-ecx 584 eb/jump $skip-chars-not-matching:loop/disp8 585 $skip-chars-not-matching:end: 586 # persist in->read 587 89/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy ecx to *(esi+4) 588 # . restore registers 589 5e/pop-to-esi 590 5b/pop-to-ebx 591 5a/pop-to-edx 592 59/pop-to-ecx 593 58/pop-to-eax 594 # . epilogue 595 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 596 5d/pop-to-ebp 597 c3/return 598 599 test-skip-chars-not-matching: 600 # setup 601 # . clear-stream(_test-stream) 602 # . . push args 603 68/push _test-stream/imm32 604 # . . call 605 e8/call clear-stream/disp32 606 # . . discard args 607 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 608 # write(_test-stream, "ab ") 609 # . . push args 610 68/push "ab "/imm32 611 68/push _test-stream/imm32 612 # . . call 613 e8/call write/disp32 614 # . . discard args 615 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 616 # skip-chars-not-matching(_test-stream, 0x20/space) 617 # . . push args 618 68/push 0x20/imm32 619 68/push _test-stream/imm32 620 # . . call 621 e8/call skip-chars-not-matching/disp32 622 # . . discard args 623 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 624 # check-ints-equal(_test-stream->read, 2, msg) 625 # . . push args 626 68/push "F - test-skip-chars-not-matching"/imm32 627 68/push 2/imm32 628 # . . push *_test-stream->read 629 b8/copy-to-eax _test-stream/imm32 630 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) 631 # . . call 632 e8/call check-ints-equal/disp32 633 # . . discard args 634 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 635 # end 636 c3/return 637 638 test-skip-chars-not-matching-none: 639 # setup 640 # . clear-stream(_test-stream) 641 # . . push args 642 68/push _test-stream/imm32 643 # . . call 644 e8/call clear-stream/disp32 645 # . . discard args 646 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 647 # write(_test-stream, " ab") 648 # . . push args 649 68/push " ab"/imm32 650 68/push _test-stream/imm32 651 # . . call 652 e8/call write/disp32 653 # . . discard args 654 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 655 # skip-chars-not-matching(_test-stream, 0x20/space) 656 # . . push args 657 68/push 0x20/imm32 658 68/push _test-stream/imm32 659 # . . call 660 e8/call skip-chars-not-matching/disp32 661 # . . discard args 662 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 663 # check-ints-equal(_test-stream->read, 0, msg) 664 # . . push args 665 68/push "F - test-skip-chars-not-matching-none"/imm32 666 68/push 0/imm32 667 # . . push *_test-stream->read 668 b8/copy-to-eax _test-stream/imm32 669 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) 670 # . . call 671 e8/call check-ints-equal/disp32 672 # . . discard args 673 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 674 # end 675 c3/return 676 677 test-skip-chars-not-matching-all: 678 # setup 679 # . clear-stream(_test-stream) 680 # . . push args 681 68/push _test-stream/imm32 682 # . . call 683 e8/call clear-stream/disp32 684 # . . discard args 685 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 686 # write(_test-stream, "ab") 687 # . . push args 688 68/push "ab"/imm32 689 68/push _test-stream/imm32 690 # . . call 691 e8/call write/disp32 692 # . . discard args 693 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 694 # skip-chars-not-matching(_test-stream, 0x20/space) 695 # . . push args 696 68/push 0x20/imm32 697 68/push _test-stream/imm32 698 # . . call 699 e8/call skip-chars-not-matching/disp32 700 # . . discard args 701 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 702 # check-ints-equal(_test-stream->read, 2, msg) 703 # . . push args 704 68/push "F - test-skip-chars-not-matching-all"/imm32 705 68/push 2/imm32 706 # . . push *_test-stream->read 707 b8/copy-to-eax _test-stream/imm32 708 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) 709 # . . call 710 e8/call check-ints-equal/disp32 711 # . . discard args 712 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 713 # end 714 c3/return 715 716 skip-chars-not-matching-whitespace: # in: (addr stream byte) 717 # . prologue 718 55/push-ebp 719 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 720 # . save registers 721 50/push-eax 722 51/push-ecx 723 53/push-ebx 724 56/push-esi 725 # esi = in 726 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi 727 # ecx = in->read 728 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx 729 # ebx = in->write 730 8b/copy 0/mod/indirect 6/rm32/esi . . . 3/r32/ebx . . # copy *esi to ebx 731 $skip-chars-not-matching-whitespace:loop: 732 # if (in->read >= in->write) break 733 39/compare 3/mod/direct 1/rm32/ecx . . . 3/r32/ebx . . # compare ecx with ebx 734 7d/jump-if->= $skip-chars-not-matching-whitespace:end/disp8 735 # eax = in->data[in->read] 736 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 737 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL 738 # if (eax == ' ') break 739 3d/compare-eax-and 0x20/imm32/space 740 74/jump-if-= $skip-chars-not-matching-whitespace:end/disp8 741 # if (eax == '\n') break 742 3d/compare-eax-and 0x0a/imm32/newline 743 74/jump-if-= $skip-chars-not-matching-whitespace:end/disp8 744 # if (eax == '\t') break 745 3d/compare-eax-and 0x09/imm32/tab 746 74/jump-if-= $skip-chars-not-matching-whitespace:end/disp8 747 # if (eax == '\r') break 748 3d/compare-eax-and 0x0d/imm32/cr 749 74/jump-if-= $skip-chars-not-matching-whitespace:end/disp8 750 # ++in->read 751 41/increment-ecx 752 eb/jump $skip-chars-not-matching-whitespace:loop/disp8 753 $skip-chars-not-matching-whitespace:end: 754 # persist in->read 755 89/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy ecx to *(esi+4) 756 # . restore registers 757 5e/pop-to-esi 758 5b/pop-to-ebx 759 59/pop-to-ecx 760 58/pop-to-eax 761 # . epilogue 762 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 763 5d/pop-to-ebp 764 c3/return 765 766 test-skip-chars-not-matching-whitespace: 767 # setup 768 # . clear-stream(_test-stream) 769 # . . push args 770 68/push _test-stream/imm32 771 # . . call 772 e8/call clear-stream/disp32 773 # . . discard args 774 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 775 # write(_test-stream, "ab\n") 776 # . . push args 777 68/push "ab\n"/imm32 778 68/push _test-stream/imm32 779 # . . call 780 e8/call write/disp32 781 # . . discard args 782 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 783 # skip-chars-not-matching-whitespace(_test-stream) 784 # . . push args 785 68/push _test-stream/imm32 786 # . . call 787 e8/call skip-chars-not-matching-whitespace/disp32 788 # . . discard args 789 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 790 # check-ints-equal(_test-stream->read, 2, msg) 791 # . . push args 792 68/push "F - test-skip-chars-not-matching-whitespace"/imm32 793 68/push 2/imm32 794 # . . push *_test-stream->read 795 b8/copy-to-eax _test-stream/imm32 796 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) 797 # . . call 798 e8/call check-ints-equal/disp32 799 # . . discard args 800 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 801 # end 802 c3/return 803 804 skip-chars-matching-in-slice: # curr: (addr byte), end: (addr byte), delimiter: byte -> curr/eax: (addr byte) 805 # . prologue 806 55/push-ebp 807 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 808 # . save registers 809 51/push-ecx 810 52/push-edx 811 53/push-ebx 812 # eax = curr 813 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax 814 # ecx = end 815 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx 816 # edx = delimiter 817 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0x10/disp8 . # copy *(ebp+16) to edx 818 # var c/ebx: byte = 0 819 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx 820 $skip-chars-matching-in-slice:loop: 821 # if (curr >= end) break 822 39/compare 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # compare eax with ecx 823 73/jump-if-addr>= $skip-chars-matching-in-slice:end/disp8 824 # c = *curr 825 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 3/r32/BL . . # copy byte at *eax to BL 826 # if (c != delimiter) break 827 39/compare 3/mod/direct 3/rm32/ebx . . . 2/r32/edx . . # compare ebx and edx 828 75/jump-if-!= $skip-chars-matching-in-slice:end/disp8 829 # ++curr 830 40/increment-eax 831 eb/jump $skip-chars-matching-in-slice:loop/disp8 832 $skip-chars-matching-in-slice:end: 833 # . restore registers 834 5b/pop-to-ebx 835 5a/pop-to-edx 836 59/pop-to-ecx 837 # . epilogue 838 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 839 5d/pop-to-ebp 840 c3/return 841 842 test-skip-chars-matching-in-slice: 843 # (eax..ecx) = " ab" 844 b8/copy-to-eax " ab"/imm32 845 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 846 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 847 05/add-to-eax 4/imm32 848 # eax = skip-chars-matching-in-slice(eax, ecx, 0x20/space) 849 # . . push args 850 68/push 0x20/imm32/space 851 51/push-ecx 852 50/push-eax 853 # . . call 854 e8/call skip-chars-matching-in-slice/disp32 855 # . . discard args 856 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 857 # check-ints-equal(ecx-eax, 2, msg) 858 # . . push args 859 68/push "F - test-skip-chars-matching-in-slice"/imm32 860 68/push 2/imm32 861 # . . push ecx-eax 862 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx 863 51/push-ecx 864 # . . call 865 e8/call check-ints-equal/disp32 866 # . . discard args 867 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 868 # end 869 c3/return 870 871 test-skip-chars-matching-in-slice-none: 872 # (eax..ecx) = "ab" 873 b8/copy-to-eax "ab"/imm32 874 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 875 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 876 05/add-to-eax 4/imm32 877 # eax = skip-chars-matching-in-slice(eax, ecx, 0x20/space) 878 # . . push args 879 68/push 0x20/imm32/space 880 51/push-ecx 881 50/push-eax 882 # . . call 883 e8/call skip-chars-matching-in-slice/disp32 884 # . . discard args 885 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 886 # check-ints-equal(ecx-eax, 2, msg) 887 # . . push args 888 68/push "F - test-skip-chars-matching-in-slice-none"/imm32 889 68/push 2/imm32 890 # . . push ecx-eax 891 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx 892 51/push-ecx 893 # . . call 894 e8/call check-ints-equal/disp32 895 # . . discard args 896 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 897 # end 898 c3/return 899 900 skip-chars-matching-whitespace-in-slice: # curr: (addr byte), end: (addr byte) -> curr/eax: (addr byte) 901 # . prologue 902 55/push-ebp 903 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 904 # . save registers 905 51/push-ecx 906 53/push-ebx 907 # eax = curr 908 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax 909 # ecx = end 910 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx 911 # var c/ebx: byte = 0 912 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx 913 $skip-chars-matching-whitespace-in-slice:loop: 914 # if (curr >= end) break 915 39/compare 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # compare eax with ecx 916 0f 83/jump-if-addr>= $skip-chars-matching-in-slice:end/disp32 917 # c = *curr 918 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 3/r32/BL . . # copy byte at *eax to BL 919 # if (c == ' ') goto body 920 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x20/imm32/space # compare ebx 921 74/jump-if-= $skip-chars-matching-whitespace-in-slice:body/disp8 922 # if (c == '\n') goto body 923 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x0a/imm32/newline # compare ebx 924 74/jump-if-= $skip-chars-matching-whitespace-in-slice:body/disp8 925 # if (c == '\t') goto body 926 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x09/imm32/tab # compare ebx 927 74/jump-if-= $skip-chars-matching-whitespace-in-slice:body/disp8 928 # if (c != '\r') break 929 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x0d/imm32/cr # compare ebx 930 75/jump-if-!= $skip-chars-matching-whitespace-in-slice:end/disp8 931 $skip-chars-matching-whitespace-in-slice:body: 932 # ++curr 933 40/increment-eax 934 eb/jump $skip-chars-matching-whitespace-in-slice:loop/disp8 935 $skip-chars-matching-whitespace-in-slice:end: 936 # . restore registers 937 5b/pop-to-ebx 938 59/pop-to-ecx 939 # . epilogue 940 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 941 5d/pop-to-ebp 942 c3/return 943 944 test-skip-chars-matching-whitespace-in-slice: 945 # (eax..ecx) = " \nab" 946 b8/copy-to-eax " \nab"/imm32 947 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 948 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 949 05/add-to-eax 4/imm32 950 # eax = skip-chars-matching-whitespace-in-slice(eax, ecx) 951 # . . push args 952 51/push-ecx 953 50/push-eax 954 # . . call 955 e8/call skip-chars-matching-whitespace-in-slice/disp32 956 # . . discard args 957 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 958 # check-ints-equal(ecx-eax, 2, msg) 959 # . . push args 960 68/push "F - test-skip-chars-matching-whitespace-in-slice"/imm32 961 68/push 2/imm32 962 # . . push ecx-eax 963 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx 964 51/push-ecx 965 # . . call 966 e8/call check-ints-equal/disp32 967 # . . discard args 968 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 969 # end 970 c3/return 971 972 # minor fork of 'skip-chars-matching-in-slice' 973 skip-chars-not-matching-in-slice: # curr: (addr byte), end: (addr byte), delimiter: byte -> curr/eax: (addr byte) 974 # . prologue 975 55/push-ebp 976 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 977 # . save registers 978 51/push-ecx 979 52/push-edx 980 53/push-ebx 981 # eax = curr 982 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax 983 # ecx = end 984 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx 985 # edx = delimiter 986 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 2/r32/edx 0x10/disp8 . # copy *(ebp+16) to edx 987 # var c/ebx: byte = 0 988 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx 989 $skip-chars-not-matching-in-slice:loop: 990 # if (curr >= end) break 991 39/compare 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # compare eax with ecx 992 73/jump-if-addr>= $skip-chars-not-matching-in-slice:end/disp8 993 # c = *curr 994 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 3/r32/BL . . # copy byte at *eax to BL 995 # if (c == delimiter) break 996 39/compare 3/mod/direct 3/rm32/ebx . . . 2/r32/edx . . # compare ebx and edx 997 74/jump-if-= $skip-chars-not-matching-in-slice:end/disp8 998 # ++curr 999 40/increment-eax 1000 eb/jump $skip-chars-not-matching-in-slice:loop/disp8 1001 $skip-chars-not-matching-in-slice:end: 1002 # . restore registers 1003 5b/pop-to-ebx 1004 5a/pop-to-edx 1005 59/pop-to-ecx 1006 # . epilogue 1007 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1008 5d/pop-to-ebp 1009 c3/return 1010 1011 test-skip-chars-not-matching-in-slice: 1012 # (eax..ecx) = "ab " 1013 b8/copy-to-eax "ab "/imm32 1014 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 1015 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 1016 05/add-to-eax 4/imm32 1017 # eax = skip-chars-not-matching-in-slice(eax, ecx, 0x20/space) 1018 # . . push args 1019 68/push 0x20/imm32/space 1020 51/push-ecx 1021 50/push-eax 1022 # . . call 1023 e8/call skip-chars-not-matching-in-slice/disp32 1024 # . . discard args 1025 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1026 # check-ints-equal(ecx-eax, 1, msg) 1027 # . . push args 1028 68/push "F - test-skip-chars-not-matching-in-slice"/imm32 1029 68/push 1/imm32 1030 # . . push ecx-eax 1031 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx 1032 51/push-ecx 1033 # . . call 1034 e8/call check-ints-equal/disp32 1035 # . . discard args 1036 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1037 # end 1038 c3/return 1039 1040 test-skip-chars-not-matching-in-slice-none: 1041 # (eax..ecx) = " ab" 1042 b8/copy-to-eax " ab"/imm32 1043 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 1044 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 1045 05/add-to-eax 4/imm32 1046 # eax = skip-chars-not-matching-in-slice(eax, ecx, 0x20/space) 1047 # . . push args 1048 68/push 0x20/imm32/space 1049 51/push-ecx 1050 50/push-eax 1051 # . . call 1052 e8/call skip-chars-not-matching-in-slice/disp32 1053 # . . discard args 1054 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1055 # check-ints-equal(ecx-eax, 3, msg) 1056 # . . push args 1057 68/push "F - test-skip-chars-not-matching-in-slice-none"/imm32 1058 68/push 3/imm32 1059 # . . push ecx-eax 1060 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx 1061 51/push-ecx 1062 # . . call 1063 e8/call check-ints-equal/disp32 1064 # . . discard args 1065 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1066 # end 1067 c3/return 1068 1069 test-skip-chars-not-matching-in-slice-all: 1070 # (eax..ecx) = "ab" 1071 b8/copy-to-eax "ab"/imm32 1072 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 1073 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 1074 05/add-to-eax 4/imm32 1075 # eax = skip-chars-not-matching-in-slice(eax, ecx, 0x20/space) 1076 # . . push args 1077 68/push 0x20/imm32/space 1078 51/push-ecx 1079 50/push-eax 1080 # . . call 1081 e8/call skip-chars-not-matching-in-slice/disp32 1082 # . . discard args 1083 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1084 # check-ints-equal(ecx-eax, 0, msg) 1085 # . . push args 1086 68/push "F - test-skip-chars-not-matching-in-slice-all"/imm32 1087 68/push 0/imm32 1088 # . . push ecx-eax 1089 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx 1090 51/push-ecx 1091 # . . call 1092 e8/call check-ints-equal/disp32 1093 # . . discard args 1094 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1095 # end 1096 c3/return 1097 1098 skip-chars-not-matching-whitespace-in-slice: # curr: (addr byte), end: (addr byte) -> curr/eax: (addr byte) 1099 # . prologue 1100 55/push-ebp 1101 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1102 # . save registers 1103 51/push-ecx 1104 53/push-ebx 1105 # eax = curr 1106 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax 1107 # ecx = end 1108 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 0xc/disp8 . # copy *(ebp+12) to ecx 1109 # var c/ebx: byte = 0 1110 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx 1111 $skip-chars-not-matching-whitespace-in-slice:loop: 1112 # if (curr >= end) break 1113 39/compare 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # compare eax with ecx 1114 0f 83/jump-if-addr>= $skip-chars-not-matching-in-slice:end/disp32 1115 # c = *curr 1116 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 3/r32/BL . . # copy byte at *eax to BL 1117 # if (c == ' ') break 1118 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x20/imm32/space # compare ebx 1119 74/jump-if-= $skip-chars-not-matching-whitespace-in-slice:end/disp8 1120 # if (c == '\n') break 1121 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x0a/imm32/newline # compare ebx 1122 74/jump-if-= $skip-chars-not-matching-whitespace-in-slice:end/disp8 1123 # if (c == '\t') break 1124 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x09/imm32/tab # compare ebx 1125 74/jump-if-= $skip-chars-not-matching-whitespace-in-slice:end/disp8 1126 # if (c == '\r') break 1127 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0x0d/imm32/cr # compare ebx 1128 74/jump-if-= $skip-chars-not-matching-whitespace-in-slice:end/disp8 1129 # ++curr 1130 40/increment-eax 1131 eb/jump $skip-chars-not-matching-whitespace-in-slice:loop/disp8 1132 $skip-chars-not-matching-whitespace-in-slice:end: 1133 # . restore registers 1134 5b/pop-to-ebx 1135 59/pop-to-ecx 1136 # . epilogue 1137 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1138 5d/pop-to-ebp 1139 c3/return 1140 1141 test-skip-chars-not-matching-whitespace-in-slice: 1142 # (eax..ecx) = "ab\n" 1143 b8/copy-to-eax "ab\n"/imm32 1144 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 1145 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 1146 05/add-to-eax 4/imm32 1147 # eax = skip-chars-not-matching-whitespace-in-slice(eax, ecx) 1148 # . . push args 1149 51/push-ecx 1150 50/push-eax 1151 # . . call 1152 e8/call skip-chars-not-matching-whitespace-in-slice/disp32 1153 # . . discard args 1154 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1155 # check-ints-equal(ecx-eax, 1, msg) 1156 # . . push args 1157 68/push "F - test-skip-chars-not-matching-whitespace-in-slice"/imm32 1158 68/push 1/imm32 1159 # . . push ecx-eax 1160 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx 1161 51/push-ecx 1162 # . . call 1163 e8/call check-ints-equal/disp32 1164 # . . discard args 1165 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1166 # end 1167 c3/return 1168 1169 # update line->read to end of string literal surrounded by double quotes 1170 # line->read must start out at a double-quote 1171 skip-string: # line: (addr stream byte) 1172 # . prologue 1173 55/push-ebp 1174 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1175 # . save registers 1176 50/push-eax 1177 51/push-ecx 1178 52/push-edx 1179 # ecx = line 1180 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx 1181 # eax = skip-string-in-slice(&line->data[line->read], &line->data[line->write]) 1182 # . . push &line->data[line->write] 1183 8b/copy 1/mod/*+disp8 1/rm32/ecx . . 2/r32/edx 8/disp8 . # copy *(ecx+8) to edx 1184 8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx 0xc/disp8 . # copy ecx+edx+12 to edx 1185 52/push-edx 1186 # . . push &line->data[line->read] 1187 8b/copy 1/mod/*+disp8 1/rm32/ecx . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx 1188 8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx 0xc/disp8 . # copy ecx+edx+12 to edx 1189 52/push-edx 1190 # . . call 1191 e8/call skip-string-in-slice/disp32 1192 # . . discard args 1193 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1194 # line->read = eax - line->data 1195 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax 1196 2d/subtract-from-eax 0xc/imm32 1197 89/copy 1/mod/*+disp8 1/rm32/ecx . . 0/r32/eax 4/disp8 . # copy eax to *(ecx+4) 1198 $skip-string:end: 1199 # . restore registers 1200 5a/pop-to-edx 1201 59/pop-to-ecx 1202 58/pop-to-eax 1203 # . epilogue 1204 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1205 5d/pop-to-ebp 1206 c3/return 1207 1208 test-skip-string: 1209 # . prologue 1210 55/push-ebp 1211 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1212 # setup 1213 # . clear-stream(_test-input-stream) 1214 # . . push args 1215 68/push _test-input-stream/imm32 1216 # . . call 1217 e8/call clear-stream/disp32 1218 # . . discard args 1219 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1220 # . write(_test-input-stream, "\"abc\" def") 1221 # . indices: 0123 45 1222 # . . push args 1223 68/push "\"abc\" def"/imm32 1224 68/push _test-input-stream/imm32 1225 # . . call 1226 e8/call write/disp32 1227 # . . discard args 1228 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1229 # precondition: line->read == 0 1230 # . . push args 1231 68/push "F - test-skip-string/precondition"/imm32 1232 68/push 0/imm32 1233 b8/copy-to-eax _test-input-stream/imm32 1234 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) 1235 # . . call 1236 e8/call check-ints-equal/disp32 1237 # . . discard args 1238 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1239 # skip-string(_test-input-stream) 1240 # . . push args 1241 68/push _test-input-stream/imm32 1242 # . . call 1243 e8/call skip-string/disp32 1244 # . . discard args 1245 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1246 # check-ints-equal(line->read, 5, msg) 1247 # . . push args 1248 68/push "F - test-skip-string"/imm32 1249 68/push 5/imm32 1250 b8/copy-to-eax _test-input-stream/imm32 1251 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) 1252 # . . call 1253 e8/call check-ints-equal/disp32 1254 # . . discard args 1255 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1256 # . epilogue 1257 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1258 5d/pop-to-ebp 1259 c3/return 1260 1261 test-skip-string-ignores-spaces: 1262 # . prologue 1263 55/push-ebp 1264 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1265 # setup 1266 # . clear-stream(_test-input-stream) 1267 # . . push args 1268 68/push _test-input-stream/imm32 1269 # . . call 1270 e8/call clear-stream/disp32 1271 # . . discard args 1272 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1273 # . write(_test-input-stream, "\"a b\"/yz") 1274 # . indices: 0123 45 1275 # . . push args 1276 68/push "\"a b\"/yz"/imm32 1277 68/push _test-input-stream/imm32 1278 # . . call 1279 e8/call write/disp32 1280 # . . discard args 1281 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1282 # precondition: line->read == 0 1283 # . . push args 1284 68/push "F - test-skip-string-ignores-spaces/precondition"/imm32 1285 68/push 0/imm32 1286 b8/copy-to-eax _test-input-stream/imm32 1287 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) 1288 # . . call 1289 e8/call check-ints-equal/disp32 1290 # . . discard args 1291 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1292 # skip-string(_test-input-stream) 1293 # . . push args 1294 68/push _test-input-stream/imm32 1295 # . . call 1296 e8/call skip-string/disp32 1297 # . . discard args 1298 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1299 # check-ints-equal(line->read, 5, msg) 1300 # . . push args 1301 68/push "F - test-skip-string-ignores-spaces"/imm32 1302 68/push 5/imm32 1303 b8/copy-to-eax _test-input-stream/imm32 1304 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) 1305 # . . call 1306 e8/call check-ints-equal/disp32 1307 # . . discard args 1308 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1309 # . epilogue 1310 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1311 5d/pop-to-ebp 1312 c3/return 1313 1314 test-skip-string-ignores-escapes: 1315 # . prologue 1316 55/push-ebp 1317 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1318 # setup 1319 # . clear-stream(_test-input-stream) 1320 # . . push args 1321 68/push _test-input-stream/imm32 1322 # . . call 1323 e8/call clear-stream/disp32 1324 # . . discard args 1325 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1326 # . write(_test-input-stream, "\"a\\\"b\"/yz") 1327 # . indices: 01 2 34 56 1328 # . . push args 1329 68/push "\"a\\\"b\"/yz"/imm32 1330 68/push _test-input-stream/imm32 1331 # . . call 1332 e8/call write/disp32 1333 # . . discard args 1334 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1335 # precondition: line->read == 0 1336 # . . push args 1337 68/push "F - test-skip-string-ignores-escapes/precondition"/imm32 1338 68/push 0/imm32 1339 b8/copy-to-eax _test-input-stream/imm32 1340 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) 1341 # . . call 1342 e8/call check-ints-equal/disp32 1343 # . . discard args 1344 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1345 # skip-string(_test-input-stream) 1346 # . . push args 1347 68/push _test-input-stream/imm32 1348 # . . call 1349 e8/call skip-string/disp32 1350 # . . discard args 1351 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1352 # check-ints-equal(line->read, 6, msg) 1353 # . . push args 1354 68/push "F - test-skip-string-ignores-escapes"/imm32 1355 68/push 6/imm32 1356 b8/copy-to-eax _test-input-stream/imm32 1357 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) 1358 # . . call 1359 e8/call check-ints-equal/disp32 1360 # . . discard args 1361 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1362 # . epilogue 1363 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1364 5d/pop-to-ebp 1365 c3/return 1366 1367 test-skip-string-works-from-mid-stream: 1368 # . prologue 1369 55/push-ebp 1370 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1371 # setup 1372 # . clear-stream(_test-input-stream) 1373 # . . push args 1374 68/push _test-input-stream/imm32 1375 # . . call 1376 e8/call clear-stream/disp32 1377 # . . discard args 1378 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1379 # . write(_test-input-stream, "0 \"a\\\"b\"/yz") 1380 # . indices: 01 2 34 56 1381 # . . push args 1382 68/push "0 \"a\\\"b\"/yz"/imm32 1383 68/push _test-input-stream/imm32 1384 # . . call 1385 e8/call write/disp32 1386 # . . discard args 1387 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1388 # precondition: line->read == 2 1389 b8/copy-to-eax _test-input-stream/imm32 1390 c7 0/subop/copy 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 2/imm32 # copy to *(eax+4) 1391 # skip-string(_test-input-stream) 1392 # . . push args 1393 68/push _test-input-stream/imm32 1394 # . . call 1395 e8/call skip-string/disp32 1396 # . . discard args 1397 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 1398 # check-ints-equal(line->read, 8, msg) 1399 # . . push args 1400 68/push "F - test-skip-string-works-from-mid-stream"/imm32 1401 68/push 8/imm32 1402 b8/copy-to-eax _test-input-stream/imm32 1403 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) 1404 # . . call 1405 e8/call check-ints-equal/disp32 1406 # . . discard args 1407 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1408 # . epilogue 1409 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1410 5d/pop-to-ebp 1411 c3/return 1412 1413 skip-string-in-slice: # curr: (addr byte), end: (addr byte) -> curr/eax: (addr byte) 1414 # . prologue 1415 55/push-ebp 1416 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1417 # . save registers 1418 51/push-ecx 1419 52/push-edx 1420 53/push-ebx 1421 # ecx = curr 1422 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx 1423 # edx = end 1424 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx 1425 # var c/eax: byte = 0 1426 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 1427 # skip initial dquote 1428 41/increment-ecx 1429 $skip-string-in-slice:loop: 1430 # if (curr >= end) return curr 1431 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx 1432 73/jump-if-addr>= $skip-string-in-slice:return-curr/disp8 1433 # c = *curr 1434 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL 1435 $skip-string-in-slice:dquote: 1436 # if (c == '"') break 1437 3d/compare-eax-and 0x22/imm32/double-quote 1438 74/jump-if-= $skip-string-in-slice:break/disp8 1439 $skip-string-in-slice:check-for-escape: 1440 # if (c == '\') escape next char 1441 3d/compare-eax-and 0x5c/imm32/backslash 1442 75/jump-if-!= $skip-string-in-slice:continue/disp8 1443 $skip-string-in-slice:escape: 1444 41/increment-ecx 1445 $skip-string-in-slice:continue: 1446 # ++curr 1447 41/increment-ecx 1448 eb/jump $skip-string-in-slice:loop/disp8 1449 $skip-string-in-slice:break: 1450 # skip final dquote 1451 41/increment-ecx 1452 $skip-string-in-slice:return-curr: 1453 # return curr 1454 89/copy 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to eax 1455 $skip-string-in-slice:end: 1456 # . restore registers 1457 5b/pop-to-ebx 1458 5a/pop-to-edx 1459 59/pop-to-ecx 1460 # . epilogue 1461 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1462 5d/pop-to-ebp 1463 c3/return 1464 1465 test-skip-string-in-slice: 1466 # . prologue 1467 55/push-ebp 1468 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1469 # setup: (eax..ecx) = "\"abc\" def" 1470 b8/copy-to-eax "\"abc\" def"/imm32 1471 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 1472 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 1473 05/add-to-eax 4/imm32 1474 # eax = skip-string-in-slice(eax, ecx) 1475 # . . push args 1476 51/push-ecx 1477 50/push-eax 1478 # . . call 1479 e8/call skip-string-in-slice/disp32 1480 # . . discard args 1481 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1482 # check-ints-equal(ecx-eax, 4, msg) # number of chars remaining after the string literal 1483 # . . push args 1484 68/push "F - test-skip-string-in-slice"/imm32 1485 68/push 4/imm32 1486 # . . push ecx-eax 1487 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx 1488 51/push-ecx 1489 # . . call 1490 e8/call check-ints-equal/disp32 1491 # . . discard args 1492 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1493 # . epilogue 1494 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1495 5d/pop-to-ebp 1496 c3/return 1497 1498 test-skip-string-in-slice-ignores-spaces: 1499 # . prologue 1500 55/push-ebp 1501 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1502 # setup: (eax..ecx) = "\"a b\"/yz" 1503 b8/copy-to-eax "\"a b\"/yz"/imm32 1504 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 1505 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 1506 05/add-to-eax 4/imm32 1507 # eax = skip-string-in-slice(eax, ecx) 1508 # . . push args 1509 51/push-ecx 1510 50/push-eax 1511 # . . call 1512 e8/call skip-string-in-slice/disp32 1513 # . . discard args 1514 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1515 # check-ints-equal(ecx-eax, 3, msg) # number of chars remaining after the string literal 1516 # . . push args 1517 68/push "F - test-skip-string-in-slice-ignores-spaces"/imm32 1518 68/push 3/imm32 1519 # . . push ecx-eax 1520 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx 1521 51/push-ecx 1522 # . . call 1523 e8/call check-ints-equal/disp32 1524 # . . discard args 1525 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 1526 # . epilogue 1527 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 1528 5d/pop-to-ebp 1529 c3/return 1530 1531 test-skip-string-in-slice-ignores-escapes: 1532 # . prologue 1533 55/push-ebp 1534 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 1535 # setup: (eax..ecx) = "\"a\\\"b\"/yz" 1536 b8/copy-to-eax "\"a\\\"b\"/yz"/imm32 1537 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 1538 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 1539 05/add-to-eax 4/imm32 1540 # eax = skip-string-in-slice(eax, ecx) 1541 # . . push args 1542 51/push-ecx 1543 50/push-eax 1544 # . . call 1545 e8/call skip-string-in-slice/disp32 1546 # . . discard args 1547 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 1548 # check-ints-equal(ecx-eax, 3, msg) # number of chars remaining after the string literal 1549 # . . push args 1550 68/push "F - test-skip-string-in-slice-ignores-escapes"/imm32 1551 68/push 3/imm32 1552 # . . push ecx-eax 1553 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecxpre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html><head><title>Python: module ranger.gui.widgets.console</title> </head><body bgcolor="#f0f0f8"> <table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading"> <tr bgcolor="#7799ee"> <td valign=bottom> <br> <font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="ranger.html"><font color="#ffffff">ranger</font></a>.<a href="ranger.gui.html"><font color="#ffffff">gui</font></a>.<a href="ranger.gui.widgets.html"><font color="#ffffff">widgets</font></a>.console</strong></big></big></font></td ><td align=right valign=bottom ><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/hut/ranger/ranger/gui/widgets/console.py">/home/hut/ranger/ranger/gui/widgets/console.py</a></font></td></tr></table> <p><tt>The <a href="#Console">Console</a> widget implements a vim-like console for entering<br> commands, searching and executing files.</tt></p> <p> <table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> <tr bgcolor="#aa55cc"> <td colspan=3 valign=bottom> <br> <font color="#ffffff" face="helvetica, arial"><big><strong>Modules</strong></big></font></td></tr> <tr><td bgcolor="#aa55cc"><tt> </tt></td><td> </td> <td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="ranger.defaults.commands.html">ranger.defaults.commands</a><br> </td><td width="25%" valign=top><a href="curses.html">curses</a><br> </td><td width="25%" valign=top><a href="ranger.html">ranger</a><br> </td><td width="25%" valign=top><a href="string.html">string</a><br> </td></tr></table></td></tr></table><p> <table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> <tr bgcolor="#ee77aa"> <td colspan=3 valign=bottom> <br> <font color="#ffffff" face="helvetica, arial"><big><strong>Classes</strong></big></font></td></tr> <tr><td bgcolor="#ee77aa"><tt> </tt></td><td> </td> <td width="100%"><dl> <dt><font face="helvetica, arial"><a href="ranger.gui.widgets.html#Widget">ranger.gui.widgets.Widget</a>(<a href="ranger.gui.displayable.html#Displayable">ranger.gui.displayable.Displayable</a>) </font></dt><dd> <dl> <dt><font face="helvetica, arial"><a href="ranger.gui.widgets.console.html#Console">Console</a> </font></dt><dd> <dl> <dt><font face="helvetica, arial"><a href="ranger.gui.widgets.console.html#ConsoleWithTab">ConsoleWithTab</a> </font></dt><dd> <dl> <dt><font face="helvetica, arial"><a href="ranger.gui.widgets.console.html#CommandConsole">CommandConsole</a> </font></dt><dd> <dl> <dt><font face="helvetica, arial"><a href="ranger.gui.widgets.console.html#QuickCommandConsole">QuickCommandConsole</a> </font></dt></dl> </dd> <dt><font face="helvetica, arial"><a href="ranger.gui.widgets.console.html#OpenConsole">OpenConsole</a> </font></dt><dt><font face="helvetica, arial"><a href="ranger.gui.widgets.console.html#QuickOpenConsole">QuickOpenConsole</a> </font></dt></dl> </dd> <dt><font face="helvetica, arial"><a href="ranger.gui.widgets.console.html#SearchConsole">SearchConsole</a> </font></dt></dl> </dd> </dl> </dd> </dl> <p> <table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section"> <tr bgcolor="#ffc8d8"> <td colspan=3 valign=bottom> <br> <font color="#000000" face="helvetica, arial"><a name="CommandConsole">class <strong>CommandConsole</strong></a>(<a href="ranger.gui.widgets.console.html#ConsoleWithTab">ConsoleWithTab</a>)</font></td></tr> <tr><td bgcolor="#ffc8d8"><tt> </tt></td><td> </td> <td width="100%"><dl><dt>Method resolution order:</dt> <dd><a href="ranger.gui.widgets.console.html#CommandConsole">CommandConsole</a></dd> <dd><a href="ranger.gui.widgets.console.html#ConsoleWithTab">ConsoleWithTab</a></dd> <dd><a href="ranger.gui.widgets.console.html#Console">Console</a></dd> <dd><a href="ranger.gui.widgets.html#Widget">ranger.gui.widgets.Widget</a></dd> <dd><a href="ranger.gui.displayable.html#Displayable">ranger.gui.displayable.Displayable</a></dd> <dd><a href="ranger.shared.html#EnvironmentAware">ranger.shared.EnvironmentAware</a></dd> <dd><a href="ranger.shared.html#FileManagerAware">ranger.shared.FileManagerAware</a></dd> <dd><a href="ranger.shared.html#Awareness">ranger.shared.Awareness</a></dd> <dd><a href="ranger.gui.curses_shortcuts.html#CursesShortcuts">ranger.gui.curses_shortcuts.CursesShortcuts</a></dd> <dd><a href="ranger.shared.settings.html#SettingsAware">ranger.shared.settings.SettingsAware</a></dd> <dd><a href="__builtin__.html#object">__builtin__.object</a></dd> </dl> <hr> Methods defined here:<br> <dl><dt><a name="CommandConsole-execute"><strong>execute</strong></a>(self, cmd<font color="#909090">=None</font>)</dt></dl> <hr> Data and other attributes defined here:<br> <dl><dt><strong>prompt</strong> = ':'</dl> <hr> Methods inherited from <a href="ranger.gui.widgets.console.html#ConsoleWithTab">ConsoleWithTab</a>:<br> <dl><dt><a name="CommandConsole-tab"><strong>tab</strong></a>(self, n<font color="#909090">=1</font>)</dt></dl> <hr> Methods inherited from <a href="ranger.gui.widgets.console.html#Console">Console</a>:<br> <dl><dt><a name="CommandConsole-__init__"><strong>__init__</strong></a>(self, win)</dt></dl> <dl><dt><a name="CommandConsole-add_to_history"><strong>add_to_history</strong></a>(self)</dt></dl> <dl><dt><a name="CommandConsole-clear"><strong>clear</strong></a>(self)</dt></dl> <dl><dt><a name="CommandConsole-close"><strong>close</strong></a>(self)</dt></dl> <dl><dt><a name="CommandConsole-delete"><strong>delete</strong></a>(self, mod)</dt></dl> <dl><dt><a name="CommandConsole-delete_rest"><strong>delete_rest</strong></a>(self, direction)</dt></dl> <dl><dt><a name="CommandConsole-delete_word"><strong>delete_word</strong></a>(self)</dt></dl> <dl><dt><a name="CommandConsole-destroy"><strong>destroy</strong></a>(self)</dt></dl> <dl><dt><a name="CommandConsole-draw"><strong>draw</strong></a>(self)</dt></dl> <dl><dt><a name="CommandConsole-finalize"><strong>finalize</strong></a>(self)</dt></dl> <dl><dt><a name="CommandConsole-history_move"><strong>history_move</strong></a>(self, n)</dt></dl> <dl><dt><a name="CommandConsole-init"><strong>init</strong></a>(self)</dt><dd><tt>override this. Called directly after class change</tt></dd></dl> <dl><dt><a name="CommandConsole-move"><strong>move</strong></a>(self, relative<font color="#909090">=0</font>, absolute<font color="#909090">=None</font>)</dt></dl> <dl><dt><a name="CommandConsole-on_line_change"><strong>on_line_change</strong></a>(self)</dt></dl> <dl><dt><a name="CommandConsole-open"><strong>open</strong></a>(self, mode, string<font color="#909090">=''</font>)</dt></dl> <dl><dt><a name="CommandConsole-paste"><strong>paste</strong></a>(self)</dt></dl> <dl><dt><a name="CommandConsole-press"><strong>press</strong></a>(self, key)</dt></dl> <dl><dt><a name="CommandConsole-type_key"><strong>type_key</strong></a>(self, key)</dt></dl> <hr> Data and other attributes inherited from <a href="ranger.gui.widgets.console.html#Console">Console</a>:<br> <dl><dt><strong>allow_close</strong> = False</dl> <dl><dt><strong>commandlist</strong> = None</dl> <dl><dt><strong>copy</strong> = ''</dl> <dl><dt><strong>histories</strong> = None</dl> <dl><dt><strong>history</strong> = None</dl> <dl><dt><strong>historypaths</strong> = []</dl> <dl><dt><strong>last_cursor_mode</strong> = None</dl> <dl><dt><strong>mode</strong> = None</dl> <dl><dt><strong>original_line</strong> = None</dl> <dl><dt><strong>override</strong> = None</dl> <dl><dt><strong>tab_deque</strong> = None</dl> <dl><dt><strong