1 # Helpers to compute widths of SubX arguments based on their metadata. 2 # /imm8 => 1 byte, 3 # /disp32 => 4 bytes, 4 # and so on. 5 6 == code 7 # instruction effective address register displacement immediate 8 # . op subop mod rm32 base index scale r32 9 # . 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 10 11 compute-width: # word: (addr array byte) -> result/eax: int 12 # . prologue 13 55/push-ebp 14 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 15 # . save registers 16 51/push-ecx 17 # eax = word 18 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to ecx 19 # var ecx: (addr byte) = &word[word->size] 20 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx 21 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 22 # eax = word->data 23 05/add-to-eax 4/imm32 24 # var in/ecx: slice = {eax, ecx} 25 51/push-ecx 26 50/push-eax 27 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx 28 # return compute-width-of-slice(ecx) 29 # . . push args 30 51/push-ecx 31 # . . call 32 e8/call compute-width-of-slice/disp32 33 # . . discard args 34 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 35 $compute-width:end: 36 # . reclaim locals 37 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 38 # . restore registers 39 59/pop-to-ecx 40 # . epilogue 41 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 42 5d/pop-to-ebp 43 c3/return 44 45 compute-width-of-slice: # s: (addr slice) -> result/eax: int 46 # . prologue 47 55/push-ebp 48 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 49 # . save registers 50 51/push-ecx 51 # ecx = s 52 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx 53 # if (has-metadata?(word, "imm32")) return 4 54 # . eax = has-metadata?(word, "imm32") 55 # . . push args 56 68/push "imm32"/imm32 57 51/push-ecx 58 # . . call 59 e8/call has-metadata?/disp32 60 # . . discard args 61 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 62 # . if (eax != false) return 4 63 3d/compare-eax-and 0/imm32/false 64 b8/copy-to-eax 4/imm32 # ZF is set, so we can overwrite eax now 65 75/jump-if-!= $compute-width-of-slice:end/disp8 66 # if (has-metadata?(word, "disp32")) return 4 67 # . eax = has-metadata?(word, "disp32") 68 # . . push args 69 68/push "disp32"/imm32 70 51/push-ecx 71 # . . call 72 e8/call has-metadata?/disp32 73 # . . discard args 74 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 75 # . if (eax != false) return 4 76 3d/compare-eax-and 0/imm32/false 77 b8/copy-to-eax 4/imm32 # ZF is set, so we can overwrite eax now 78 75/jump-if-!= $compute-width-of-slice:end/disp8 79 # if (has-metadata?(word, "imm16")) return 2 80 # . eax = has-metadata?(word, "imm16") 81 # . . push args 82 68/push "imm16"/imm32 83 51/push-ecx 84 # . . call 85 e8/call has-metadata?/disp32 86 # . . discard args 87 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 88 # . if (eax != false) return 2 89 3d/compare-eax-and 0/imm32/false 90 b8/copy-to-eax 2/imm32 # ZF is set, so we can overwrite eax now 91 75/jump-if-!= $compute-width-of-slice:end/disp8 92 # if (has-metadata?(word, "disp16")) return 2 93 # . eax = has-metadata?(word, "disp16") 94 # . . push args 95 68/push "disp16"/imm32 96 51/push-ecx 97 # . . call 98 e8/call has-metadata?/disp32 99 # . . discard args 100 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp 101 # . if (eax != false) return 2 102 3d/compare-eax-and 0/imm32/false 103 b8/copy-to-eax 2/imm32 # ZF is set, so we can overwrite eax now 104 75/jump-if-!= $compute-width-of-slice:end/disp8 105 # otherwise return 1 106 b8/copy-to-eax 1/imm32 107 $compute-width-of-slice:end: 108 # . restore registers 109 59/pop-to-ecx 110 # . epilogue 111 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp 112 5d/pop-to-ebp 113 c3/return 114 115 test-compute-width: 116 # . prologue 117 55/push-ebp 118 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp 119 $test-compute-width:imm8: 120 # eax = compute-width("0x2/imm8") 121 # . . push args 122 68/push "0x2/imm8"/imm32 123 # . . call 124 e8/call compute-width/disp32 125 # . . discard args 126 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 127 # check-ints-equal(eax, 1, msg) 128 # . . push args 129 68/push "F - test-compute-width: 0x2/imm8"/imm32 130 50/push-eax 131 68/push 1/imm32 132 # . . call 133 e8/call check-ints-equal/disp32 134 # . . discard args 135 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 136 $test-compute-width:imm16: 137 # eax = compute-width("4/imm16") 138 # . . push args 139 68/push "4/imm16"/imm32 140 # . . call 141 e8/call compute-width/disp32 142 # . . discard args 143 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 144 # check-ints-equal(eax, 2, msg) 145 # . . push args 146 68/push "F - test-compute-width: 4/imm16"/imm32 147 50/push-eax 148 68/push 2/imm32 149 # . . call 150 e8/call check-ints-equal/disp32 151 # . . discard args 152 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 153 $test-compute-width:imm32: 154 # eax = compute-width("4/imm32") 155 # . . push args 156 68/push "4/imm32"/imm32 157 # . . call 158 e8/call compute-width/disp32 159 # . . discard args 160 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 161 # check-ints-equal(eax, 4, msg) 162 # . . push args 163 68/push "F - test-compute-width: 4/imm32"/imm32 164 50/push-eax 165 68/push 4/imm32 166 # . . call 167 e8/call check-ints-equal/disp32 168 # . . discard args 169 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp 170 $test-compute-width:disp8: 171 # eax = compute-width("foo/disp8") 172 # . . push args 173 68/push "foo/disp8"/imm32 174 # . . call 175 e8/call compute-width/disp32 176 # . . discard args 177 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp 178 # check-ints-equal(eax, 1, msg) 179 # . . push args 180 68/push "F - test-compute-width: foo/disp8"/imm32 181 50/push-eax 182 68/push 1/imm32 183 # . . call 184 e8/call check-ints-equal/disp32 185 # . . discard args 186 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/> Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erro