https://github.com/akkartik/mu/blob/master/128subx-words.subx
  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