diff options
Diffstat (limited to '128subx-words.subx')
-rw-r--r-- | 128subx-words.subx | 623 |
1 files changed, 623 insertions, 0 deletions
diff --git a/128subx-words.subx b/128subx-words.subx new file mode 100644 index 00000000..6f93e421 --- /dev/null +++ b/128subx-words.subx @@ -0,0 +1,623 @@ +# Helpers for parsing SubX words, with their rules for hex, labels and metadata. + +== code +# instruction effective address register displacement immediate +# . op subop mod rm32 base index scale r32 +# . 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 + +has-metadata?: # word: (addr slice), s: (addr string) -> eax: boolean + # pseudocode: + # var twig: &slice = next-token-from-slice(word->start, word->end, '/') # skip name + # curr = twig->end + # while true + # twig = next-token-from-slice(curr, word->end, '/') + # if (twig.empty()) break + # if (slice-equal?(twig, s)) return true + # curr = twig->end + # return false + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # . save registers + 51/push-ecx + 52/push-edx + 56/push-esi + 57/push-edi + # esi = word + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi + # var edx: (addr byte) = word->end + 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 2/r32/edx 4/disp8 . # copy *(esi+4) to edx + # var twig/edi: slice + 68/push 0/imm32/end + 68/push 0/imm32/start + 89/copy 3/mod/direct 7/rm32/edi . . . 4/r32/esp . . # copy esp to edi + # next-token-from-slice(word->start, word->end, '/', twig) + # . . push args + 57/push-edi + 68/push 0x2f/imm32/slash + 52/push-edx + ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi + # . . call + e8/call next-token-from-slice/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp +$has-metadata?:loop: + # next-token-from-slice(curr, word->end, '/', twig) + # . . push args + 57/push-edi + 68/push 0x2f/imm32/slash + 52/push-edx + ff 6/subop/push 1/mod/*+disp8 7/rm32/edi . . . . 4/disp8 . # push *(edi+4) + # . . call + e8/call next-token-from-slice/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp + # if (slice-empty?(twig)) return false + # . eax = slice-empty?(twig) + # . . push args + 57/push-edi + # . . call + e8/call slice-empty?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # . if (eax != false) return false + 3d/compare-eax-and 0/imm32/false + 75/jump-if-!= $has-metadata?:false/disp8 + # if (slice-equal?(twig, s)) return true + # . eax = slice-equal?(twig, s) + # . . push args + ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + 57/push-edi + # . . call + e8/call slice-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if (eax != false) return true + 3d/compare-eax-and 0/imm32/false + # eax already contains true + 75/jump-if-!= $has-metadata?:end/disp8 + eb/jump $has-metadata?:loop/disp8 +$has-metadata?:false: + b8/copy-to-eax 0/imm32/false +$has-metadata?:end: + # . reclaim locals + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . restore registers + 5f/pop-to-edi + 5e/pop-to-esi + 5a/pop-to-edx + 59/pop-to-ecx + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-has-metadata-true: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # (eax..ecx) = "ab/imm32" + b8/copy-to-eax "ab/imm32"/imm32 + 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx + 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 + 05/add-to-eax 4/imm32 + # var in/esi: slice = {eax, ecx} + 51/push-ecx + 50/push-eax + 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi + # eax = has-metadata?(esi, "imm32") + # . . push args + 68/push "imm32"/imm32 + 56/push-esi + # . . call + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(eax, 1, msg) + # . . push args + 68/push "F - test-has-metadata-true"/imm32 + 68/push 1/imm32/true + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-has-metadata-false: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # (eax..ecx) = "ab/c" + b8/copy-to-eax "ab/c"/imm32 + 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx + 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 + 05/add-to-eax 4/imm32 + # var in/esi: slice = {eax, ecx} + 51/push-ecx + 50/push-eax + 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi + # eax = has-metadata?(esi, "d") + # . . push args + 68/push "d"/imm32 + 56/push-esi + # . . call + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(eax, 0, msg) + # . . push args + 68/push "F - test-has-metadata-false"/imm32 + 68/push 0/imm32/false + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-has-metadata-ignore-name: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # (eax..ecx) = "a/b" + b8/copy-to-eax "a/b"/imm32 + 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx + 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 + 05/add-to-eax 4/imm32 + # var in/esi: slice = {eax, ecx} + 51/push-ecx + 50/push-eax + 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi + # eax = has-metadata?(esi, "a") + # . . push args + 68/push "a"/imm32 + 56/push-esi + # . . call + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(eax, 0, msg) + # . . push args + 68/push "F - test-has-metadata-ignore-name"/imm32 + 68/push 0/imm32/false + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-has-metadata-multiple-true: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # (eax..ecx) = "a/b/c" + b8/copy-to-eax "a/b/c"/imm32 + 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx + 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 + 05/add-to-eax 4/imm32 + # var in/esi: slice = {eax, ecx} + 51/push-ecx + 50/push-eax + 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi + # eax = has-metadata?(esi, "c") + # . . push args + 68/push "c"/imm32 + 56/push-esi + # . . call + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(eax, 1, msg) + # . . push args + 68/push "F - test-has-metadata-multiple-true"/imm32 + 68/push 1/imm32/true + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-has-metadata-multiple-false: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # (eax..ecx) = "a/b/c" + b8/copy-to-eax "a/b/c"/imm32 + 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx + 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 + 05/add-to-eax 4/imm32 + # var in/esi: slice = {eax, ecx} + 51/push-ecx + 50/push-eax + 89/copy 3/mod/direct 6/rm32/esi . . . 4/r32/esp . . # copy esp to esi + # eax = has-metadata?(esi, "d") + # . . push args + 68/push "d"/imm32 + 56/push-esi + # . . call + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # check-ints-equal(eax, 0, msg) + # . . push args + 68/push "F - test-has-metadata-multiple-false"/imm32 + 68/push 0/imm32/false + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +# conditions for 'valid' names that are not at risk of looking like hex numbers +# keep in sync with the rules in labels.cc +#: - if it starts with a digit, it's treated as a number. If it can't be +#: parsed as hex it will raise an error. +#: - if it starts with '-' it's treated as a number. +#: - if it starts with '0x' it's treated as a number. (redundant) +#: - if it's two characters long, it can't be a name. Either it's a hex +#: byte, or it raises an error. +is-valid-name?: # in: (addr slice) -> eax: boolean + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # . save registers + 51/push-ecx + 56/push-esi + # esi = in + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi + # var start/ecx: (addr byte) = in->start + 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx +$is-valid-name?:check0: + # if (start >= in->end) return false + 3b/compare 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # compare ecx with *(esi+4) + 73/jump-if-addr>= $is-valid-name?:false/disp8 +$is-valid-name?:check1: + # var len/eax: int = in->end - start + 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 0/r32/eax 4/disp8 . # copy *(esi+4) to eax + 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax + # if (eax == 2) return false + 3d/compare-eax-and 2/imm32 + 74/jump-if-= $is-valid-name?:false/disp8 +$is-valid-name?:check2: + # var c/eax: (addr byte) = *start + 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax + 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL + # if (c == "-") return false + 3d/compare-eax-and 2d/imm32/- + 74/jump-if-= $is-valid-name?:false/disp8 +$is-valid-name?:check3a: + # if (c < "0") return true + 3d/compare-eax-with 30/imm32/0 + 7c/jump-if-< $is-valid-name?:true/disp8 +$is-valid-name?:check3b: + # if (c > "9") return true + 3d/compare-eax-with 39/imm32/9 + 7f/jump-if-> $is-valid-name?:true/disp8 +$is-valid-name?:false: + # return false + b8/copy-to-eax 0/imm32/false + eb/jump $is-valid-name?:end/disp8 +$is-valid-name?:true: + # return true + b8/copy-to-eax 1/imm32/true +$is-valid-name?:end: + # . restore registers + 5e/pop-to-esi + 59/pop-to-ecx + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-is-valid-name-digit-prefix: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # (eax..ecx) = "34" + b8/copy-to-eax "34"/imm32 + 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx + 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 + 05/add-to-eax 4/imm32 + # var slice/ecx: slice = {eax, ecx} + 51/push-ecx + 50/push-eax + 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + # eax = is-valid-name?(slice) + # . . push args + 51/push-ecx + # . . call + e8/call is-valid-name?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 0, msg) + # . . push args + 68/push "F - test-is-valid-name-digit-prefix"/imm32 + 68/push 0/imm32/false + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-is-valid-name-negative-prefix: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # (eax..ecx) = "-0x34" + b8/copy-to-eax "-0x34"/imm32 + 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx + 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 + 05/add-to-eax 4/imm32 + # var slice/ecx: slice = {eax, ecx} + 51/push-ecx + 50/push-eax + 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + # eax = is-valid-name?(slice) + # . . push args + 51/push-ecx + # . . call + e8/call is-valid-name?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 0, msg) + # . . push args + 68/push "F - test-is-valid-name-negative-prefix"/imm32 + 68/push 0/imm32/false + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-is-valid-name-0x-prefix: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # (eax..ecx) = "0x34" + b8/copy-to-eax "0x34"/imm32 + 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx + 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 + 05/add-to-eax 4/imm32 + # var slice/ecx: slice = {eax, ecx} + 51/push-ecx + 50/push-eax + 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + # eax = is-valid-name?(slice) + # . . push args + 51/push-ecx + # . . call + e8/call is-valid-name?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 0, msg) + # . . push args + 68/push "F - test-is-valid-name-0x-prefix"/imm32 + 68/push 0/imm32/false + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-is-valid-name-starts-with-pre-digit: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # (eax..ecx) = "/03" + b8/copy-to-eax "/03"/imm32 + 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx + 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 + 05/add-to-eax 4/imm32 + # var slice/ecx: slice = {eax, ecx} + 51/push-ecx + 50/push-eax + 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + # eax = is-valid-name?(slice) + # . . push args + 51/push-ecx + # . . call + e8/call is-valid-name?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 1, msg) + # . . push args + 68/push "F - test-is-valid-name-starts-with-pre-digit"/imm32 + 68/push 1/imm32/true + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-is-valid-name-starts-with-post-digit: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # (eax..ecx) = "q34" + b8/copy-to-eax "q34"/imm32 + 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx + 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 + 05/add-to-eax 4/imm32 + # var slice/ecx: slice = {eax, ecx} + 51/push-ecx + 50/push-eax + 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + # eax = is-valid-name?(slice) + # . . push args + 51/push-ecx + # . . call + e8/call is-valid-name?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 1, msg) + # . . push args + 68/push "F - test-is-valid-name-starts-with-post-digit"/imm32 + 68/push 1/imm32/true + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-is-valid-name-starts-with-digit: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # (eax..ecx) = "0x34" + b8/copy-to-eax "0x34"/imm32 + 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx + 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 + 05/add-to-eax 4/imm32 + # var slice/ecx: slice = {eax, ecx} + 51/push-ecx + 50/push-eax + 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + # eax = is-valid-name?(slice) + # . . push args + 51/push-ecx + # . . call + e8/call is-valid-name?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 0, msg) + # . . push args + 68/push "F - test-is-valid-name-starts-with-digit"/imm32 + 68/push 0/imm32/false + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +is-label?: # word: (addr slice) -> eax: boolean + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # . save registers + 51/push-ecx + # ecx = word + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx + # var end/ecx: (addr byte) = word->end + 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 1/r32/ecx 4/disp8 . # copy *(ecx+4) to ecx + # return *(end - 1) == ':' + # . eax = *(end-1) + 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax + 8a/copy-byte 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/AL -1/disp8 . # copy byte at *(ecx-1) to AL + # . return (eax == ':') + 3d/compare-eax-and 0x3a/imm32/colon + b8/copy-to-eax 1/imm32/true + 74/jump-if-= $is-label?:end/disp8 + b8/copy-to-eax 0/imm32/false +$is-label?:end: + # . restore registers + 59/pop-to-ecx + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +test-is-label?: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +$test-is-label?:true: + # (eax..ecx) = "AAA:" + b8/copy-to-eax "AAA:"/imm32 + 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx + 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 + 05/add-to-eax 4/imm32 + # var slice/ecx: slice = {eax, ecx} + 51/push-ecx + 50/push-eax + 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + # is-label?(slice/ecx) + # . . push args + 51/push-ecx + # . . call + e8/call is-label?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 1, msg) + # . . push args + 68/push "F - test-is-label?:true"/imm32 + 68/push 1/imm32 + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +$test-is-label?:false: + # (eax..ecx) = "AAA" + b8/copy-to-eax "AAA"/imm32 + 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx + 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 + 05/add-to-eax 4/imm32 + # var slice/ecx: slice = {eax, ecx} + 51/push-ecx + 50/push-eax + 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + # is-label?(slice/ecx) + # . . push args + 51/push-ecx + # . . call + e8/call is-label?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 0, msg) + # . . push args + 68/push "F - test-is-label?:false"/imm32 + 68/push 0/imm32 + 50/push-eax + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + # . epilogue + 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 5d/pop-to-ebp + c3/return + +# . . vim:nowrap:textwidth=0 |