diff options
Diffstat (limited to 'linux/133subx-widths.subx')
-rw-r--r-- | linux/133subx-widths.subx | 243 |
1 files changed, 243 insertions, 0 deletions
diff --git a/linux/133subx-widths.subx b/linux/133subx-widths.subx new file mode 100644 index 00000000..6d8ce8de --- /dev/null +++ b/linux/133subx-widths.subx @@ -0,0 +1,243 @@ +# Helpers to compute widths of SubX arguments based on their metadata. +# /imm8 => 1 byte, +# /disp32 => 4 bytes, +# and so on. + +== 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 + +compute-width: # word: (addr array byte) -> result/eax: int + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + # . save registers + 51/push-ecx + # eax = word + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to ecx + # var ecx: (addr byte) = &word[word->size] + 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 + # eax = word->data + 05/add-to-eax 4/imm32 + # var in/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 + # return compute-width-of-slice(ecx) + # . . push args + 51/push-ecx + # . . call + e8/call compute-width-of-slice/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +$compute-width:end: + # . reclaim locals + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . 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 + +compute-width-of-slice: # s: (addr slice) -> result/eax: int + # . 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 = s + 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx + # if (has-metadata?(word, "imm32")) return 4 + # . eax = has-metadata?(word, "imm32") + # . . push args + 68/push "imm32"/imm32 + 51/push-ecx + # . . call + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if (eax != false) return 4 + 3d/compare-eax-and 0/imm32/false + b8/copy-to-eax 4/imm32 # ZF is set, so we can overwrite eax now + 75/jump-if-!= $compute-width-of-slice:end/disp8 + # if (has-metadata?(word, "disp32")) return 4 + # . eax = has-metadata?(word, "disp32") + # . . push args + 68/push "disp32"/imm32 + 51/push-ecx + # . . call + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if (eax != false) return 4 + 3d/compare-eax-and 0/imm32/false + b8/copy-to-eax 4/imm32 # ZF is set, so we can overwrite eax now + 75/jump-if-!= $compute-width-of-slice:end/disp8 + # if (has-metadata?(word, "imm16")) return 2 + # . eax = has-metadata?(word, "imm16") + # . . push args + 68/push "imm16"/imm32 + 51/push-ecx + # . . call + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if (eax != false) return 2 + 3d/compare-eax-and 0/imm32/false + b8/copy-to-eax 2/imm32 # ZF is set, so we can overwrite eax now + 75/jump-if-!= $compute-width-of-slice:end/disp8 + # if (has-metadata?(word, "disp16")) return 2 + # . eax = has-metadata?(word, "disp16") + # . . push args + 68/push "disp16"/imm32 + 51/push-ecx + # . . call + e8/call has-metadata?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + # . if (eax != false) return 2 + 3d/compare-eax-and 0/imm32/false + b8/copy-to-eax 2/imm32 # ZF is set, so we can overwrite eax now + 75/jump-if-!= $compute-width-of-slice:end/disp8 + # otherwise return 1 + b8/copy-to-eax 1/imm32 +$compute-width-of-slice: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-compute-width: + # . prologue + 55/push-ebp + 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +$test-compute-width:imm8: + # eax = compute-width("0x2/imm8") + # . . push args + 68/push "0x2/imm8"/imm32 + # . . call + e8/call compute-width/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-compute-width: 0x2/imm8"/imm32 + 50/push-eax + 68/push 1/imm32 + # . . 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-compute-width:imm16: + # eax = compute-width("4/imm16") + # . . push args + 68/push "4/imm16"/imm32 + # . . call + e8/call compute-width/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 2, msg) + # . . push args + 68/push "F - test-compute-width: 4/imm16"/imm32 + 50/push-eax + 68/push 2/imm32 + # . . 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-compute-width:imm32: + # eax = compute-width("4/imm32") + # . . push args + 68/push "4/imm32"/imm32 + # . . call + e8/call compute-width/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 4, msg) + # . . push args + 68/push "F - test-compute-width: 4/imm32"/imm32 + 50/push-eax + 68/push 4/imm32 + # . . 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-compute-width:disp8: + # eax = compute-width("foo/disp8") + # . . push args + 68/push "foo/disp8"/imm32 + # . . call + e8/call compute-width/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-compute-width: foo/disp8"/imm32 + 50/push-eax + 68/push 1/imm32 + # . . 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-compute-width:disp16: + # eax = compute-width("foo/disp16") + # . . push args + 68/push "foo/disp16"/imm32 + # . . call + e8/call compute-width/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 2, msg) + # . . push args + 68/push "F - test-compute-width: foo/disp16"/imm32 + 50/push-eax + 68/push 2/imm32 + # . . 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-compute-width:disp32: + # eax = compute-width("foo/disp32") + # . . push args + 68/push "foo/disp32"/imm32 + # . . call + e8/call compute-width/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + # check-ints-equal(eax, 4, msg) + # . . push args + 68/push "F - test-compute-width: foo/disp32"/imm32 + 50/push-eax + 68/push 4/imm32 + # . . 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-compute-width:no-metadata: + # eax = compute-width("45") + # . . push args + 68/push "45"/imm32 + # . . call + e8/call compute-width/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-compute-width: 45 (no metadata)"/imm32 + 50/push-eax + 68/push 1/imm32 + # . . 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 |