1 # Helpers for parsing SubX words, with their rules for hex, labels and metadata. 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 has-metadata?: # word: (addr slice), s: (addr string) -> result/eax: boolean 9 # pseudocode: 10 # var twig: &slice = next-token-from-slice(word->start, word->end, '/') # skip name 11 # curr = twig->end 12 # while true 13 # twig = next-token-from-slice(curr, word->end, '/') 14 # if (twig.empty()) break 15 # if (slice-equal?(twig, s)) return true 16 # curr = twig->end 17 # return false 18 # . prologue 19 55/push-ebp 20 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 21 # . save registers 22 51/push-ecx 23 52/push-edx 24 56/push-esi 25 57/push-edi 26 # esi = word 27 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi 28 # var edx: (addr byte) = word->end 29 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 2/r32/edx 4/disp8 . # copy *(esi+4) to edx 30 # var twig/edi: slice 31 68/push 0/imm32/end 32 68/push 0/imm32/start 33 89/copy 3/mod/direct 7/rm32/edi . . . 4/r32/esp . . # copy esp to edi 34 # next-token-from-slice(word->start, word->end, '/', twig) 35 # . . push args 36 57/push-edi 37 68/push 0x2f/imm32/slash 38 52/push-edx 39 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi 40 # . . call 41 e8/call next-token-from-slice/disp32 42 # . . discard args 43 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp 44 $has-metadata?:loop: 45 # next-token-from-slice(curr, word->end, '/', twig) 46 # . . push args 47 57/push-edi 48 68/push 0x2f/imm32/slash 49 52/push-edx 50 ff 6/subop/push 1/mod/*+disp8 7/rm32/edi . . . . 4/disp8 . # push *(edi+4) 51 # . . call 52 e8/call next-token-from-slice/disp32 53 # . . discard args 54 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp 55 # if (slice-empty?(twig)) return false 56 # . eax = slice-empty?(twig) 57 # . . push args 58 57/push-edi 59 # . . call 60 e8/call slice-empty?/disp32 61 # . . discard args 62 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 63 # . if (eax != false) return false 64 3d/compare-eax-and 0/imm32/false 65 75/jump-if-!= $has-metadata?:false/disp8 66 # if (slice-equal?(twig, s)) return true 67 # . eax = slice-equal?(twig, s) 68 # . . push args 69 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) 70 57/push-edi 71 # . . call 72 e8/call slice-equal?/disp32 73 # . . discard args#!/bin/bash # Regenerate html files. # If given a single argument, regenerate just that file. set -e ( cd tools; c++ -g linkify.cc -o linkify; ) # generate html/$1.html using /tmp/tags process() { mkdir -p html/`dirname $1` rm -f html/$1.html convert_html $1 tools/linkify /tmp/tags html/$1.html mv html/$1.html.out html/$1.html } URL_BASE='https://github.com/akkartik/mu/blob/main' convert_html() { vim -c "set number" -c TOhtml -c write -c qall $1 sed -i 's,<title>.*/mu/,<title>Mu - ,' $1.html sed -i 's,\.html</title>,</title>,' $1.html sed -i "/^<body/a <a href='$URL_BASE/$1'>$URL_BASE/$1</a>" $1.html sed -i 's/^\* { \(.*\) }/* { font-size:12pt; \1 }/g' $1.html sed -i 's/^body { \(.*\) }/body { font-size:12pt; \1 }/g' $1.html sed -i '/^body {/a a { color:inherit; }' $1.html # switch unicode characters around in the rendered html # the ones we have in the source files render double-wide in html # the ones we want in the html cause iTerm2 to slow down in alt-tabbing for some reason # the following commands give us the best of both worlds sed -i -e 's/┈/╌/g' -e 's/┊/╎/g' $1.html mv -i $1.html html/`dirname $1` } ctags -x *.cc |grep -v '^. ' > /tmp/tags # don't hyperlink every 'i' to the integer register variant for f in *.cc do test $# -gt 0 && test $1 != $f && continue process $f done ctags -x [0-9]*.subx [0-9]*.mu > /tmp/tags for f in *.subx *.mu do test $# -gt 0 && test $1 != $f && continue process $f done for f in apps/*.subx do test $# -gt 0 && test $1 != $f && continue ( cd apps ctags -x ../[0-9]*.subx ../[0-9]*.mu `basename $f` > /tmp/tags ) process $f done for f in apps/*.mu do test $# -gt 0 && test $1 != $f && continue ( cd apps ctags -x ../[0-9]*.subx ../[0-9]*.mu `basename $f` > /tmp/tags ) process $f done for f in apps/*/*.mu do test $# -gt 0 && test $1 != $f && continue echo $f ( cd `dirname $f` ctags -x ../../[0-9]*.subx ../../[0-9]*.mu *.mu > /tmp/tags ) process $f done for f in baremetal/*.hex do test $# -gt 0 && test $1 != $f && continue ( cd baremetal ctags -x [0-9]*.subx [0-9]*.mu `basename $f` > /tmp/tags ) process $f done for f in baremetal/*.subx do test $# -gt 0 && test $1 != $f && continue ( cd baremetal ctags -x [0-9]*.subx [0-9]*.mu `basename $f` > /tmp/tags ) process $f done for f in baremetal/*.mu do test $# -gt 0 && test $1 != $f && continue ( cd baremetal ctags -x [0-9]*.subx [0-9]*.mu `basename $f` > /tmp/tags ) process $f done rm /tmp/tags. . . 8/imm32 # add to esp 186 # check-ints-equal(eax, 0, msg) 187 # . . push args 188 68/push "F - test-has-metadata-ignore-name"/imm32 189 68/push 0/imm32/false 190 50/push-eax 191 # . . call 192 e8/call check-ints-equal/disp32 193 # . . discard args 194 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 195 # . epilogue 196 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 197 5d/pop-to-ebp 198 c3/return 199 200 test-has-metadata-multiple-true: 201 # . prologue 202 55/push-ebp 203 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 204 # (eax..ecx) = "a/b/c" 205 b8/copy-to-eax "a/b/c"/imm32 206 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 207 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 208 05/add-to-eax 4/imm32 209 # var in/esi: slice = {eax, ecx} 210 51/push-ecx 211 50/push-eax 212 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi 213 # eax = has-metadata?(esi, "c") 214 # . . push args 215 68/push "c"/imm32 216 56/push-esi 217 # . . call 218 e8/call has-metadata?/disp32 219 # . . discard args 220 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 221 # check-ints-equal(eax, 1, msg) 222 # . . push args 223 68/push "F - test-has-metadata-multiple-true"/imm32 224 68/push 1/imm32/true 225 50/push-eax 226 # . . call 227 e8/call check-ints-equal/disp32 228 # . . discard args 229 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 230 # . epilogue 231 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 232 5d/pop-to-ebp 233 c3/return 234 235 test-has-metadata-multiple-false: 236 # . prologue 237 55/push-ebp 238 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 239 # (eax..ecx) = "a/b/c" 240 b8/copy-to-eax "a/b/c"/imm32 241 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 242 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 243 05/add-to-eax 4/imm32 244 # var in/esi: slice = {eax, ecx} 245 51/push-ecx 246 50/push-eax 247 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi 248 # eax = has-metadata?(esi, "d") 249 # . . push args 250 68/push "d"/imm32 251 56/push-esi 252 # . . call 253 e8/call has-metadata?/disp32 254 # . . discard args 255 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 256 # check-ints-equal(eax, 0, msg) 257 # . . push args 258 68/push "F - test-has-metadata-multiple-false"/imm32 259 68/push 0/imm32/false 260 50/push-eax 261 # . . call 262 e8/call check-ints-equal/disp32 263 # . . discard args 264 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 265 # . epilogue 266 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 267 5d/pop-to-ebp 268 c3/return 269 270 # conditions for 'valid' names that are not at risk of looking like hex numbers 271 # keep in sync with the rules in labels.cc 272 #: - if it starts with a digit, it's treated as a number. If it can't be 273 #: parsed as hex it will raise an error. 274 #: - if it starts with '-' it's treated as a number. 275 #: - if it starts with '0x' it's treated as a number. (redundant) 276 #: - if it's two characters long, it can't be a name. Either it's a hex 277 #: byte, or it raises an error. 278 is-valid-name?: # in: (addr slice) -> result/eax: boolean 279 # . prologue 280 55/push-ebp 281 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 282 # . save registers 283 51/push-ecx 284 56/push-esi 285 # esi = in 286 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi 287 # var start/ecx: (addr byte) = in->start 288 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx 289 $is-valid-name?:check0: 290 # if (start >= in->end) return false 291 3b/compare 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # compare ecx with *(esi+4) 292 73/jump-if-addr>= $is-valid-name?:false/disp8 293 $is-valid-name?:check1: 294 # var len/eax: int = in->end - start 295 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 0/r32/eax 4/disp8 . # copy *(esi+4) to eax 296 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax 297 # if (eax == 2) return false 298 3d/compare-eax-and 2/imm32 299 74/jump-if-= $is-valid-name?:false/disp8 300 $is-valid-name?:check2: 301 # var c/eax: (addr byte) = *start 302 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 303 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL 304 # if (c == "-") return false 305 3d/compare-eax-and 2d/imm32/- 306 74/jump-if-= $is-valid-name?:false/disp8 307 $is-valid-name?:check3a: 308 # if (c < "0") return true 309 3d/compare-eax-with 30/imm32/0 310 7c/jump-if-< $is-valid-name?:true/disp8 311 $is-valid-name?:check3b: 312 # if (c > "9") return true 313 3d/compare-eax-with 39/imm32/9 314 7f/jump-if-> $is-valid-name?:true/disp8 315 $is-valid-name?:false: 316 # return false 317 b8/copy-to-eax 0/imm32/false 318 eb/jump $is-valid-name?:end/disp8 319 $is-valid-name?:true: 320 # return true 321 b8/copy-to-eax 1/imm32/true 322 $is-valid-name?:end: 323 # . restore registers 324 5e/pop-to-esi 325 59/pop-to-ecx 326 # . epilogue 327 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 328 5d/pop-to-ebp 329 c3/return 330 331 test-is-valid-name-digit-prefix: 332 # . prologue 333 55/push-ebp 334 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 335 # (eax..ecx) = "34" 336 b8/copy-to-eax "34"/imm32 337 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 338 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 339 05/add-to-eax 4/imm32 340 # var slice/ecx: slice = {eax, ecx} 341 51/push-ecx 342 50/push-eax 343 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 344 # eax = is-valid-name?(slice) 345 # . . push args 346 51/push-ecx 347 # . . call 348 e8/call is-valid-name?/disp32 349 # . . discard args 350 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 351 # check-ints-equal(eax, 0, msg) 352 # . . push args 353 68/push "F - test-is-valid-name-digit-prefix"/imm32 354 68/push 0/imm32/false 355 50/push-eax 356 # . . call 357 e8/call check-ints-equal/disp32 358 # . . discard args 359 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 360 # . epilogue 361 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 362 5d/pop-to-ebp 363 c3/return 364 365 test-is-valid-name-negative-prefix: 366 # . prologue 367 55/push-ebp 368 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 369 # (eax..ecx) = "-0x34" 370 b8/copy-to-eax "-0x34"/imm32 371 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 372 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 373 05/add-to-eax 4/imm32 374 # var slice/ecx: slice = {eax, ecx} 375 51/push-ecx 376 50/push-eax 377 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 378 # eax = is-valid-name?(slice) 379 # . . push args 380 51/push-ecx 381 # . . call 382 e8/call is-valid-name?/disp32 383 # . . discard args 384 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 385 # check-ints-equal(eax, 0, msg) 386 # . . push args 387 68/push "F - test-is-valid-name-negative-prefix"/imm32 388 68/push 0/imm32/false 389 50/push-eax 390 # . . call 391 e8/call check-ints-equal/disp32 392 # . . discard args 393 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 394 # . epilogue 395 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 396 5d/pop-to-ebp 397 c3/return 398 399 test-is-valid-name-0x-prefix: 400 # . prologue 401 55/push-ebp 402 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 403 # (eax..ecx) = "0x34" 404 b8/copy-to-eax "0x34"/imm32 405 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 406 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 407 05/add-to-eax 4/imm32 408 # var slice/ecx: slice = {eax, ecx} 409 51/push-ecx 410 50/push-eax 411 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 412 # eax = is-valid-name?(slice) 413 # . . push args 414 51/push-ecx 415 # . . call 416 e8/call is-valid-name?/disp32 417 # . . discard args 418 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 419 # check-ints-equal(eax, 0, msg) 420 # . . push args 421 68/push "F - test-is-valid-name-0x-prefix"/imm32 422 68/push 0/imm32/false 423 50/push-eax 424 # . . call 425 e8/call check-ints-equal/disp32 426 # . . discard args 427 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 428 # . epilogue 429 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 430 5d/pop-to-ebp 431 c3/return 432 433 test-is-valid-name-starts-with-pre-digit: 434 # . prologue 435 55/push-ebp 436 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 437 # (eax..ecx) = "/03" 438 b8/copy-to-eax "/03"/imm32 439 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 440 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 441 05/add-to-eax 4/imm32 442 # var slice/ecx: slice = {eax, ecx} 443 51/push-ecx 444 50/push-eax 445 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 446 # eax = is-valid-name?(slice) 447 # . . push args 448 51/push-ecx 449 # . . call 450 e8/call is-valid-name?/disp32 451 # . . discard args 452 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 453 # check-ints-equal(eax, 1, msg) 454 # . . push args 455 68/push "F - test-is-valid-name-starts-with-pre-digit"/imm32 456 68/push 1/imm32/true 457 50/push-eax 458 # . . call 459 e8/call check-ints-equal/disp32 460 # . . discard args 461 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 462 # . epilogue 463 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 464 5d/pop-to-ebp 465 c3/return 466 467 test-is-valid-name-starts-with-post-digit: 468 # . prologue 469 55/push-ebp 470 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 471 # (eax..ecx) = "q34" 472 b8/copy-to-eax "q34"/imm32 473 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 474 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 475 05/add-to-eax 4/imm32 476 # var slice/ecx: slice = {eax, ecx} 477 51/push-ecx 478 50/push-eax 479 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 480 # eax = is-valid-name?(slice) 481 # . . push args 482 51/push-ecx 483 # . . call 484 e8/call is-valid-name?/disp32 485 # . . discard args 486 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 487 # check-ints-equal(eax, 1, msg) 488 # . . push args 489 68/push "F - test-is-valid-name-starts-with-post-digit"/imm32 490 68/push 1/imm32/true 491 50/push-eax 492 # . . call 493 e8/call check-ints-equal/disp32 494 # . . discard args 495 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 496 # . epilogue 497 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 498 5d/pop-to-ebp 499 c3/return 500 501 test-is-valid-name-starts-with-digit: 502 # . prologue 503 55/push-ebp 504 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 505 # (eax..ecx) = "0x34" 506 b8/copy-to-eax "0x34"/imm32 507 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 508 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 509 05/add-to-eax 4/imm32 510 # var slice/ecx: slice = {eax, ecx} 511 51/push-ecx 512 50/push-eax 513 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 514 # eax = is-valid-name?(slice) 515 # . . push args 516 51/push-ecx 517 # . . call 518 e8/call is-valid-name?/disp32 519 # . . discard args 520 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 521 # check-ints-equal(eax, 0, msg) 522 # . . push args 523 68/push "F - test-is-valid-name-starts-with-digit"/imm32 524 68/push 0/imm32/false 525 50/push-eax 526 # . . call 527 e8/call check-ints-equal/disp32 528 # . . discard args 529 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 530 # . epilogue 531 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 532 5d/pop-to-ebp 533 c3/return 534 535 is-label?: # word: (addr slice) -> result/eax: boolean 536 # . prologue 537 55/push-ebp 538 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 539 # . save registers 540 51/push-ecx 541 # ecx = word 542 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx 543 # var end/ecx: (addr byte) = word->end 544 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 1/r32/ecx 4/disp8 . # copy *(ecx+4) to ecx 545 # return *(end - 1) == ':' 546 # . eax = *(end-1) 547 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax 548 8a/copy-byte 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/AL -1/disp8 . # copy byte at *(ecx-1) to AL 549 # . return (eax == ':') 550 3d/compare-eax-and 0x3a/imm32/colon 551 b8/copy-to-eax 1/imm32/true 552 74/jump-if-= $is-label?:end/disp8 553 b8/copy-to-eax 0/imm32/false 554 $is-label?:end: 555 # . restore registers 556 59/pop-to-ecx 557 # . epilogue 558 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 559 5d/pop-to-ebp 560 c3/return 561 562 test-is-label?: 563 # . prologue 564 55/push-ebp 565 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 566 $test-is-label?:true: 567 # (eax..ecx) = "AAA:" 568 b8/copy-to-eax "AAA:"/imm32 569 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 570 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 571 05/add-to-eax 4/imm32 572 # var slice/ecx: slice = {eax, ecx} 573 51/push-ecx 574 50/push-eax 575 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 576 # is-label?(slice/ecx) 577 # . . push args 578 51/push-ecx 579 # . . call 580 e8/call is-label?/disp32 581 # . . discard args 582 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 583 # check-ints-equal(eax, 1, msg) 584 # . . push args 585 68/push "F - test-is-label?:true"/imm32 586 68/push 1/imm32 587 50/push-eax 588 # . . call 589 e8/call check-ints-equal/disp32 590 # . . discard args 591 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 592 $test-is-label?:false: 593 # (eax..ecx) = "AAA" 594 b8/copy-to-eax "AAA"/imm32 595 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 596 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 597 05/add-to-eax 4/imm32 598 # var slice/ecx: slice = {eax, ecx} 599 51/push-ecx 600 50/push-eax 601 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 602 # is-label?(slice/ecx) 603 # . . push args 604 51/push-ecx 605 # . . call 606 e8/call is-label?/disp32 607 # . . discard args 608 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 609 # check-ints-equal(eax, 0, msg) 610 # . . push args 611 68/push "F - test-is-label?:false"/imm32 612 68/push 0/imm32 613 50/push-eax 614 # . . call 615 e8/call check-ints-equal/disp32 616 # . . discard args 617 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 618 # . epilogue 619 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 620 5d/pop-to-ebp 621 c3/return 622 623 # . . vim:nowrap:textwidth=0