From 3046e34da8fc798fc3d340b1356c231d37d26fdf Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sat, 31 Aug 2019 22:14:11 -0700 Subject: 5595 - support ebp and esp in sigils The x86 instruction set carves out exceptions for these registers. --- html/apps/sigils.subx.html | 8089 ++++++++++++++++++++++---------------------- 1 file changed, 4106 insertions(+), 3983 deletions(-) (limited to 'html') diff --git a/html/apps/sigils.subx.html b/html/apps/sigils.subx.html index bb979e43..eb903051 100644 --- a/html/apps/sigils.subx.html +++ b/html/apps/sigils.subx.html @@ -97,4013 +97,4136 @@ if ('onhashchange' in window) { 35 # 36 # No metadata allowed inside '*(...)'. 37 # Whitespace inside '*(...)' is ok. But not immediately after the '*' or '%'. - 38 - 39 == code - 40 # instruction effective address register displacement immediate - 41 # . op subop mod rm32 base index scale r32 - 42 # . 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 - 43 - 44 Entry: # run tests if necessary, convert stdin if not - 45 # initialize heap - 46 # . Heap = new-segment(Heap-size) - 47 # . . push args - 48 68/push Heap/imm32 - 49 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Heap-size/disp32 # push *Heap-size - 50 # . . call - 51 e8/call new-segment/disp32 - 52 # . . discard args - 53 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 54 - 55 # run tests if necessary, convert stdin if not - 56 # . prolog - 57 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - 58 # - if argc > 1 and argv[1] == "test", then return run_tests() - 59 # . argc > 1 - 60 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 0/disp8 1/imm32 # compare *ebp - 61 7e/jump-if-lesser-or-equal $run-main/disp8 - 62 # . argv[1] == "test" - 63 # . . push args - 64 68/push "test"/imm32 - 65 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) - 66 # . . call - 67 e8/call kernel-string-equal?/disp32 - 68 # . . discard args - 69 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 70 # . check result - 71 3d/compare-eax-and 1/imm32 - 72 75/jump-if-not-equal $run-main/disp8 - 73 # . run-tests() - 74 e8/call run-tests/disp32 - 75 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/ebx Num-test-failures/disp32 # copy *Num-test-failures to ebx - 76 eb/jump $main:end/disp8 - 77 $run-main: - 78 # - otherwise convert stdin - 79 # convert(Stdin, Stdout) - 80 # . . push args - 81 68/push Stdout/imm32 - 82 68/push Stdin/imm32 - 83 # . . call - 84 e8/call convert/disp32 - 85 # . . discard args - 86 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 87 # . syscall(exit, 0) - 88 bb/copy-to-ebx 0/imm32 - 89 $main:end: - 90 b8/copy-to-eax 1/imm32/exit - 91 cd/syscall 0x80/imm8 - 92 - 93 # error messages considered: - 94 # *x + 34 -> error: base+disp addressing must be within '()' - 95 convert: # in : (address buffered-file), out : (address buffered-file) -> <void> - 96 # pseudocode: - 97 # var line = new-stream(512, 1) - 98 # while true - 99 # clear-stream(line) - 100 # read-line-buffered(in, line) - 101 # if (line->write == 0) break # end of file - 102 # while true - 103 # var word-slice = next-word-or-expression(line) - 104 # if slice-empty?(word-slice) # end of line - 105 # break - 106 # if slice-starts-with?(word-slice, "#") # comment - 107 # continue - 108 # if slice-starts-with?(word-slice, '%') # direct mode - 109 # emit-direct-mode(word-slice, out) - 110 # else if slice-starts-with?(word-slice, '*') # indirect mode - 111 # base, index, scale, disp = parse-effective-address(word-slice) - 112 # emit-indirect-mode(out, base, index, scale, disp) - 113 # else if slice-starts-with?(word-slice, '+') - 114 # abort("'+' only permitted within '*(...)'") - 115 # else - 116 # write-slice-buffered(out, word-slice) - 117 # write(out, " ") - 118 # write(out, "\n") - 119 # flush(out) - 120 # - 121 # . prolog - 122 55/push-ebp - 123 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - 124 # . save registers - 125 50/push-eax - 126 51/push-ecx - 127 52/push-edx - 128 53/push-ebx - 129 # var line/ecx : (address stream byte) = stream(512) - 130 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x200/imm32 # subtract from esp - 131 68/push 0x200/imm32/length - 132 68/push 0/imm32/read - 133 68/push 0/imm32/write - 134 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx - 135 # var word-slice/edx = {0, 0} - 136 68/push 0/imm32/end - 137 68/push 0/imm32/start - 138 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx - 139 $convert:line-loop: - 140 # clear-stream(line) - 141 # . . push args - 142 51/push-ecx - 143 # . . call - 144 e8/call clear-stream/disp32 - 145 # . . discard args - 146 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 147 # read-line-buffered(in, line) - 148 # . . push args - 149 51/push-ecx - 150 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) - 151 # . . call - 152 e8/call read-line-buffered/disp32 - 153 # . . discard args - 154 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 155 $convert:check0: - 156 # if (line->write == 0) break - 157 81 7/subop/compare 0/mod/indirect 1/rm32/ecx . . . . . 0/imm32 # compare *ecx - 158 0f 84/jump-if-equal $convert:break/disp32 - 159 $convert:word-loop: - 160 # next-word-or-expression(line, word-slice) - 161 # . . push args - 162 52/push-edx - 163 51/push-ecx - 164 # . . call - 165 e8/call next-word-or-expression/disp32 - 166 # . . discard args - 167 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 168 $convert:check1: - 169 # if (slice-empty?(word-slice)) break - 170 # . eax = slice-empty?(word-slice) - 171 # . . push args - 172 52/push-edx - 173 # . . call - 174 e8/call slice-empty?/disp32 - 175 # . . discard args - 176 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 177 # . if (eax != 0) break - 178 3d/compare-eax-and 0/imm32 - 179 0f 85/jump-if-not-equal $convert:next-line/disp32 - 180 $convert:check-for-comment: - 181 # if (slice-starts-with?(word-slice, "#")) continue - 182 # . start/ebx = word-slice->start - 183 8b/copy 0/mod/indirect 2/rm32/edx . . . 3/r32/ebx . . # copy *edx to ebx - 184 # . c/eax = *start - 185 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax - 186 8a/copy-byte 0/mod/indirect 3/rm32/ebx . . . 0/r32/AL . . # copy byte at *ebx to AL - 187 # . if (eax == '#') continue - 188 3d/compare-eax-and 0x23/imm32/hash - 189 74/jump-if-equal $convert:word-loop/disp8 - 190 $convert:check-for-direct-mode: - 191 # if (!slice-starts-with?(word-slice, "%")) goto next check - 192 3d/compare-eax-and 0x25/imm32/percent - 193 75/jump-if-not-equal $convert:check-for-indirect-mode/disp8 - 194 $convert:direct-mode: - 195 +-- 46 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- - 241 # emit-direct-mode(word-slice, out) - 242 # . . push args - 243 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - 244 52/push-edx - 245 # . . call - 246 e8/call emit-direct-mode/disp32 - 247 # . . discard args - 248 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 249 # continue - 250 e9/jump $convert:next-word/disp32 - 251 $convert:check-for-indirect-mode: - 252 # if (!slice-starts-with?(word-slice, "*")) goto next check - 253 3d/compare-eax-and 0x2a/imm32/asterisk - 254 75/jump-if-not-equal $convert:check-for-invalid-addition/disp8 - 255 $convert:indirect-mode: - 256 # spill registers - 257 50/push-eax - 258 51/push-ecx - 259 52/push-edx - 260 53/push-ebx - 261 # base/eax, index/ecx, scale/edx, disp/ebx = parse-effective-address(word-slice) - 262 # . . push args + 38 # + 39 # The code generated is sub-optimal: + 40 # - displacements are always disp32, even when disp8 will do + 41 # - *(...esp...) always uses SIB arguments even when redundant + 42 + 43 == code + 44 # instruction effective address register displacement immediate + 45 # . op subop mod rm32 base index scale r32 + 46 # . 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 + 47 + 48 Entry: # run tests if necessary, convert stdin if not + 49 # initialize heap + 50 # . Heap = new-segment(Heap-size) + 51 # . . push args + 52 68/push Heap/imm32 + 53 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Heap-size/disp32 # push *Heap-size + 54 # . . call + 55 e8/call new-segment/disp32 + 56 # . . discard args + 57 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 58 + 59 # run tests if necessary, convert stdin if not + 60 # . prolog + 61 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + 62 # - if argc > 1 and argv[1] == "test", then return run_tests() + 63 # . argc > 1 + 64 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 0/disp8 1/imm32 # compare *ebp + 65 7e/jump-if-lesser-or-equal $run-main/disp8 + 66 # . argv[1] == "test" + 67 # . . push args + 68 68/push "test"/imm32 + 69 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) + 70 # . . call + 71 e8/call kernel-string-equal?/disp32 + 72 # . . discard args + 73 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 74 # . check result + 75 3d/compare-eax-and 1/imm32 + 76 75/jump-if-not-equal $run-main/disp8 + 77 # . run-tests() + 78 e8/call run-tests/disp32 + 79 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/ebx Num-test-failures/disp32 # copy *Num-test-failures to ebx + 80 eb/jump $main:end/disp8 + 81 $run-main: + 82 # - otherwise convert stdin + 83 # convert(Stdin, Stdout) + 84 # . . push args + 85 68/push Stdout/imm32 + 86 68/push Stdin/imm32 + 87 # . . call + 88 e8/call convert/disp32 + 89 # . . discard args + 90 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 91 # . syscall(exit, 0) + 92 bb/copy-to-ebx 0/imm32 + 93 $main:end: + 94 b8/copy-to-eax 1/imm32/exit + 95 cd/syscall 0x80/imm8 + 96 + 97 # error messages considered: + 98 # *x + 34 -> error: base+disp addressing must be within '()' + 99 convert: # in : (address buffered-file), out : (address buffered-file) -> <void> + 100 # pseudocode: + 101 # var line = new-stream(512, 1) + 102 # while true + 103 # clear-stream(line) + 104 # read-line-buffered(in, line) + 105 # if (line->write == 0) break # end of file + 106 # while true + 107 # var word-slice = next-word-or-expression(line) + 108 # if slice-empty?(word-slice) # end of line + 109 # break + 110 # if slice-starts-with?(word-slice, "#") # comment + 111 # continue + 112 # if slice-starts-with?(word-slice, '%') # direct mode + 113 # emit-direct-mode(word-slice, out) + 114 # else if slice-starts-with?(word-slice, '*') # indirect mode + 115 # base, index, scale, disp = parse-effective-address(word-slice) + 116 # emit-indirect-mode(out, base, index, scale, disp) + 117 # else if slice-starts-with?(word-slice, '+') + 118 # abort("'+' only permitted within '*(...)'") + 119 # else + 120 # write-slice-buffered(out, word-slice) + 121 # write(out, " ") + 122 # write(out, "\n") + 123 # flush(out) + 124 # + 125 # . prolog + 126 55/push-ebp + 127 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + 128 # . save registers + 129 50/push-eax + 130 51/push-ecx + 131 52/push-edx + 132 53/push-ebx + 133 # var line/ecx : (address stream byte) = stream(512) + 134 81 5/subop/subtract 3/mod/direct 4/rm32/esp . . . . . 0x200/imm32 # subtract from esp + 135 68/push 0x200/imm32/length + 136 68/push 0/imm32/read + 137 68/push 0/imm32/write + 138 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx + 139 # var word-slice/edx = {0, 0} + 140 68/push 0/imm32/end + 141 68/push 0/imm32/start + 142 89/copy 3/mod/direct 2/rm32/edx . . . 4/r32/esp . . # copy esp to edx + 143 $convert:line-loop: + 144 # clear-stream(line) + 145 # . . push args + 146 51/push-ecx + 147 # . . call + 148 e8/call clear-stream/disp32 + 149 # . . discard args + 150 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 151 # read-line-buffered(in, line) + 152 # . . push args + 153 51/push-ecx + 154 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) + 155 # . . call + 156 e8/call read-line-buffered/disp32 + 157 # . . discard args + 158 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 159 $convert:check0: + 160 # if (line->write == 0) break + 161 81 7/subop/compare 0/mod/indirect 1/rm32/ecx . . . . . 0/imm32 # compare *ecx + 162 0f 84/jump-if-equal $convert:break/disp32 + 163 $convert:word-loop: + 164 # next-word-or-expression(line, word-slice) + 165 # . . push args + 166 52/push-edx + 167 51/push-ecx + 168 # . . call + 169 e8/call next-word-or-expression/disp32 + 170 # . . discard args + 171 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 172 $convert:check1: + 173 # if (slice-empty?(word-slice)) break + 174 # . eax = slice-empty?(word-slice) + 175 # . . push args + 176 52/push-edx + 177 # . . call + 178 e8/call slice-empty?/disp32 + 179 # . . discard args + 180 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 181 # . if (eax != 0) break + 182 3d/compare-eax-and 0/imm32 + 183 0f 85/jump-if-not-equal $convert:next-line/disp32 + 184 $convert:check-for-comment: + 185 # if (slice-starts-with?(word-slice, "#")) continue + 186 # . start/ebx = word-slice->start + 187 8b/copy 0/mod/indirect 2/rm32/edx . . . 3/r32/ebx . . # copy *edx to ebx + 188 # . c/eax = *start + 189 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax + 190 8a/copy-byte 0/mod/indirect 3/rm32/ebx . . . 0/r32/AL . . # copy byte at *ebx to AL + 191 # . if (eax == '#') continue + 192 3d/compare-eax-and 0x23/imm32/hash + 193 74/jump-if-equal $convert:word-loop/disp8 + 194 $convert:check-for-direct-mode: + 195 # if (!slice-starts-with?(word-slice, "%")) goto next check + 196 3d/compare-eax-and 0x25/imm32/percent + 197 75/jump-if-not-equal $convert:check-for-indirect-mode/disp8 + 198 $convert:direct-mode: + 199 +-- 46 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- + 245 # emit-direct-mode(word-slice, out) + 246 # . . push args + 247 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + 248 52/push-edx + 249 # . . call + 250 e8/call emit-direct-mode/disp32 + 251 # . . discard args + 252 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 253 # continue + 254 e9/jump $convert:next-word/disp32 + 255 $convert:check-for-indirect-mode: + 256 # if (!slice-starts-with?(word-slice, "*")) goto next check + 257 3d/compare-eax-and 0x2a/imm32/asterisk + 258 75/jump-if-not-equal $convert:check-for-invalid-addition/disp8 + 259 $convert:indirect-mode: + 260 # spill registers + 261 50/push-eax + 262 51/push-ecx 263 52/push-edx - 264 # . . call - 265 e8/call parse-effective-address/disp32 - 266 # . . discard args - 267 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 268 # emit-indirect-mode(out, base, index, scale, disp) - 269 # . . push args - 270 53/push-ebx - 271 52/push-edx - 272 51/push-ecx - 273 50/push-eax - 274 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - 275 # . . call - 276 e8/call emit-indirect-mode/disp32 - 277 # . . discard args - 278 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp - 279 # restore registers - 280 5b/pop-to-ebx - 281 5a/pop-to-edx - 282 59/pop-to-ecx - 283 58/pop-to-eax - 284 # continue - 285 e9/jump $convert:next-word/disp32 - 286 $convert:check-for-invalid-addition: - 287 # if (slice-starts-with?(word-slice, "+")) goto error1 - 288 3d/compare-eax-and 0x2b/imm32/plus - 289 74/jump-if-equal $convert:error1/disp8 - 290 $convert:check-for-invalid-left-shift: - 291 # if (slice-starts-with?(word-slice, "<")) goto error1 - 292 3d/compare-eax-and 0x3c/imm32/less-than + 264 53/push-ebx + 265 # base/eax, index/ecx, scale/edx, disp/ebx = parse-effective-address(word-slice) + 266 # . . push args + 267 52/push-edx + 268 # . . call + 269 e8/call parse-effective-address/disp32 + 270 # . . discard args + 271 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 272 # emit-indirect-mode(out, base, index, scale, disp) + 273 # . . push args + 274 53/push-ebx + 275 52/push-edx + 276 51/push-ecx + 277 50/push-eax + 278 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + 279 # . . call + 280 e8/call emit-indirect-mode/disp32 + 281 # . . discard args + 282 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp + 283 # restore registers + 284 5b/pop-to-ebx + 285 5a/pop-to-edx + 286 59/pop-to-ecx + 287 58/pop-to-eax + 288 # continue + 289 e9/jump $convert:next-word/disp32 + 290 $convert:check-for-invalid-addition: + 291 # if (slice-starts-with?(word-slice, "+")) goto error1 + 292 3d/compare-eax-and 0x2b/imm32/plus 293 74/jump-if-equal $convert:error1/disp8 - 294 $convert:regular-word: - 295 # write-slice-buffered(out, word-slice) - 296 # . . push args - 297 52/push-edx - 298 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - 299 # . . call - 300 e8/call write-slice-buffered/disp32 - 301 # . . discard args - 302 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 303 # fall through - 304 $convert:next-word: - 305 # write-buffered(out, " ") - 306 # . . push args - 307 68/push " "/imm32 - 308 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - 309 # . . call - 310 e8/call write-buffered/disp32 - 311 # . . discard args - 312 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 313 # loop - 314 e9/jump $convert:word-loop/disp32 - 315 $convert:next-line: - 316 # write-buffered(out, "\n") - 317 # . . push args - 318 68/push Newline/imm32 - 319 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - 320 # . . call - 321 e8/call write-buffered/disp32 - 322 # . . discard args - 323 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 324 # loop - 325 e9/jump $convert:line-loop/disp32 - 326 $convert:break: - 327 # flush(out) - 328 # . . push args - 329 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) - 330 # . . call - 331 e8/call flush/disp32 - 332 # . . discard args - 333 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 334 $convert:end: - 335 # . reclaim locals - 336 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x214/imm32 # add to esp - 337 # . restore registers - 338 5b/pop-to-ebx - 339 5a/pop-to-edx - 340 59/pop-to-ecx - 341 58/pop-to-eax - 342 # . epilog - 343 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 344 5d/pop-to-ebp - 345 c3/return - 346 - 347 $convert:error1: - 348 # print(stderr, "error: '" eax "' only permitted within '*(...)' in '" line "'") - 349 # . write-buffered(Stderr, "error: '") - 350 # . . push args - 351 68/push "error: '"/imm32 - 352 68/push Stderr/imm32 - 353 # . . call - 354 e8/call write-buffered/disp32 - 355 # . . discard args - 356 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 357 # . write-byte-buffered(Stderr, eax) - 358 # . . push args - 359 50/push-eax - 360 68/push Stderr/imm32 - 361 # . . call - 362 e8/call write-byte-buffered/disp32 - 363 # . . discard args - 364 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 365 # . write-buffered(Stderr, "' only permitted within '*(...)' in '") - 366 # . . push args - 367 68/push "' only permitted within '*(...)' in '"/imm32 - 368 68/push Stderr/imm32 - 369 # . . call - 370 e8/call write-buffered/disp32 - 371 # . . discard args - 372 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 373 # . write-stream-data(Stderr, line) - 374 # . . push args - 375 51/push-ecx - 376 68/push Stderr/imm32 - 377 # . . call - 378 e8/call write-stream-data/disp32 - 379 # . . discard args - 380 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 381 # . write-buffered(Stderr, "'") - 382 # . . push args - 383 68/push "'"/imm32 - 384 68/push Stderr/imm32 - 385 # . . call - 386 e8/call write-buffered/disp32 - 387 # . . discard args - 388 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 389 # . flush(Stderr) - 390 # . . push args - 391 68/push Stderr/imm32 - 392 # . . call - 393 e8/call flush/disp32 - 394 # . . discard args - 395 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 396 # . syscall(exit, 1) - 397 bb/copy-to-ebx 1/imm32 - 398 b8/copy-to-eax 1/imm32/exit - 399 cd/syscall 0x80/imm8 - 400 # never gets here - 401 - 402 test-convert-passes-most-words-through: - 403 # . prolog - 404 55/push-ebp - 405 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - 406 # setup - 407 # . clear-stream(_test-input-stream) - 408 # . . push args - 409 68/push _test-input-stream/imm32 - 410 # . . call - 411 e8/call clear-stream/disp32 - 412 # . . discard args - 413 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 414 # . clear-stream(_test-input-buffered-file+4) - 415 # . . push args - 416 b8/copy-to-eax _test-input-buffered-file/imm32 - 417 05/add-to-eax 4/imm32 - 418 50/push-eax - 419 # . . call - 420 e8/call clear-stream/disp32 - 421 # . . discard args - 422 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 423 # . clear-stream(_test-output-stream) - 424 # . . push args - 425 68/push _test-output-stream/imm32 - 426 # . . call - 427 e8/call clear-stream/disp32 - 428 # . . discard args - 429 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 430 # . clear-stream(_test-output-buffered-file+4) - 431 # . . push args - 432 b8/copy-to-eax _test-output-buffered-file/imm32 - 433 05/add-to-eax 4/imm32 - 434 50/push-eax - 435 # . . call - 436 e8/call clear-stream/disp32 - 437 # . . discard args - 438 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 439 # initialize input - 440 # . write(_test-input-stream, "== abcd 0x1") - 441 # . . push args - 442 68/push "== abcd 0x1"/imm32 - 443 68/push _test-input-stream/imm32 - 444 # . . call - 445 e8/call write/disp32 - 446 # . . discard args - 447 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 448 # convert(_test-input-buffered-file, _test-output-buffered-file) - 449 # . . push args - 450 68/push _test-output-buffered-file/imm32 - 451 68/push _test-input-buffered-file/imm32 - 452 # . . call - 453 e8/call convert/disp32 - 454 # . . discard args - 455 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 456 # check that the line just passed through - 457 # . flush(_test-output-buffered-file) - 458 # . . push args - 459 68/push _test-output-buffered-file/imm32 - 460 # . . call - 461 e8/call flush/disp32 - 462 # . . discard args - 463 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 464 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 490 # . check-stream-equal(_test-output-stream, "== abcd 0x1 \n", msg) - 491 # . . push args - 492 68/push "F - test-convert-passes-most-words-through"/imm32 - 493 68/push "== abcd 0x1 \n"/imm32 - 494 68/push _test-output-stream/imm32 - 495 # . . call - 496 e8/call check-stream-equal/disp32 - 497 # . . discard args - 498 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - 499 # . epilog - 500 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 501 5d/pop-to-ebp - 502 c3/return - 503 - 504 test-convert-direct-mode: - 505 # . prolog - 506 55/push-ebp - 507 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - 508 # setup - 509 # . clear-stream(_test-input-stream) - 510 # . . push args - 511 68/push _test-input-stream/imm32 - 512 # . . call - 513 e8/call clear-stream/disp32 - 514 # . . discard args - 515 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 516 # . clear-stream(_test-input-buffered-file+4) - 517 # . . push args - 518 b8/copy-to-eax _test-input-buffered-file/imm32 - 519 05/add-to-eax 4/imm32 - 520 50/push-eax - 521 # . . call - 522 e8/call clear-stream/disp32 - 523 # . . discard args - 524 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 525 # . clear-stream(_test-output-stream) - 526 # . . push args - 527 68/push _test-output-stream/imm32 - 528 # . . call - 529 e8/call clear-stream/disp32 - 530 # . . discard args - 531 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 532 # . clear-stream(_test-output-buffered-file+4) - 533 # . . push args - 534 b8/copy-to-eax _test-output-buffered-file/imm32 - 535 05/add-to-eax 4/imm32 - 536 50/push-eax - 537 # . . call - 538 e8/call clear-stream/disp32 - 539 # . . discard args - 540 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 541 # initialize input - 542 # . write(_test-input-stream, "ab %ecx") - 543 # . . push args - 544 68/push "ab %ecx"/imm32 - 545 68/push _test-input-stream/imm32 - 546 # . . call - 547 e8/call write/disp32 - 548 # . . discard args - 549 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 550 # convert(_test-input-buffered-file, _test-output-buffered-file) - 551 # . . push args - 552 68/push _test-output-buffered-file/imm32 - 553 68/push _test-input-buffered-file/imm32 - 554 # . . call - 555 e8/call convert/disp32 - 556 # . . discard args - 557 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 558 # check that the line just passed through - 559 # . flush(_test-output-buffered-file) - 560 # . . push args - 561 68/push _test-output-buffered-file/imm32 - 562 # . . call - 563 e8/call flush/disp32 - 564 # . . discard args - 565 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 566 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 592 # . check-stream-equal(_test-output-stream, "ab 3/mod/direct 0x00000001/rm32 \n", msg) - 593 # . . push args - 594 68/push "F - test-convert-direct-mode"/imm32 - 595 68/push "ab 3/mod/direct 0x00000001/rm32 \n"/imm32 - 596 68/push _test-output-stream/imm32 - 597 # . . call - 598 e8/call check-stream-equal/disp32 - 599 # . . discard args - 600 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - 601 # . epilog - 602 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 603 5d/pop-to-ebp - 604 c3/return - 605 - 606 test-convert-register-indirect-mode: - 607 # . prolog - 608 55/push-ebp - 609 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - 610 # setup - 611 # . clear-stream(_test-input-stream) - 612 # . . push args - 613 68/push _test-input-stream/imm32 - 614 # . . call - 615 e8/call clear-stream/disp32 - 616 # . . discard args - 617 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 618 # . clear-stream(_test-input-buffered-file+4) - 619 # . . push args - 620 b8/copy-to-eax _test-input-buffered-file/imm32 - 621 05/add-to-eax 4/imm32 - 622 50/push-eax - 623 # . . call - 624 e8/call clear-stream/disp32 - 625 # . . discard args - 626 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 627 # . clear-stream(_test-output-stream) - 628 # . . push args - 629 68/push _test-output-stream/imm32 - 630 # . . call - 631 e8/call clear-stream/disp32 - 632 # . . discard args - 633 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 634 # . clear-stream(_test-output-buffered-file+4) - 635 # . . push args - 636 b8/copy-to-eax _test-output-buffered-file/imm32 - 637 05/add-to-eax 4/imm32 - 638 50/push-eax - 639 # . . call - 640 e8/call clear-stream/disp32 - 641 # . . discard args - 642 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 643 # initialize input - 644 # . write(_test-input-stream, "ab *ecx") - 645 # . . push args - 646 68/push "ab *ecx"/imm32 - 647 68/push _test-input-stream/imm32 - 648 # . . call - 649 e8/call write/disp32 - 650 # . . discard args - 651 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 652 # convert(_test-input-buffered-file, _test-output-buffered-file) - 653 # . . push args - 654 68/push _test-output-buffered-file/imm32 - 655 68/push _test-input-buffered-file/imm32 - 656 # . . call - 657 e8/call convert/disp32 - 658 # . . discard args - 659 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 660 # check that the line just passed through - 661 # . flush(_test-output-buffered-file) - 662 # . . push args - 663 68/push _test-output-buffered-file/imm32 - 664 # . . call - 665 e8/call flush/disp32 - 666 # . . discard args - 667 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 668 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 694 # . check-stream-equal(_test-output-stream, "ab 0/mod/indirect 0x00000001/rm32 \n", msg) - 695 # . . push args - 696 68/push "F - test-convert-indirect-mode"/imm32 - 697 68/push "ab 0/mod/indirect 0x00000001/rm32 \n"/imm32 - 698 68/push _test-output-stream/imm32 - 699 # . . call - 700 e8/call check-stream-equal/disp32 - 701 # . . discard args - 702 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - 703 # . epilog - 704 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 705 5d/pop-to-ebp - 706 c3/return - 707 - 708 test-convert-register-indirect-mode-without-displacement: - 709 # . prolog - 710 55/push-ebp - 711 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - 712 # setup - 713 # . clear-stream(_test-input-stream) - 714 # . . push args - 715 68/push _test-input-stream/imm32 - 716 # . . call - 717 e8/call clear-stream/disp32 - 718 # . . discard args - 719 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 720 # . clear-stream(_test-input-buffered-file+4) - 721 # . . push args - 722 b8/copy-to-eax _test-input-buffered-file/imm32 - 723 05/add-to-eax 4/imm32 - 724 50/push-eax - 725 # . . call - 726 e8/call clear-stream/disp32 - 727 # . . discard args - 728 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 729 # . clear-stream(_test-output-stream) - 730 # . . push args - 731 68/push _test-output-stream/imm32 - 732 # . . call - 733 e8/call clear-stream/disp32 - 734 # . . discard args - 735 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 736 # . clear-stream(_test-output-buffered-file+4) - 737 # . . push args - 738 b8/copy-to-eax _test-output-buffered-file/imm32 - 739 05/add-to-eax 4/imm32 - 740 50/push-eax - 741 # . . call - 742 e8/call clear-stream/disp32 - 743 # . . discard args - 744 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 745 # initialize input - 746 # . write(_test-input-stream, "ab *(ecx)") - 747 # . . push args - 748 68/push "ab *(ecx)"/imm32 - 749 68/push _test-input-stream/imm32 - 750 # . . call - 751 e8/call write/disp32 - 752 # . . discard args - 753 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 754 # convert(_test-input-buffered-file, _test-output-buffered-file) - 755 # . . push args - 756 68/push _test-output-buffered-file/imm32 - 757 68/push _test-input-buffered-file/imm32 - 758 # . . call - 759 e8/call convert/disp32 - 760 # . . discard args - 761 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 762 # check that the line just passed through - 763 # . flush(_test-output-buffered-file) - 764 # . . push args - 765 68/push _test-output-buffered-file/imm32 - 766 # . . call - 767 e8/call flush/disp32 - 768 # . . discard args - 769 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 770 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 796 # . check-stream-equal(_test-output-stream, "ab 0/mod/indirect 1/rm32 \n", msg) - 797 # . . push args - 798 68/push "F - test-convert-indirect-mode-without-displacement"/imm32 - 799 68/push "ab 0/mod/indirect 0x00000001/rm32 \n"/imm32 - 800 68/push _test-output-stream/imm32 - 801 # . . call - 802 e8/call check-stream-equal/disp32 - 803 # . . discard args - 804 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - 805 # . epilog - 806 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 807 5d/pop-to-ebp - 808 c3/return - 809 - 810 test-convert-register-indirect-mode-with-displacement: - 811 # . prolog - 812 55/push-ebp - 813 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - 814 # setup - 815 # . clear-stream(_test-input-stream) - 816 # . . push args - 817 68/push _test-input-stream/imm32 - 818 # . . call - 819 e8/call clear-stream/disp32 - 820 # . . discard args - 821 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 822 # . clear-stream(_test-input-buffered-file+4) - 823 # . . push args - 824 b8/copy-to-eax _test-input-buffered-file/imm32 - 825 05/add-to-eax 4/imm32 - 826 50/push-eax - 827 # . . call - 828 e8/call clear-stream/disp32 - 829 # . . discard args - 830 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 831 # . clear-stream(_test-output-stream) - 832 # . . push args - 833 68/push _test-output-stream/imm32 - 834 # . . call - 835 e8/call clear-stream/disp32 - 836 # . . discard args - 837 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 838 # . clear-stream(_test-output-buffered-file+4) - 839 # . . push args - 840 b8/copy-to-eax _test-output-buffered-file/imm32 - 841 05/add-to-eax 4/imm32 - 842 50/push-eax - 843 # . . call - 844 e8/call clear-stream/disp32 - 845 # . . discard args - 846 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 847 # initialize input - 848 # . write(_test-input-stream, "ab *(ecx+4)") - 849 # . . push args - 850 68/push "ab *(ecx+4)"/imm32 - 851 68/push _test-input-stream/imm32 - 852 # . . call - 853 e8/call write/disp32 - 854 # . . discard args - 855 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 856 # convert(_test-input-buffered-file, _test-output-buffered-file) - 857 # . . push args - 858 68/push _test-output-buffered-file/imm32 - 859 68/push _test-input-buffered-file/imm32 - 860 # . . call - 861 e8/call convert/disp32 - 862 # . . discard args - 863 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 864 # check that the line just passed through - 865 # . flush(_test-output-buffered-file) - 866 # . . push args - 867 68/push _test-output-buffered-file/imm32 - 868 # . . call - 869 e8/call flush/disp32 - 870 # . . discard args - 871 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 872 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 898 # . check-stream-equal(_test-output-stream, "ab 2/mod/*+disp32 1/rm32 4/disp32 \n", msg) - 899 # . . push args - 900 68/push "F - test-convert-indirect-mode-with-displacement"/imm32 - 901 68/push "ab 2/mod/*+disp32 0x00000001/rm32 0x00000004/disp32 \n"/imm32 - 902 68/push _test-output-stream/imm32 - 903 # . . call - 904 e8/call check-stream-equal/disp32 - 905 # . . discard args - 906 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp - 907 # . epilog - 908 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp - 909 5d/pop-to-ebp - 910 c3/return - 911 - 912 # boss level - 913 test-convert-register-indirect-mode-with-sib-byte: - 914 # . prolog - 915 55/push-ebp - 916 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp - 917 # setup - 918 # . clear-stream(_test-input-stream) - 919 # . . push args - 920 68/push _test-input-stream/imm32 - 921 # . . call - 922 e8/call clear-stream/disp32 - 923 # . . discard args - 924 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 925 # . clear-stream(_test-input-buffered-file+4) - 926 # . . push args - 927 b8/copy-to-eax _test-input-buffered-file/imm32 - 928 05/add-to-eax 4/imm32 - 929 50/push-eax - 930 # . . call - 931 e8/call clear-stream/disp32 - 932 # . . discard args - 933 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 934 # . clear-stream(_test-output-stream) - 935 # . . push args - 936 68/push _test-output-stream/imm32 - 937 # . . call - 938 e8/call clear-stream/disp32 - 939 # . . discard args - 940 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 941 # . clear-stream(_test-output-buffered-file+4) - 942 # . . push args - 943 b8/copy-to-eax _test-output-buffered-file/imm32 - 944 05/add-to-eax 4/imm32 - 945 50/push-eax - 946 # . . call - 947 e8/call clear-stream/disp32 - 948 # . . discard args - 949 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 950 # initialize input - 951 # . write(_test-input-stream, "ab *(ecx + edx<<3 + 4)") - 952 # . . push args - 953 68/push "ab *(ecx + edx<<3 + 4)"/imm32 - 954 68/push _test-input-stream/imm32 - 955 # . . call - 956 e8/call write/disp32 - 957 # . . discard args - 958 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 959 # convert(_test-input-buffered-file, _test-output-buffered-file) - 960 # . . push args - 961 68/push _test-output-buffered-file/imm32 - 962 68/push _test-input-buffered-file/imm32 - 963 # . . call - 964 e8/call convert/disp32 - 965 # . . discard args - 966 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp - 967 # check that the line just passed through - 968 # . flush(_test-output-buffered-file) - 969 # . . push args - 970 68/push _test-output-buffered-file/imm32 - 971 # . . call - 972 e8/call flush/disp32 - 973 # . . discard args - 974 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp - 975 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1001 # . check-stream-equal(_test-output-stream, "ab 2/mod/*+disp32 4/rm32/sib 1/base 2/index 3/scale 4/disp32 \n", msg) -1002 # . . push args -1003 68/push "F - test-convert-indirect-mode-with-sib-byte"/imm32 -1004 68/push "ab 2/mod/*+disp32 4/rm32/sib 0x00000001/base 0x00000002/index 0x00000003/scale 0x00000004/disp32 \n"/imm32 -1005 68/push _test-output-stream/imm32 -1006 # . . call -1007 e8/call check-stream-equal/disp32 -1008 # . . discard args -1009 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1010 # . epilog -1011 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -1012 5d/pop-to-ebp -1013 c3/return -1014 -1015 test-convert-register-indirect-mode-with-sib-byte-negative-displacement: -1016 # . prolog -1017 55/push-ebp -1018 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -1019 # setup -1020 # . clear-stream(_test-input-stream) -1021 # . . push args -1022 68/push _test-input-stream/imm32 -1023 # . . call -1024 e8/call clear-stream/disp32 -1025 # . . discard args -1026 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1027 # . clear-stream(_test-input-buffered-file+4) -1028 # . . push args -1029 b8/copy-to-eax _test-input-buffered-file/imm32 -1030 05/add-to-eax 4/imm32 -1031 50/push-eax -1032 # . . call -1033 e8/call clear-stream/disp32 -1034 # . . discard args -1035 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1036 # . clear-stream(_test-output-stream) -1037 # . . push args -1038 68/push _test-output-stream/imm32 -1039 # . . call -1040 e8/call clear-stream/disp32 -1041 # . . discard args -1042 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1043 # . clear-stream(_test-output-buffered-file+4) -1044 # . . push args -1045 b8/copy-to-eax _test-output-buffered-file/imm32 -1046 05/add-to-eax 4/imm32 -1047 50/push-eax -1048 # . . call -1049 e8/call clear-stream/disp32 -1050 # . . discard args -1051 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1052 # initialize input -1053 # . write(_test-input-stream, "ab *(ecx + edx<<3 - 4)") -1054 # . . push args -1055 68/push "ab *(ecx + edx<<3 - 4)"/imm32 -1056 68/push _test-input-stream/imm32 -1057 # . . call -1058 e8/call write/disp32 -1059 # . . discard args -1060 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1061 # convert(_test-input-buffered-file, _test-output-buffered-file) -1062 # . . push args -1063 68/push _test-output-buffered-file/imm32 -1064 68/push _test-input-buffered-file/imm32 -1065 # . . call -1066 e8/call convert/disp32 -1067 # . . discard args -1068 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1069 # check that the line just passed through -1070 # . flush(_test-output-buffered-file) -1071 # . . push args -1072 68/push _test-output-buffered-file/imm32 -1073 # . . call -1074 e8/call flush/disp32 -1075 # . . discard args -1076 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1077 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1103 # . check-stream-equal(_test-output-stream, "ab 2/mod/*+disp32 4/rm32/sib 1/base 2/index 3/scale -4/disp32 \n", msg) -1104 # . . push args -1105 68/push "F - test-convert-indirect-mode-with-sib-byte-negative-displacement"/imm32 -1106 68/push "ab 2/mod/*+disp32 4/rm32/sib 0x00000001/base 0x00000002/index 0x00000003/scale 0xfffffffc/disp32 \n"/imm32 -1107 68/push _test-output-stream/imm32 -1108 # . . call -1109 e8/call check-stream-equal/disp32 -1110 # . . discard args -1111 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1112 # . epilog -1113 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -1114 5d/pop-to-ebp -1115 c3/return -1116 -1117 # beware: modifies 'word' -1118 emit-direct-mode: # word : (address slice), out : (address buffered-file) -1119 # . prolog -1120 55/push-ebp -1121 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -1122 # . save registers -1123 50/push-eax -1124 # ++word->start -1125 # . eax = word -1126 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax -1127 # . ++(*eax) -1128 ff 0/subop/increment 0/mod/indirect 0/rm32/eax . . . . . . # increment *eax -1129 # reg-num/eax = get-slice(Registers, word, row-size=8) -1130 # . . push args -1131 68/push "Registers"/imm32 -1132 68/push 8/imm32/row-size -1133 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -1134 68/push Registers/imm32 -1135 # . . call -1136 e8/call get-slice/disp32 -1137 # . . discard args -1138 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp -1139 # write-buffered(out, "3/mod/direct ") -1140 # . . push args -1141 68/push "3/mod/direct "/imm32 -1142 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) -1143 # . . call -1144 e8/call write-buffered/disp32 -1145 # . . discard args -1146 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1147 # print-int32-buffered(out, *eax) -1148 # . . push args -1149 ff 6/subop/push 0/mod/indirect 0/rm32/eax . . . . . . # push *eax -1150 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) -1151 # . . call -1152 e8/call print-int32-buffered/disp32 -1153 # . . discard args -1154 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1155 # write-buffered(out, "/rm32") -1156 # . . push args -1157 68/push "/rm32"/imm32 -1158 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) -1159 # . . call -1160 e8/call write-buffered/disp32 -1161 # . . discard args -1162 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1163 $emit-direct-mode:end: -1164 # . restore registers -1165 58/pop-to-eax -1166 # . epilog -1167 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -1168 5d/pop-to-ebp -1169 c3/return -1170 -1171 test-emit-direct-mode: -1172 # . prolog -1173 55/push-ebp -1174 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -1175 # setup -1176 # . clear-stream(_test-output-stream) -1177 # . . push args -1178 68/push _test-output-stream/imm32 -1179 # . . call -1180 e8/call clear-stream/disp32 -1181 # . . discard args -1182 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1183 # . clear-stream(_test-output-buffered-file+4) -1184 # . . push args -1185 b8/copy-to-eax _test-output-buffered-file/imm32 -1186 05/add-to-eax 4/imm32 -1187 50/push-eax -1188 # . . call -1189 e8/call clear-stream/disp32 -1190 # . . discard args -1191 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1192 # var slice/ecx = "%eax" -1193 b8/copy-to-eax "%eax"/imm32 -1194 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -1195 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 -1196 05/add-to-eax 4/imm32 -1197 # . ecx = {eax, ecx} -1198 51/push-ecx -1199 50/push-eax -1200 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -1201 # emit-direct-mode(str, _test-output-buffered-file) -1202 # . . push args -1203 68/push _test-output-buffered-file/imm32 -1204 51/push-ecx -1205 # . . call -1206 e8/call emit-direct-mode/disp32 -1207 # . . discard args -1208 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1209 # . flush(_test-output-buffered-file) -1210 # . . push args -1211 68/push _test-output-buffered-file/imm32 -1212 # . . call -1213 e8/call flush/disp32 -1214 # . . discard args -1215 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1216 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -1242 # check-stream-equal(_test-output-stream, "3/mod/direct 0/rm32", msg) -1243 # . . push args -1244 68/push "F - test-emit-direct-mode/0"/imm32 -1245 68/push "3/mod/direct 0x00000000/rm32"/imm32 -1246 68/push _test-output-stream/imm32 -1247 # . . call -1248 e8/call check-stream-equal/disp32 -1249 # . . discard args -1250 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1251 # . epilog -1252 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -1253 5d/pop-to-ebp -1254 c3/return -1255 -1256 test-emit-direct-mode-2: -1257 # . prolog -1258 55/push-ebp -1259 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -1260 # setup -1261 # . clear-stream(_test-output-stream) -1262 # . . push args -1263 68/push _test-output-stream/imm32 -1264 # . . call -1265 e8/call clear-stream/disp32 -1266 # . . discard args -1267 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1268 # . clear-stream(_test-output-buffered-file+4) -1269 # . . push args -1270 b8/copy-to-eax _test-output-buffered-file/imm32 -1271 05/add-to-eax 4/imm32 -1272 50/push-eax -1273 # . . call -1274 e8/call clear-stream/disp32 -1275 # . . discard args -1276 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1277 # var slice/ecx = "%edi" -1278 b8/copy-to-eax "%edi"/imm32 -1279 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -1280 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 -1281 05/add-to-eax 4/imm32 -1282 # . ecx = {eax, ecx} -1283 51/push-ecx -1284 50/push-eax -1285 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -1286 # emit-direct-mode(str/ecx, _test-output-buffered-file) -1287 # . . push args -1288 68/push _test-output-buffered-file/imm32 -1289 51/push-ecx -1290 # . . call -1291 e8/call emit-direct-mode/disp32 -1292 # . . discard args -1293 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1294 # . flush(_test-output-buffered-file) -1295 # . . push args -1296 68/push _test-output-buffered-file/imm32 -1297 # . . call -1298 e8/call flush/disp32 -1299 # . . discard args -1300 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1301 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -1327 # check-stream-equal(_test-output-stream, "3/mod/direct 7/rm32", msg) -1328 # . . push args -1329 68/push "F - test-emit-direct-mode/1"/imm32 -1330 68/push "3/mod/direct 0x00000007/rm32"/imm32 -1331 68/push _test-output-stream/imm32 -1332 # . . call -1333 e8/call check-stream-equal/disp32 -1334 # . . discard args -1335 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1336 # . epilog -1337 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -1338 5d/pop-to-ebp -1339 c3/return -1340 -1341 # (re)compute the bounds of the next word or parenthetical expression in the line -1342 # return empty string on reaching end of file -1343 # -1344 # error messages considered: -1345 # * ... -> error: no space after '*' -1346 # *(... -> error: *(...) expression must be all on a single line -1347 next-word-or-expression: # line : (address stream byte), out : (address slice) -1348 # . prolog -1349 55/push-ebp -1350 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -1351 # . save registers -1352 50/push-eax -1353 51/push-ecx -1354 56/push-esi -1355 57/push-edi -1356 # esi = line -1357 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi -1358 # edi = out -1359 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi -1360 # skip-chars-matching(line, ' ') -1361 # . . push args -1362 68/push 0x20/imm32/space -1363 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -1364 # . . call -1365 e8/call skip-chars-matching/disp32 -1366 # . . discard args -1367 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1368 $next-word-or-expression:check0: -1369 # if (line->read >= line->write) clear out and return -1370 # . eax = line->read -1371 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 0/r32/eax 4/disp8 . # copy *(esi+4) to eax -1372 # . if (eax < line->write) goto next check -1373 3b/compare 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # compare eax with *esi -1374 7c/jump-if-lesser $next-word-or-expression:check-for-comment/disp8 -1375 # . return out = {0, 0} -1376 c7 0/subop/copy 0/mod/direct 7/rm32/edi . . . . . 0/imm32 # copy to *edi -1377 c7 0/subop/copy 1/mod/*+disp8 7/rm32/edi . . . . 4/disp8 0/imm32 # copy to *(edi+4) -1378 e9/jump $next-word-or-expression:end/disp32 -1379 $next-word-or-expression:check-for-comment: -1380 # out->start = &line->data[line->read] -1381 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx -1382 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/eax 0xc/disp8 . # copy esi+ecx+12 to eax -1383 89/copy 0/mod/indirect 7/rm32/edi . . . 0/r32/eax . . # copy eax to *edi -1384 # if (line->data[line->read] != '#') goto next check -1385 # . eax = line->data[line->read] -1386 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax -1387 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL -1388 # . compare -1389 3d/compare-eax-and 0x23/imm32/pound -1390 75/jump-if-not-equal $next-word-or-expression:check-for-string-literal/disp8 -1391 $next-word-or-expression:comment: -1392 # out->end = &line->data[line->write] -1393 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax -1394 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 0/index/eax . 0/r32/eax 0xc/disp8 . # copy esi+eax+12 to eax -1395 89/copy 1/mod/*+disp8 7/rm32/edi . . . 0/r32/eax 4/disp8 . # copy eax to *(edi+4) -1396 # line->read = line->write # skip rest of line + 294 $convert:check-for-invalid-left-shift: + 295 # if (slice-starts-with?(word-slice, "<")) goto error1 + 296 3d/compare-eax-and 0x3c/imm32/less-than + 297 74/jump-if-equal $convert:error1/disp8 + 298 $convert:regular-word: + 299 # write-slice-buffered(out, word-slice) + 300 # . . push args + 301 52/push-edx + 302 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + 303 # . . call + 304 e8/call write-slice-buffered/disp32 + 305 # . . discard args + 306 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 307 # fall through + 308 $convert:next-word: + 309 # write-buffered(out, " ") + 310 # . . push args + 311 68/push " "/imm32 + 312 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + 313 # . . call + 314 e8/call write-buffered/disp32 + 315 # . . discard args + 316 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 317 # loop + 318 e9/jump $convert:word-loop/disp32 + 319 $convert:next-line: + 320 # write-buffered(out, "\n") + 321 # . . push args + 322 68/push Newline/imm32 + 323 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + 324 # . . call + 325 e8/call write-buffered/disp32 + 326 # . . discard args + 327 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 328 # loop + 329 e9/jump $convert:line-loop/disp32 + 330 $convert:break: + 331 # flush(out) + 332 # . . push args + 333 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) + 334 # . . call + 335 e8/call flush/disp32 + 336 # . . discard args + 337 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 338 $convert:end: + 339 # . reclaim locals + 340 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x214/imm32 # add to esp + 341 # . restore registers + 342 5b/pop-to-ebx + 343 5a/pop-to-edx + 344 59/pop-to-ecx + 345 58/pop-to-eax + 346 # . epilog + 347 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 348 5d/pop-to-ebp + 349 c3/return + 350 + 351 $convert:error1: + 352 # print(stderr, "error: '" eax "' only permitted within '*(...)' in '" line "'") + 353 # . write-buffered(Stderr, "error: '") + 354 # . . push args + 355 68/push "error: '"/imm32 + 356 68/push Stderr/imm32 + 357 # . . call + 358 e8/call write-buffered/disp32 + 359 # . . discard args + 360 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 361 # . write-byte-buffered(Stderr, eax) + 362 # . . push args + 363 50/push-eax + 364 68/push Stderr/imm32 + 365 # . . call + 366 e8/call write-byte-buffered/disp32 + 367 # . . discard args + 368 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 369 # . write-buffered(Stderr, "' only permitted within '*(...)' in '") + 370 # . . push args + 371 68/push "' only permitted within '*(...)' in '"/imm32 + 372 68/push Stderr/imm32 + 373 # . . call + 374 e8/call write-buffered/disp32 + 375 # . . discard args + 376 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 377 # . write-stream-data(Stderr, line) + 378 # . . push args + 379 51/push-ecx + 380 68/push Stderr/imm32 + 381 # . . call + 382 e8/call write-stream-data/disp32 + 383 # . . discard args + 384 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 385 # . write-buffered(Stderr, "'") + 386 # . . push args + 387 68/push "'"/imm32 + 388 68/push Stderr/imm32 + 389 # . . call + 390 e8/call write-buffered/disp32 + 391 # . . discard args + 392 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 393 # . flush(Stderr) + 394 # . . push args + 395 68/push Stderr/imm32 + 396 # . . call + 397 e8/call flush/disp32 + 398 # . . discard args + 399 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 400 # . syscall(exit, 1) + 401 bb/copy-to-ebx 1/imm32 + 402 b8/copy-to-eax 1/imm32/exit + 403 cd/syscall 0x80/imm8 + 404 # never gets here + 405 + 406 test-convert-passes-most-words-through: + 407 # . prolog + 408 55/push-ebp + 409 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + 410 # setup + 411 # . clear-stream(_test-input-stream) + 412 # . . push args + 413 68/push _test-input-stream/imm32 + 414 # . . call + 415 e8/call clear-stream/disp32 + 416 # . . discard args + 417 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 418 # . clear-stream(_test-input-buffered-file+4) + 419 # . . push args + 420 b8/copy-to-eax _test-input-buffered-file/imm32 + 421 05/add-to-eax 4/imm32 + 422 50/push-eax + 423 # . . call + 424 e8/call clear-stream/disp32 + 425 # . . discard args + 426 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 427 # . clear-stream(_test-output-stream) + 428 # . . push args + 429 68/push _test-output-stream/imm32 + 430 # . . call + 431 e8/call clear-stream/disp32 + 432 # . . discard args + 433 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 434 # . clear-stream(_test-output-buffered-file+4) + 435 # . . push args + 436 b8/copy-to-eax _test-output-buffered-file/imm32 + 437 05/add-to-eax 4/imm32 + 438 50/push-eax + 439 # . . call + 440 e8/call clear-stream/disp32 + 441 # . . discard args + 442 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 443 # initialize input + 444 # . write(_test-input-stream, "== abcd 0x1") + 445 # . . push args + 446 68/push "== abcd 0x1"/imm32 + 447 68/push _test-input-stream/imm32 + 448 # . . call + 449 e8/call write/disp32 + 450 # . . discard args + 451 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 452 # convert(_test-input-buffered-file, _test-output-buffered-file) + 453 # . . push args + 454 68/push _test-output-buffered-file/imm32 + 455 68/push _test-input-buffered-file/imm32 + 456 # . . call + 457 e8/call convert/disp32 + 458 # . . discard args + 459 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 460 # check that the line just passed through + 461 # . flush(_test-output-buffered-file) + 462 # . . push args + 463 68/push _test-output-buffered-file/imm32 + 464 # . . call + 465 e8/call flush/disp32 + 466 # . . discard args + 467 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 468 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 494 # . check-stream-equal(_test-output-stream, "== abcd 0x1 \n", msg) + 495 # . . push args + 496 68/push "F - test-convert-passes-most-words-through"/imm32 + 497 68/push "== abcd 0x1 \n"/imm32 + 498 68/push _test-output-stream/imm32 + 499 # . . call + 500 e8/call check-stream-equal/disp32 + 501 # . . discard args + 502 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + 503 # . epilog + 504 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 505 5d/pop-to-ebp + 506 c3/return + 507 + 508 test-convert-direct-mode: + 509 # . prolog + 510 55/push-ebp + 511 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + 512 # setup + 513 # . clear-stream(_test-input-stream) + 514 # . . push args + 515 68/push _test-input-stream/imm32 + 516 # . . call + 517 e8/call clear-stream/disp32 + 518 # . . discard args + 519 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 520 # . clear-stream(_test-input-buffered-file+4) + 521 # . . push args + 522 b8/copy-to-eax _test-input-buffered-file/imm32 + 523 05/add-to-eax 4/imm32 + 524 50/push-eax + 525 # . . call + 526 e8/call clear-stream/disp32 + 527 # . . discard args + 528 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 529 # . clear-stream(_test-output-stream) + 530 # . . push args + 531 68/push _test-output-stream/imm32 + 532 # . . call + 533 e8/call clear-stream/disp32 + 534 # . . discard args + 535 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 536 # . clear-stream(_test-output-buffered-file+4) + 537 # . . push args + 538 b8/copy-to-eax _test-output-buffered-file/imm32 + 539 05/add-to-eax 4/imm32 + 540 50/push-eax + 541 # . . call + 542 e8/call clear-stream/disp32 + 543 # . . discard args + 544 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 545 # initialize input + 546 # . write(_test-input-stream, "ab %ecx") + 547 # . . push args + 548 68/push "ab %ecx"/imm32 + 549 68/push _test-input-stream/imm32 + 550 # . . call + 551 e8/call write/disp32 + 552 # . . discard args + 553 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 554 # convert(_test-input-buffered-file, _test-output-buffered-file) + 555 # . . push args + 556 68/push _test-output-buffered-file/imm32 + 557 68/push _test-input-buffered-file/imm32 + 558 # . . call + 559 e8/call convert/disp32 + 560 # . . discard args + 561 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 562 # check that the line just passed through + 563 # . flush(_test-output-buffered-file) + 564 # . . push args + 565 68/push _test-output-buffered-file/imm32 + 566 # . . call + 567 e8/call flush/disp32 + 568 # . . discard args + 569 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 570 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 596 # . check-stream-equal(_test-output-stream, "ab 3/mod/direct 0x00000001/rm32 \n", msg) + 597 # . . push args + 598 68/push "F - test-convert-direct-mode"/imm32 + 599 68/push "ab 3/mod/direct 0x00000001/rm32 \n"/imm32 + 600 68/push _test-output-stream/imm32 + 601 # . . call + 602 e8/call check-stream-equal/disp32 + 603 # . . discard args + 604 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + 605 # . epilog + 606 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 607 5d/pop-to-ebp + 608 c3/return + 609 + 610 test-convert-register-indirect-mode: + 611 # . prolog + 612 55/push-ebp + 613 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + 614 # setup + 615 # . clear-stream(_test-input-stream) + 616 # . . push args + 617 68/push _test-input-stream/imm32 + 618 # . . call + 619 e8/call clear-stream/disp32 + 620 # . . discard args + 621 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 622 # . clear-stream(_test-input-buffered-file+4) + 623 # . . push args + 624 b8/copy-to-eax _test-input-buffered-file/imm32 + 625 05/add-to-eax 4/imm32 + 626 50/push-eax + 627 # . . call + 628 e8/call clear-stream/disp32 + 629 # . . discard args + 630 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 631 # . clear-stream(_test-output-stream) + 632 # . . push args + 633 68/push _test-output-stream/imm32 + 634 # . . call + 635 e8/call clear-stream/disp32 + 636 # . . discard args + 637 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 638 # . clear-stream(_test-output-buffered-file+4) + 639 # . . push args + 640 b8/copy-to-eax _test-output-buffered-file/imm32 + 641 05/add-to-eax 4/imm32 + 642 50/push-eax + 643 # . . call + 644 e8/call clear-stream/disp32 + 645 # . . discard args + 646 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 647 # initialize input + 648 # . write(_test-input-stream, "ab *ecx") + 649 # . . push args + 650 68/push "ab *ecx"/imm32 + 651 68/push _test-input-stream/imm32 + 652 # . . call + 653 e8/call write/disp32 + 654 # . . discard args + 655 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 656 # convert(_test-input-buffered-file, _test-output-buffered-file) + 657 # . . push args + 658 68/push _test-output-buffered-file/imm32 + 659 68/push _test-input-buffered-file/imm32 + 660 # . . call + 661 e8/call convert/disp32 + 662 # . . discard args + 663 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 664 # check that the line just passed through + 665 # . flush(_test-output-buffered-file) + 666 # . . push args + 667 68/push _test-output-buffered-file/imm32 + 668 # . . call + 669 e8/call flush/disp32 + 670 # . . discard args + 671 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 672 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 698 # . check-stream-equal(_test-output-stream, "ab 0/mod/indirect 0x00000001/rm32 \n", msg) + 699 # . . push args + 700 68/push "F - test-convert-indirect-mode"/imm32 + 701 68/push "ab 0/mod/indirect 0x00000001/rm32 \n"/imm32 + 702 68/push _test-output-stream/imm32 + 703 # . . call + 704 e8/call check-stream-equal/disp32 + 705 # . . discard args + 706 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + 707 # . epilog + 708 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 709 5d/pop-to-ebp + 710 c3/return + 711 + 712 test-convert-register-indirect-mode-without-displacement: + 713 # . prolog + 714 55/push-ebp + 715 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + 716 # setup + 717 # . clear-stream(_test-input-stream) + 718 # . . push args + 719 68/push _test-input-stream/imm32 + 720 # . . call + 721 e8/call clear-stream/disp32 + 722 # . . discard args + 723 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 724 # . clear-stream(_test-input-buffered-file+4) + 725 # . . push args + 726 b8/copy-to-eax _test-input-buffered-file/imm32 + 727 05/add-to-eax 4/imm32 + 728 50/push-eax + 729 # . . call + 730 e8/call clear-stream/disp32 + 731 # . . discard args + 732 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 733 # . clear-stream(_test-output-stream) + 734 # . . push args + 735 68/push _test-output-stream/imm32 + 736 # . . call + 737 e8/call clear-stream/disp32 + 738 # . . discard args + 739 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 740 # . clear-stream(_test-output-buffered-file+4) + 741 # . . push args + 742 b8/copy-to-eax _test-output-buffered-file/imm32 + 743 05/add-to-eax 4/imm32 + 744 50/push-eax + 745 # . . call + 746 e8/call clear-stream/disp32 + 747 # . . discard args + 748 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 749 # initialize input + 750 # . write(_test-input-stream, "ab *(ecx)") + 751 # . . push args + 752 68/push "ab *(ecx)"/imm32 + 753 68/push _test-input-stream/imm32 + 754 # . . call + 755 e8/call write/disp32 + 756 # . . discard args + 757 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 758 # convert(_test-input-buffered-file, _test-output-buffered-file) + 759 # . . push args + 760 68/push _test-output-buffered-file/imm32 + 761 68/push _test-input-buffered-file/imm32 + 762 # . . call + 763 e8/call convert/disp32 + 764 # . . discard args + 765 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 766 # check that the line just passed through + 767 # . flush(_test-output-buffered-file) + 768 # . . push args + 769 68/push _test-output-buffered-file/imm32 + 770 # . . call + 771 e8/call flush/disp32 + 772 # . . discard args + 773 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 774 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 800 # . check-stream-equal(_test-output-stream, "ab 0/mod/indirect 1/rm32 \n", msg) + 801 # . . push args + 802 68/push "F - test-convert-indirect-mode-without-displacement"/imm32 + 803 68/push "ab 0/mod/indirect 0x00000001/rm32 \n"/imm32 + 804 68/push _test-output-stream/imm32 + 805 # . . call + 806 e8/call check-stream-equal/disp32 + 807 # . . discard args + 808 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + 809 # . epilog + 810 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 811 5d/pop-to-ebp + 812 c3/return + 813 + 814 test-convert-register-indirect-mode-with-displacement: + 815 # . prolog + 816 55/push-ebp + 817 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + 818 # setup + 819 # . clear-stream(_test-input-stream) + 820 # . . push args + 821 68/push _test-input-stream/imm32 + 822 # . . call + 823 e8/call clear-stream/disp32 + 824 # . . discard args + 825 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 826 # . clear-stream(_test-input-buffered-file+4) + 827 # . . push args + 828 b8/copy-to-eax _test-input-buffered-file/imm32 + 829 05/add-to-eax 4/imm32 + 830 50/push-eax + 831 # . . call + 832 e8/call clear-stream/disp32 + 833 # . . discard args + 834 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 835 # . clear-stream(_test-output-stream) + 836 # . . push args + 837 68/push _test-output-stream/imm32 + 838 # . . call + 839 e8/call clear-stream/disp32 + 840 # . . discard args + 841 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 842 # . clear-stream(_test-output-buffered-file+4) + 843 # . . push args + 844 b8/copy-to-eax _test-output-buffered-file/imm32 + 845 05/add-to-eax 4/imm32 + 846 50/push-eax + 847 # . . call + 848 e8/call clear-stream/disp32 + 849 # . . discard args + 850 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 851 # initialize input + 852 # . write(_test-input-stream, "ab *(ecx+4)") + 853 # . . push args + 854 68/push "ab *(ecx+4)"/imm32 + 855 68/push _test-input-stream/imm32 + 856 # . . call + 857 e8/call write/disp32 + 858 # . . discard args + 859 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 860 # convert(_test-input-buffered-file, _test-output-buffered-file) + 861 # . . push args + 862 68/push _test-output-buffered-file/imm32 + 863 68/push _test-input-buffered-file/imm32 + 864 # . . call + 865 e8/call convert/disp32 + 866 # . . discard args + 867 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 868 # check that the line just passed through + 869 # . flush(_test-output-buffered-file) + 870 # . . push args + 871 68/push _test-output-buffered-file/imm32 + 872 # . . call + 873 e8/call flush/disp32 + 874 # . . discard args + 875 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 876 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 902 # . check-stream-equal(_test-output-stream, "ab 2/mod/*+disp32 1/rm32 4/disp32 \n", msg) + 903 # . . push args + 904 68/push "F - test-convert-indirect-mode-with-displacement"/imm32 + 905 68/push "ab 2/mod/*+disp32 0x00000001/rm32 0x00000004/disp32 \n"/imm32 + 906 68/push _test-output-stream/imm32 + 907 # . . call + 908 e8/call check-stream-equal/disp32 + 909 # . . discard args + 910 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp + 911 # . epilog + 912 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp + 913 5d/pop-to-ebp + 914 c3/return + 915 + 916 # boss level + 917 test-convert-register-indirect-mode-with-sib-byte: + 918 # . prolog + 919 55/push-ebp + 920 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp + 921 # setup + 922 # . clear-stream(_test-input-stream) + 923 # . . push args + 924 68/push _test-input-stream/imm32 + 925 # . . call + 926 e8/call clear-stream/disp32 + 927 # . . discard args + 928 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 929 # . clear-stream(_test-input-buffered-file+4) + 930 # . . push args + 931 b8/copy-to-eax _test-input-buffered-file/imm32 + 932 05/add-to-eax 4/imm32 + 933 50/push-eax + 934 # . . call + 935 e8/call clear-stream/disp32 + 936 # . . discard args + 937 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 938 # . clear-stream(_test-output-stream) + 939 # . . push args + 940 68/push _test-output-stream/imm32 + 941 # . . call + 942 e8/call clear-stream/disp32 + 943 # . . discard args + 944 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 945 # . clear-stream(_test-output-buffered-file+4) + 946 # . . push args + 947 b8/copy-to-eax _test-output-buffered-file/imm32 + 948 05/add-to-eax 4/imm32 + 949 50/push-eax + 950 # . . call + 951 e8/call clear-stream/disp32 + 952 # . . discard args + 953 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 954 # initialize input + 955 # . write(_test-input-stream, "ab *(ecx + edx<<3 + 4)") + 956 # . . push args + 957 68/push "ab *(ecx + edx<<3 + 4)"/imm32 + 958 68/push _test-input-stream/imm32 + 959 # . . call + 960 e8/call write/disp32 + 961 # . . discard args + 962 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 963 # convert(_test-input-buffered-file, _test-output-buffered-file) + 964 # . . push args + 965 68/push _test-output-buffered-file/imm32 + 966 68/push _test-input-buffered-file/imm32 + 967 # . . call + 968 e8/call convert/disp32 + 969 # . . discard args + 970 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp + 971 # check that the line just passed through + 972 # . flush(_test-output-buffered-file) + 973 # . . push args + 974 68/push _test-output-buffered-file/imm32 + 975 # . . call + 976 e8/call flush/disp32 + 977 # . . discard args + 978 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp + 979 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1005 # . check-stream-equal(_test-output-stream, "ab 2/mod/*+disp32 4/rm32/sib 1/base 2/index 3/scale 4/disp32 \n", msg) +1006 # . . push args +1007 68/push "F - test-convert-indirect-mode-with-sib-byte"/imm32 +1008 68/push "ab 2/mod/*+disp32 4/rm32/sib 0x00000001/base 0x00000002/index 0x00000003/scale 0x00000004/disp32 \n"/imm32 +1009 68/push _test-output-stream/imm32 +1010 # . . call +1011 e8/call check-stream-equal/disp32 +1012 # . . discard args +1013 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1014 # . epilog +1015 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +1016 5d/pop-to-ebp +1017 c3/return +1018 +1019 test-convert-register-indirect-mode-with-sib-byte-negative-displacement: +1020 # . prolog +1021 55/push-ebp +1022 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +1023 # setup +1024 # . clear-stream(_test-input-stream) +1025 # . . push args +1026 68/push _test-input-stream/imm32 +1027 # . . call +1028 e8/call clear-stream/disp32 +1029 # . . discard args +1030 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1031 # . clear-stream(_test-input-buffered-file+4) +1032 # . . push args +1033 b8/copy-to-eax _test-input-buffered-file/imm32 +1034 05/add-to-eax 4/imm32 +1035 50/push-eax +1036 # . . call +1037 e8/call clear-stream/disp32 +1038 # . . discard args +1039 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1040 # . clear-stream(_test-output-stream) +1041 # . . push args +1042 68/push _test-output-stream/imm32 +1043 # . . call +1044 e8/call clear-stream/disp32 +1045 # . . discard args +1046 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1047 # . clear-stream(_test-output-buffered-file+4) +1048 # . . push args +1049 b8/copy-to-eax _test-output-buffered-file/imm32 +1050 05/add-to-eax 4/imm32 +1051 50/push-eax +1052 # . . call +1053 e8/call clear-stream/disp32 +1054 # . . discard args +1055 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1056 # initialize input +1057 # . write(_test-input-stream, "ab *(ecx + edx<<3 - 4)") +1058 # . . push args +1059 68/push "ab *(ecx + edx<<3 - 4)"/imm32 +1060 68/push _test-input-stream/imm32 +1061 # . . call +1062 e8/call write/disp32 +1063 # . . discard args +1064 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1065 # convert(_test-input-buffered-file, _test-output-buffered-file) +1066 # . . push args +1067 68/push _test-output-buffered-file/imm32 +1068 68/push _test-input-buffered-file/imm32 +1069 # . . call +1070 e8/call convert/disp32 +1071 # . . discard args +1072 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1073 # check that the line just passed through +1074 # . flush(_test-output-buffered-file) +1075 # . . push args +1076 68/push _test-output-buffered-file/imm32 +1077 # . . call +1078 e8/call flush/disp32 +1079 # . . discard args +1080 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1081 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1107 # . check-stream-equal(_test-output-stream, "ab 2/mod/*+disp32 4/rm32/sib 1/base 2/index 3/scale -4/disp32 \n", msg) +1108 # . . push args +1109 68/push "F - test-convert-indirect-mode-with-sib-byte-negative-displacement"/imm32 +1110 68/push "ab 2/mod/*+disp32 4/rm32/sib 0x00000001/base 0x00000002/index 0x00000003/scale 0xfffffffc/disp32 \n"/imm32 +1111 68/push _test-output-stream/imm32 +1112 # . . call +1113 e8/call check-stream-equal/disp32 +1114 # . . discard args +1115 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1116 # . epilog +1117 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +1118 5d/pop-to-ebp +1119 c3/return +1120 +1121 # beware: modifies 'word' +1122 emit-direct-mode: # word : (address slice), out : (address buffered-file) +1123 # . prolog +1124 55/push-ebp +1125 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +1126 # . save registers +1127 50/push-eax +1128 # ++word->start +1129 # . eax = word +1130 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 0/r32/eax 8/disp8 . # copy *(ebp+8) to eax +1131 # . ++(*eax) +1132 ff 0/subop/increment 0/mod/indirect 0/rm32/eax . . . . . . # increment *eax +1133 # reg-num/eax = get-slice(Registers, word, row-size=8) +1134 # . . push args +1135 68/push "Registers"/imm32 +1136 68/push 8/imm32/row-size +1137 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +1138 68/push Registers/imm32 +1139 # . . call +1140 e8/call get-slice/disp32 +1141 # . . discard args +1142 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp +1143 # write-buffered(out, "3/mod/direct ") +1144 # . . push args +1145 68/push "3/mod/direct "/imm32 +1146 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) +1147 # . . call +1148 e8/call write-buffered/disp32 +1149 # . . discard args +1150 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1151 # print-int32-buffered(out, *eax) +1152 # . . push args +1153 ff 6/subop/push 0/mod/indirect 0/rm32/eax . . . . . . # push *eax +1154 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) +1155 # . . call +1156 e8/call print-int32-buffered/disp32 +1157 # . . discard args +1158 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1159 # write-buffered(out, "/rm32") +1160 # . . push args +1161 68/push "/rm32"/imm32 +1162 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) +1163 # . . call +1164 e8/call write-buffered/disp32 +1165 # . . discard args +1166 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1167 $emit-direct-mode:end: +1168 # . restore registers +1169 58/pop-to-eax +1170 # . epilog +1171 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +1172 5d/pop-to-ebp +1173 c3/return +1174 +1175 test-emit-direct-mode: +1176 # . prolog +1177 55/push-ebp +1178 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +1179 # setup +1180 # . clear-stream(_test-output-stream) +1181 # . . push args +1182 68/push _test-output-stream/imm32 +1183 # . . call +1184 e8/call clear-stream/disp32 +1185 # . . discard args +1186 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1187 # . clear-stream(_test-output-buffered-file+4) +1188 # . . push args +1189 b8/copy-to-eax _test-output-buffered-file/imm32 +1190 05/add-to-eax 4/imm32 +1191 50/push-eax +1192 # . . call +1193 e8/call clear-stream/disp32 +1194 # . . discard args +1195 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1196 # var slice/ecx = "%eax" +1197 b8/copy-to-eax "%eax"/imm32 +1198 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +1199 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 +1200 05/add-to-eax 4/imm32 +1201 # . ecx = {eax, ecx} +1202 51/push-ecx +1203 50/push-eax +1204 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +1205 # emit-direct-mode(str, _test-output-buffered-file) +1206 # . . push args +1207 68/push _test-output-buffered-file/imm32 +1208 51/push-ecx +1209 # . . call +1210 e8/call emit-direct-mode/disp32 +1211 # . . discard args +1212 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1213 # . flush(_test-output-buffered-file) +1214 # . . push args +1215 68/push _test-output-buffered-file/imm32 +1216 # . . call +1217 e8/call flush/disp32 +1218 # . . discard args +1219 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1220 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +1246 # check-stream-equal(_test-output-stream, "3/mod/direct 0/rm32", msg) +1247 # . . push args +1248 68/push "F - test-emit-direct-mode/0"/imm32 +1249 68/push "3/mod/direct 0x00000000/rm32"/imm32 +1250 68/push _test-output-stream/imm32 +1251 # . . call +1252 e8/call check-stream-equal/disp32 +1253 # . . discard args +1254 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1255 # . epilog +1256 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +1257 5d/pop-to-ebp +1258 c3/return +1259 +1260 test-emit-direct-mode-2: +1261 # . prolog +1262 55/push-ebp +1263 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +1264 # setup +1265 # . clear-stream(_test-output-stream) +1266 # . . push args +1267 68/push _test-output-stream/imm32 +1268 # . . call +1269 e8/call clear-stream/disp32 +1270 # . . discard args +1271 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1272 # . clear-stream(_test-output-buffered-file+4) +1273 # . . push args +1274 b8/copy-to-eax _test-output-buffered-file/imm32 +1275 05/add-to-eax 4/imm32 +1276 50/push-eax +1277 # . . call +1278 e8/call clear-stream/disp32 +1279 # . . discard args +1280 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1281 # var slice/ecx = "%edi" +1282 b8/copy-to-eax "%edi"/imm32 +1283 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +1284 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 +1285 05/add-to-eax 4/imm32 +1286 # . ecx = {eax, ecx} +1287 51/push-ecx +1288 50/push-eax +1289 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +1290 # emit-direct-mode(str/ecx, _test-output-buffered-file) +1291 # . . push args +1292 68/push _test-output-buffered-file/imm32 +1293 51/push-ecx +1294 # . . call +1295 e8/call emit-direct-mode/disp32 +1296 # . . discard args +1297 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1298 # . flush(_test-output-buffered-file) +1299 # . . push args +1300 68/push _test-output-buffered-file/imm32 +1301 # . . call +1302 e8/call flush/disp32 +1303 # . . discard args +1304 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1305 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +1331 # check-stream-equal(_test-output-stream, "3/mod/direct 7/rm32", msg) +1332 # . . push args +1333 68/push "F - test-emit-direct-mode/1"/imm32 +1334 68/push "3/mod/direct 0x00000007/rm32"/imm32 +1335 68/push _test-output-stream/imm32 +1336 # . . call +1337 e8/call check-stream-equal/disp32 +1338 # . . discard args +1339 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1340 # . epilog +1341 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +1342 5d/pop-to-ebp +1343 c3/return +1344 +1345 # (re)compute the bounds of the next word or parenthetical expression in the line +1346 # return empty string on reaching end of file +1347 # +1348 # error messages considered: +1349 # * ... -> error: no space after '*' +1350 # *(... -> error: *(...) expression must be all on a single line +1351 next-word-or-expression: # line : (address stream byte), out : (address slice) +1352 # . prolog +1353 55/push-ebp +1354 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +1355 # . save registers +1356 50/push-eax +1357 51/push-ecx +1358 56/push-esi +1359 57/push-edi +1360 # esi = line +1361 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi +1362 # edi = out +1363 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 7/r32/edi 0xc/disp8 . # copy *(ebp+12) to edi +1364 # skip-chars-matching(line, ' ') +1365 # . . push args +1366 68/push 0x20/imm32/space +1367 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +1368 # . . call +1369 e8/call skip-chars-matching/disp32 +1370 # . . discard args +1371 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1372 $next-word-or-expression:check0: +1373 # if (line->read >= line->write) clear out and return +1374 # . eax = line->read +1375 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 0/r32/eax 4/disp8 . # copy *(esi+4) to eax +1376 # . if (eax < line->write) goto next check +1377 3b/compare 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # compare eax with *esi +1378 7c/jump-if-lesser $next-word-or-expression:check-for-comment/disp8 +1379 # . return out = {0, 0} +1380 c7 0/subop/copy 0/mod/direct 7/rm32/edi . . . . . 0/imm32 # copy to *edi +1381 c7 0/subop/copy 1/mod/*+disp8 7/rm32/edi . . . . 4/disp8 0/imm32 # copy to *(edi+4) +1382 e9/jump $next-word-or-expression:end/disp32 +1383 $next-word-or-expression:check-for-comment: +1384 # out->start = &line->data[line->read] +1385 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx +1386 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/eax 0xc/disp8 . # copy esi+ecx+12 to eax +1387 89/copy 0/mod/indirect 7/rm32/edi . . . 0/r32/eax . . # copy eax to *edi +1388 # if (line->data[line->read] != '#') goto next check +1389 # . eax = line->data[line->read] +1390 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax +1391 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL +1392 # . compare +1393 3d/compare-eax-and 0x23/imm32/pound +1394 75/jump-if-not-equal $next-word-or-expression:check-for-string-literal/disp8 +1395 $next-word-or-expression:comment: +1396 # out->end = &line->data[line->write] 1397 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax -1398 89/copy 1/mod/*+disp8 6/rm32/esi . . . 0/r32/eax 4/disp8 . # copy eax to *(esi+4) -1399 # return -1400 eb/jump $next-word-or-expression:end/disp8 -1401 $next-word-or-expression:check-for-string-literal: -1402 # if (line->data[line->read] != '"') goto next check -1403 # . eax = line->data[line->read] -1404 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax -1405 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL -1406 # . compare -1407 3d/compare-eax-and 0x22/imm32/dquote -1408 75/jump-if-not-equal $next-word-or-expression:check-for-paren/disp8 -1409 $next-word-or-expression:string-literal: -1410 # skip-string(line) -1411 # . . push args -1412 56/push-esi -1413 # . . call -1414 e8/call skip-string/disp32 -1415 # . . discard args -1416 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1417 # skip rest of word -1418 eb/jump $next-word-or-expression:regular-word/disp8 -1419 $next-word-or-expression:check-for-paren: -1420 # if (line->data[line->read] != '*') goto next check -1421 # . eax = line->data[line->read] -1422 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax -1423 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL -1424 # . compare -1425 3d/compare-eax-and 0x2a/imm32/asterisk -1426 75/jump-if-not-equal $next-word-or-expression:regular-word/disp8 -1427 # if (line->data[line->read] == ' ') goto error1 -1428 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xd/disp8 . # copy byte at *(esi+ecx+12+1) to AL -1429 # . compare -1430 3d/compare-eax-and 0x20/imm32/space -1431 74/jump-if-equal $next-word-or-expression:error1/disp8 -1432 # if (line->data[line->read] != '(') goto regular word -1433 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xd/disp8 . # copy byte at *(esi+ecx+12+1) to AL -1434 # . compare -1435 3d/compare-eax-and 0x28/imm32/open-paren -1436 75/jump-if-not-equal $next-word-or-expression:regular-word/disp8 -1437 $next-word-or-expression:paren: -1438 # skip-until-close-paren(line) -1439 # . . push args -1440 56/push-esi -1441 # . . call -1442 e8/call skip-until-close-paren/disp32 -1443 # . . discard args -1444 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1445 # if (line->data[line->read] != ')') goto error2 -1446 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx -1447 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL -1448 # . compare -1449 3d/compare-eax-and 0x29/imm32/close-paren -1450 75/jump-if-not-equal $next-word-or-expression:error2/disp8 -1451 # skip ')' -1452 ff 0/subop/increment 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # increment *(esi+4) -1453 # fall through -1454 $next-word-or-expression:regular-word: -1455 # skip-chars-not-matching-whitespace(line) # including trailing newline -1456 # . . push args -1457 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -1458 # . . call -1459 e8/call skip-chars-not-matching-whitespace/disp32 -1460 # . . discard args -1461 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1462 # out->end = &line->data[line->read] -1463 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx -1464 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/eax 0xc/disp8 . # copy esi+ecx+12 to eax -1465 89/copy 1/mod/*+disp8 7/rm32/edi . . . 0/r32/eax 4/disp8 . # copy eax to *(edi+4) -1466 $next-word-or-expression:end: -1467 # . restore registers -1468 5f/pop-to-edi -1469 5e/pop-to-esi -1470 59/pop-to-ecx -1471 58/pop-to-eax -1472 # . epilog -1473 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -1474 5d/pop-to-ebp -1475 c3/return -1476 -1477 $next-word-or-expression:error1: -1478 # print(stderr, "error: no space allowed after '*' in '" line "'") -1479 # . write-buffered(Stderr, "error: no space allowed after '*' in '") -1480 # . . push args -1481 68/push "error: no space allowed after '*' in '"/imm32 -1482 68/push Stderr/imm32 -1483 # . . call -1484 e8/call write-buffered/disp32 -1485 # . . discard args -1486 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1487 # . write-stream-data(Stderr, line) -1488 # . . push args -1489 56/push-esi -1490 68/push Stderr/imm32 -1491 # . . call -1492 e8/call write-stream-data/disp32 -1493 # . . discard args -1494 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1495 # . write-buffered(Stderr, "'") -1496 # . . push args -1497 68/push "'"/imm32 -1498 68/push Stderr/imm32 -1499 # . . call -1500 e8/call write-buffered/disp32 -1501 # . . discard args -1502 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1503 # . flush(Stderr) -1504 # . . push args -1505 68/push Stderr/imm32 -1506 # . . call -1507 e8/call flush/disp32 -1508 # . . discard args -1509 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1510 # . syscall(exit, 1) -1511 bb/copy-to-ebx 1/imm32 -1512 b8/copy-to-eax 1/imm32/exit -1513 cd/syscall 0x80/imm8 -1514 # never gets here -1515 -1516 $next-word-or-expression:error2: -1517 # print(stderr, "error: no space allowed after '*' in '" line "'") -1518 # . write-buffered(Stderr, "error: *(...) expression must be all on a single line in '") -1519 # . . push args -1520 68/push "error: *(...) expression must be all on a single line in '"/imm32 -1521 68/push Stderr/imm32 -1522 # . . call -1523 e8/call write-buffered/disp32 -1524 # . . discard args -1525 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1526 # . write-stream-data(Stderr, line) -1527 # . . push args -1528 56/push-esi -1529 68/push Stderr/imm32 -1530 # . . call -1531 e8/call write-stream-data/disp32 -1532 # . . discard args -1533 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1534 # . write-buffered(Stderr, "'") -1535 # . . push args -1536 68/push "'"/imm32 -1537 68/push Stderr/imm32 -1538 # . . call -1539 e8/call write-buffered/disp32 -1540 # . . discard args -1541 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1542 # . flush(Stderr) -1543 # . . push args -1544 68/push Stderr/imm32 -1545 # . . call -1546 e8/call flush/disp32 -1547 # . . discard args -1548 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1549 # . syscall(exit, 1) -1550 bb/copy-to-ebx 1/imm32 -1551 b8/copy-to-eax 1/imm32/exit -1552 cd/syscall 0x80/imm8 -1553 # never gets here -1554 -1555 test-next-word-or-expression: -1556 # . prolog -1557 55/push-ebp -1558 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -1559 # setup -1560 # . clear-stream(_test-input-stream) -1561 # . . push args -1562 68/push _test-input-stream/imm32 -1563 # . . call -1564 e8/call clear-stream/disp32 -1565 # . . discard args -1566 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1567 # var slice/ecx = {0, 0} -1568 68/push 0/imm32/end -1569 68/push 0/imm32/start -1570 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -1571 # write(_test-input-stream, " ab") -1572 # . . push args -1573 68/push " ab"/imm32 -1574 68/push _test-input-stream/imm32 -1575 # . . call -1576 e8/call write/disp32 -1577 # . . discard args -1578 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1579 # next-word-or-expression(_test-input-stream, slice) -1580 # . . push args -1581 51/push-ecx -1582 68/push _test-input-stream/imm32 -1583 # . . call -1584 e8/call next-word-or-expression/disp32 -1585 # . . discard args -1586 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1587 # check-ints-equal(_test-input-stream->read, 4, msg) -1588 # . . push args -1589 68/push "F - test-next-word-or-expression/updates-stream-read-correctly"/imm32 -1590 68/push 4/imm32 -1591 b8/copy-to-eax _test-input-stream/imm32 -1592 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) -1593 # . . call -1594 e8/call check-ints-equal/disp32 -1595 # . . discard args -1596 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1597 # check-ints-equal(slice->start - _test-input-stream->data, 2, msg) -1598 # . check-ints-equal(slice->start - _test-input-stream, 14, msg) -1599 # . . push args -1600 68/push "F - test-next-word-or-expression: start"/imm32 -1601 68/push 0xe/imm32 -1602 # . . push slice->start - _test-input-stream -1603 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax -1604 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax -1605 50/push-eax -1606 # . . call -1607 e8/call check-ints-equal/disp32 -1608 # . . discard args -1609 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1610 # check-ints-equal(slice->end - _test-input-stream->data, 4, msg) -1611 # . check-ints-equal(slice->end - _test-input-stream, 16, msg) -1612 # . . push args -1613 68/push "F - test-next-word-or-expression: end"/imm32 -1614 68/push 0x10/imm32 -1615 # . . push slice->end - _test-input-stream -1616 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax -1617 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax -1618 50/push-eax -1619 # . . call -1620 e8/call check-ints-equal/disp32 -1621 # . . discard args -1622 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1623 # . epilog -1624 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -1625 5d/pop-to-ebp -1626 c3/return -1627 -1628 test-next-word-or-expression-returns-whole-comment: -1629 # . prolog -1630 55/push-ebp -1631 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -1632 # setup -1633 # . clear-stream(_test-input-stream) -1634 # . . push args -1635 68/push _test-input-stream/imm32 -1636 # . . call -1637 e8/call clear-stream/disp32 -1638 # . . discard args -1639 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1640 # var slice/ecx = {0, 0} -1641 68/push 0/imm32/end -1642 68/push 0/imm32/start -1643 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -1644 # write(_test-input-stream, " # a") -1645 # . . push args -1646 68/push " # a"/imm32 -1647 68/push _test-input-stream/imm32 -1648 # . . call -1649 e8/call write/disp32 -1650 # . . discard args -1651 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1652 # next-word-or-expression(_test-input-stream, slice) -1653 # . . push args -1654 51/push-ecx -1655 68/push _test-input-stream/imm32 -1656 # . . call -1657 e8/call next-word-or-expression/disp32 -1658 # . . discard args -1659 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1660 # check-ints-equal(_test-input-stream->read, 5, msg) -1661 # . . push args -1662 68/push "F - test-next-word-or-expression-returns-whole-comment/updates-stream-read-correctly"/imm32 -1663 68/push 5/imm32 -1664 b8/copy-to-eax _test-input-stream/imm32 -1665 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) -1666 # . . call -1667 e8/call check-ints-equal/disp32 -1668 # . . discard args -1669 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1670 # check-ints-equal(slice->start - _test-input-stream->data, 2, msg) -1671 # . check-ints-equal(slice->start - _test-input-stream, 14, msg) -1672 # . . push args -1673 68/push "F - test-next-word-or-expression-returns-whole-comment: start"/imm32 -1674 68/push 0xe/imm32 -1675 # . . push slice->start - _test-input-stream -1676 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax -1677 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax -1678 50/push-eax -1679 # . . call -1680 e8/call check-ints-equal/disp32 -1681 # . . discard args -1682 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1683 # check-ints-equal(slice->end - _test-input-stream->data, 5, msg) -1684 # . check-ints-equal(slice->end - _test-input-stream, 17, msg) -1685 # . . push args -1686 68/push "F - test-next-word-or-expression-returns-whole-comment: end"/imm32 -1687 68/push 0x11/imm32 -1688 # . . push slice->end - _test-input-stream -1689 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax -1690 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax -1691 50/push-eax -1692 # . . call -1693 e8/call check-ints-equal/disp32 -1694 # . . discard args -1695 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1696 # . epilog -1697 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -1698 5d/pop-to-ebp -1699 c3/return -1700 -1701 test-next-word-or-expression-returns-empty-slice-on-eof: -1702 # . prolog -1703 55/push-ebp -1704 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -1705 # setup -1706 # . clear-stream(_test-input-stream) -1707 # . . push args -1708 68/push _test-input-stream/imm32 -1709 # . . call -1710 e8/call clear-stream/disp32 -1711 # . . discard args -1712 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1713 # var slice/ecx = {0, 0} -1714 68/push 0/imm32/end -1715 68/push 0/imm32/start -1716 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -1717 # write nothing to _test-input-stream -1718 # next-word-or-expression(_test-input-stream, slice) -1719 # . . push args -1720 51/push-ecx -1721 68/push _test-input-stream/imm32 -1722 # . . call -1723 e8/call next-word-or-expression/disp32 -1724 # . . discard args -1725 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1726 # check-ints-equal(slice->end - slice->start, 0, msg) -1727 # . . push args -1728 68/push "F - test-next-word-or-expression-returns-empty-expression-on-eof"/imm32 -1729 68/push 0/imm32 -1730 # . . push slice->end - slice->start -1731 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax -1732 2b/subtract 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # subtract *ecx from eax -1733 50/push-eax -1734 # . . call -1735 e8/call check-ints-equal/disp32 -1736 # . . discard args -1737 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1738 # . epilog -1739 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -1740 5d/pop-to-ebp -1741 c3/return -1742 -1743 test-next-word-or-expression-returns-string-literal: -1744 # . prolog -1745 55/push-ebp -1746 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -1747 # setup -1748 # . clear-stream(_test-input-stream) -1749 # . . push args -1750 68/push _test-input-stream/imm32 -1751 # . . call -1752 e8/call clear-stream/disp32 -1753 # . . discard args -1754 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1755 # var slice/ecx = {0, 0} -1756 68/push 0/imm32/end -1757 68/push 0/imm32/start -1758 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -1759 # write(_test-input-stream, " \"a b\"/imm32 ") -1760 # . . push args -1761 68/push " \"a b\"/imm32 "/imm32 -1762 68/push _test-input-stream/imm32 -1763 # . . call -1764 e8/call write/disp32 -1765 # . . discard args -1766 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1767 # next-word-or-expression(_test-input-stream, slice) -1768 # . . push args -1769 51/push-ecx -1770 68/push _test-input-stream/imm32 -1771 # . . call -1772 e8/call next-word-or-expression/disp32 -1773 # . . discard args -1774 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1775 # check-ints-equal(slice->start - _test-input-stream->data, 1, msg) -1776 # . check-ints-equal(slice->start - _test-input-stream, 13, msg) -1777 # . . push args -1778 68/push "F - test-next-word-or-expression-returns-string-literal: start"/imm32 -1779 68/push 0xd/imm32 -1780 # . . push slice->start - _test-input-stream -1781 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax -1782 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax -1783 50/push-eax -1784 # . . call -1785 e8/call check-ints-equal/disp32 -1786 # . . discard args -1787 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1788 # check-ints-equal(slice->end - _test-input-stream->data, 12, msg) -1789 # . check-ints-equal(slice->end - _test-input-stream, 24, msg) -1790 # . . push args -1791 68/push "F - test-next-word-or-expression-returns-string-literal: end"/imm32 -1792 68/push 0x18/imm32 -1793 # . . push slice->end - _test-input-stream -1794 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax -1795 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax -1796 50/push-eax -1797 # . . call -1798 e8/call check-ints-equal/disp32 -1799 # . . discard args -1800 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1801 # . epilog -1802 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -1803 5d/pop-to-ebp -1804 c3/return -1805 -1806 test-next-word-or-expression-returns-string-with-escapes: -1807 # . prolog -1808 55/push-ebp -1809 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -1810 # setup -1811 # . clear-stream(_test-input-stream) -1812 # . . push args -1813 68/push _test-input-stream/imm32 -1814 # . . call -1815 e8/call clear-stream/disp32 -1816 # . . discard args -1817 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1818 # var slice/ecx = {0, 0} -1819 68/push 0/imm32/end -1820 68/push 0/imm32/start -1821 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -1822 # write(_test-input-stream, " \"a\\\"b\"/x") -1823 # . . push args -1824 68/push " \"a\\\"b\"/x"/imm32 -1825 68/push _test-input-stream/imm32 -1826 # . . call -1827 e8/call write/disp32 -1828 # . . discard args -1829 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1830 # next-word-or-expression(_test-input-stream, slice) -1831 # . . push args -1832 51/push-ecx -1833 68/push _test-input-stream/imm32 -1834 # . . call -1835 e8/call next-word-or-expression/disp32 -1836 # . . discard args -1837 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1838 # check-ints-equal(slice->start - _test-input-stream->data, 1, msg) -1839 # . check-ints-equal(slice->start - _test-input-stream, 13, msg) -1840 # . . push args -1841 68/push "F - test-next-word-or-expression-returns-string-with-escapes: start"/imm32 -1842 68/push 0xd/imm32 -1843 # . . push slice->start - _test-input-stream -1844 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax -1845 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax -1846 50/push-eax -1847 # . . call -1848 e8/call check-ints-equal/disp32 -1849 # . . discard args -1850 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1851 # check-ints-equal(slice->end - _test-input-stream->data, 9, msg) -1852 # . check-ints-equal(slice->end - _test-input-stream, 21, msg) -1853 # . . push args -1854 68/push "F - test-next-word-or-expression-returns-string-with-escapes: end"/imm32 -1855 68/push 0x15/imm32 -1856 # . . push slice->end - _test-input-stream -1857 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax -1858 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax -1859 50/push-eax -1860 # . . call -1861 e8/call check-ints-equal/disp32 -1862 # . . discard args -1863 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1864 # . epilog -1865 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -1866 5d/pop-to-ebp -1867 c3/return -1868 -1869 test-next-word-or-expression-returns-whole-expression: -1870 # . prolog -1871 55/push-ebp -1872 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -1873 # setup -1874 # . clear-stream(_test-input-stream) -1875 # . . push args -1876 68/push _test-input-stream/imm32 -1877 # . . call -1878 e8/call clear-stream/disp32 -1879 # . . discard args -1880 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -1881 # var slice/ecx = {0, 0} -1882 68/push 0/imm32/end -1883 68/push 0/imm32/start -1884 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -1885 # write(_test-input-stream, " *(a b)/imm32 ") -1886 # . . push args -1887 68/push " *(a b)/imm32 "/imm32 -1888 68/push _test-input-stream/imm32 -1889 # . . call -1890 e8/call write/disp32 -1891 # . . discard args -1892 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1893 # next-word-or-expression(_test-input-stream, slice) -1894 # . . push args -1895 51/push-ecx -1896 68/push _test-input-stream/imm32 -1897 # . . call -1898 e8/call next-word-or-expression/disp32 -1899 # . . discard args -1900 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -1901 # check-ints-equal(slice->start - _test-input-stream->data, 1, msg) -1902 # . check-ints-equal(slice->start - _test-input-stream, 13, msg) -1903 # . . push args -1904 68/push "F - test-next-word-or-expression-returns-whole-expression: start"/imm32 -1905 68/push 0xd/imm32 -1906 # . . push slice->start - _test-input-stream -1907 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax -1908 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax -1909 50/push-eax -1910 # . . call -1911 e8/call check-ints-equal/disp32 -1912 # . . discard args -1913 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1914 # check-ints-equal(slice->end - _test-input-stream->data, 13, msg) -1915 # . check-ints-equal(slice->end - _test-input-stream, 25, msg) -1916 # . . push args -1917 68/push "F - test-next-word-or-expression-returns-whole-expression: end"/imm32 -1918 68/push 0x19/imm32 -1919 # . . push slice->end - _test-input-stream -1920 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax -1921 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax -1922 50/push-eax -1923 # . . call -1924 e8/call check-ints-equal/disp32 -1925 # . . discard args -1926 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -1927 # . epilog -1928 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -1929 5d/pop-to-ebp -1930 c3/return -1931 -1932 # Grammar: -1933 # *reg -> 0/mod reg/rm32 -1934 # *(reg) -> 0/mod reg/rm32 -1935 # *(reg+disp) -> 2/mod reg/rm32 disp/disp32 -1936 # *(reg1+reg2<<s) -> 2/mod 4/rm32 reg1/base reg2/index s/scale 0/disp32 -1937 # *(reg1+reg2<<s+disp) -> 2/mod 4/rm32 reg1/base reg2/index s/scale disp/disp32 -1938 # Intermediate structure: base, index, scale, disp -1939 # Default values: base: 0, index: 4 (none), scale: 0, disp: 0 -1940 # beware: modifies 'word' -1941 parse-effective-address: # word : (address slice) -> base/eax, index/ecx, scale/edx, disp/ebx -1942 # pseudocode: -1943 # ++word->start to skip '*' -1944 # initialize defaults: base=0, index=4, scale=0, disp=0 -1945 # if (*word->start != '(') { -1946 # base = get-slice(Registers, word, row-size=8) -1947 # return -1948 # } -1949 # # compound expressions -1950 # skip whitespace -1951 # read register into base -1952 # skip whitespace -1953 # if (*word->start == ')') goto end -1954 # if (*word->start == '-') goto displacement -1955 # if (*word->start != '+') goto error1 -1956 # ++word->start to skip '+' -1957 # skip whitespace -1958 # if next 3 characters don't make a register, goto displacement -1959 # read register into index -1960 # skip whitespace -1961 # if (*word->start == ')') goto end -1962 # if (*word->start == '<') { -1963 # ++word->start to skip '<' -1964 # if (*word->start != '<') goto error2 -1965 # ++word->start to skip '<' -1966 # skip whitespace -1967 # read integer into scale -1968 # skip whitespace -1969 # if (*word->start == ')') goto end -1970 # } -1971 # if (*word->start not in '+' '-') goto error3 -1972 # displacement: -1973 # read integer into disp -1974 # skip whitespace -1975 # if (*word->start != ')') goto error4 -1976 # . prolog -1977 55/push-ebp -1978 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -1979 # . save registers -1980 56/push-esi -1981 57/push-edi -1982 # esi = word -1983 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi -1984 # ++word->start to skip '*' -1985 ff 0/subop/increment 0/mod/indirect 6/rm32/esi . . . . . . # increment *esi -1986 # initialize defaults -1987 # base is in edi; we'll move it to eax just before we return -1988 bf/copy-to-edi 0/imm32 -1989 b9/copy-to-ecx 4/imm32/no-index -1990 ba/copy-to-edx 0/imm32/.scale -1991 bb/copy-to-ebx 0/imm32/disp -1992 $parse-effective-address:check-for-simple-register: -1993 # if (*word->start == '(') goto compound expression -1994 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax -1995 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL -1996 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax -1997 3d/compare-eax-and 0x28/imm32/open-paren -1998 74/jump-if-equal $parse-effective-address:compound-expression/disp8 -1999 $parse-effective-address:simple-register: -2000 # base = get-slice(Registers, word, row-size=8) -2001 # . eax = get-slice(Registers, word, row-size=8) -2002 # . . push args -2003 68/push "Registers"/imm32 -2004 68/push 8/imm32/row-size -2005 56/push-esi -2006 68/push Registers/imm32 -2007 # . . call -2008 e8/call get-slice/disp32 -2009 # . . discard args -2010 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp -2011 # . base = *eax -2012 8b/copy 0/mod/indirect 0/rm32/eax . . . 7/r32/edi . . # copy *eax to edi -2013 # return -2014 e9/jump $parse-effective-address:end/disp32 -2015 $parse-effective-address:compound-expression: -2016 # ++word->start to skip '(' -2017 ff 0/subop/increment 0/mod/indirect 6/rm32/esi . . . . . . # increment *esi -2018 # skip whitespace -2019 # . eax = skip-chars-matching-whitespace-in-slice(word->start, word->end) -2020 # . . push args -2021 ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) -2022 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi -2023 # . . call -2024 e8/call skip-chars-matching-whitespace-in-slice/disp32 -2025 # . . discard args -2026 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2027 # . word->start = eax -2028 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi -2029 # read register into base -2030 # . eax = next-register(word) -2031 # . . push args -2032 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2033 # . . call -2034 e8/call next-register/disp32 -2035 # . . discard args -2036 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -2037 # . edi = *eax -2038 8b/copy 0/mod/indirect 0/rm32/eax . . . 7/r32/edi . . # copy *eax to edi -2039 # skip whitespace -2040 # . eax = skip-chars-matching-whitespace-in-slice(word->start, word->end) -2041 # . . push args -2042 ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) -2043 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi -2044 # . . call -2045 e8/call skip-chars-matching-whitespace-in-slice/disp32 -2046 # . . discard args -2047 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2048 # . word->start = eax -2049 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi -2050 # if (*word->start == ')') goto end -2051 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL -2052 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax -2053 3d/compare-eax-and 0x29/imm32/close-paren -2054 0f 84/jump-if-equal $parse-effective-address:end/disp32 -2055 # if (*word->start == '-') goto displacement -2056 3d/compare-eax-and 0x2d/imm32/minus -2057 0f 84/jump-if-equal $parse-effective-address:displacement/disp32 -2058 # if (*word->start != '+') goto error1 -2059 3d/compare-eax-and 0x2b/imm32/plus -2060 0f 85/jump-if-not-equal $parse-effective-address:error1/disp32 -2061 $parse-effective-address:check-for-index: -2062 # ++word->start to skip '+' -2063 ff 0/subop/increment 0/mod/indirect 6/rm32/esi . . . . . . # increment *esi -2064 # skip whitespace -2065 # . eax = skip-chars-matching-whitespace-in-slice(word->start, word->end) -2066 # . . push args -2067 ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) -2068 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi -2069 # . . call -2070 e8/call skip-chars-matching-whitespace-in-slice/disp32 -2071 # . . discard args -2072 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2073 # . word->start = eax -2074 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi -2075 $parse-effective-address:resolve-ambiguity: -2076 # if next 3 characters don't make a register, goto displacement -2077 # . spill ecx -2078 51/push-ecx -2079 # . var tmp/ecx = {word->start, word->start+3} -2080 # . . ecx = word->start -2081 89/copy 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # copy eax to ecx -2082 # . . eax = word->start+3 -2083 05/add-to-eax 3/imm32 -2084 # . . push -2085 50/push-eax -2086 51/push-ecx -2087 # . . copy esp to ecx -2088 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -2089 # . eax = maybe-get-slice(Register, tmp, row-size=8) -2090 # . . push args -2091 68/push 8/imm32/row-size -2092 51/push-ecx -2093 68/push Registers/imm32 -2094 # . . call -2095 e8/call maybe-get-slice/disp32 -2096 # . . discard args -2097 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2098 # . reclaim tmp -2099 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2100 # . restore ecx -2101 59/pop-to-ecx -2102 # . if (eax == 0) goto displacement -2103 3d/compare-eax-and 0/imm32 -2104 0f 84/jump-if-equal $parse-effective-address:displacement/disp32 -2105 $parse-effective-address:index: -2106 # read register into index -2107 # . eax = next-register(word) -2108 # . . push args -2109 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2110 # . . call -2111 e8/call next-register/disp32 -2112 # . . discard args -2113 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -2114 # . ecx = *eax -2115 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -2116 # skip whitespace -2117 # . eax = skip-chars-matching-whitespace-in-slice(word->start, word->end) -2118 # . . push args -2119 ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) -2120 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi -2121 # . . call -2122 e8/call skip-chars-matching-whitespace-in-slice/disp32 -2123 # . . discard args -2124 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2125 # . word->start = eax -2126 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi -2127 # if (*word->start == ')') goto end -2128 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL -2129 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax -2130 3d/compare-eax-and 0x29/imm32/close-paren -2131 0f 84/jump-if-equal $parse-effective-address:end/disp32 -2132 $parse-effective-address:check-for-scale: -2133 # if (*word->start != '<') goto next check -2134 3d/compare-eax-and 0x3c/imm32/less-than -2135 75/jump-if-not-equal $parse-effective-address:check-for-displacement/disp8 -2136 # ++word->start to skip '<' -2137 ff 0/subop/increment 0/mod/indirect 6/rm32/esi . . . . . . # increment *esi -2138 # if (*word->start != '<') goto error2 -2139 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax -2140 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL -2141 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax -2142 3d/compare-eax-and 0x3c/imm32/less-than -2143 0f 85/jump-if-not-equal $parse-effective-address:error2/disp32 -2144 # ++word->start to skip '<' -2145 ff 0/subop/increment 0/mod/indirect 6/rm32/esi . . . . . . # increment *esi -2146 # skip whitespace -2147 # . eax = skip-chars-matching-whitespace-in-slice(word->start, word->end) -2148 # . . push args -2149 ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) -2150 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi -2151 # . . call -2152 e8/call skip-chars-matching-whitespace-in-slice/disp32 -2153 # . . discard args -2154 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2155 # . word->start = eax -2156 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi -2157 $parse-effective-address:scale: -2158 # read positive integer into scale -2159 # . eax = next-positive-hex-int(word) -2160 # . . push args -2161 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2162 # . . call -2163 e8/call next-positive-hex-int/disp32 -2164 # . . discard args -2165 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -2166 # . edx = eax -2167 89/copy 3/mod/direct 2/rm32/edx . . . 0/r32/eax . . # copy eax to edx -2168 # skip whitespace -2169 # . eax = skip-chars-matching-whitespace-in-slice(word->start, word->end) -2170 # . . push args -2171 ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) -2172 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi -2173 # . . call -2174 e8/call skip-chars-matching-whitespace-in-slice/disp32 -2175 # . . discard args -2176 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2177 # . word->start = eax -2178 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi -2179 # if (*word->start == ')') goto end -2180 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL -2181 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax -2182 3d/compare-eax-and 0x29/imm32/close-paren -2183 74/jump-if-equal $parse-effective-address:end/disp8 -2184 $parse-effective-address:check-for-displacement: -2185 # if (*word->start not in '+' '-') goto error3 -2186 3d/compare-eax-and 0x2b/imm32/plus -2187 74/jump-if-equal $parse-effective-address:displacement/disp8 -2188 3d/compare-eax-and 0x2d/imm32/minus -2189 74/jump-if-equal $parse-effective-address:displacement/disp8 -2190 e9/jump $parse-effective-address:error3/disp32 -2191 $parse-effective-address:displacement: -2192 # read integer into disp -2193 # . eax = next-hex-int(word) -2194 # . . push args -2195 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2196 # . . call -2197 e8/call next-hex-int/disp32 -2198 # . . discard args -2199 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -2200 # . ebx = eax -2201 89/copy 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # copy eax to ebx -2202 # skip whitespace -2203 # . eax = skip-chars-matching-whitespace-in-slice(word->start, word->end) -2204 # . . push args -2205 ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) -2206 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi -2207 # . . call -2208 e8/call skip-chars-matching-whitespace-in-slice/disp32 -2209 # . . discard args -2210 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2211 # . word->start = eax -2212 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi -2213 # if (*word->start != ')') goto error4 -2214 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL -2215 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax -2216 3d/compare-eax-and 0x29/imm32/close-paren -2217 0f 85/jump-if-not-equal $parse-effective-address:error4/disp32 -2218 $parse-effective-address:end: -2219 # return base in eax -2220 89/copy 3/mod/direct 0/rm32/eax . . . 7/r32/edi . . # copy edi to eax -2221 # . restore registers -2222 5f/pop-to-edi -2223 5e/pop-to-esi -2224 # . epilog -2225 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -2226 5d/pop-to-ebp -2227 c3/return -2228 -2229 $parse-effective-address:error1: -2230 # print(stderr, "error: unexpected character: " eax "\n") -2231 # . write-buffered(Stderr, "error: unexpected character: ") -2232 # . . push args -2233 68/push "error: unexpected character: "/imm32 -2234 68/push Stderr/imm32 -2235 # . . call -2236 e8/call write-buffered/disp32 -2237 # . . discard args -2238 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2239 # . print-int32-buffered(out, eax) -2240 # . . push args -2241 50/push-eax -2242 68/push Stderr/imm32 -2243 # . . call -2244 e8/call print-int32-buffered/disp32 -2245 # . . discard args -2246 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2247 # . write-buffered(Stderr, "\n") -2248 # . . push args -2249 68/push "\n"/imm32 -2250 68/push Stderr/imm32 -2251 # . . call -2252 e8/call write-buffered/disp32 -2253 # . . discard args -2254 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2255 # . flush(Stderr) -2256 # . . push args -2257 68/push Stderr/imm32 -2258 # . . call -2259 e8/call flush/disp32 -2260 # . . discard args -2261 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -2262 # . syscall(exit, 1) -2263 bb/copy-to-ebx 1/imm32 -2264 b8/copy-to-eax 1/imm32/exit -2265 cd/syscall 0x80/imm8 -2266 # never gets here -2267 -2268 $parse-effective-address:error2: -2269 # print(stderr, "error: '<' can only be followed by '<' but got: " eax "\n") -2270 # . write-buffered(Stderr, "error: '<' can only be followed by '<' but got: ") -2271 # . . push args -2272 68/push "error: '<' can only be followed by '<' but got: "/imm32 -2273 68/push Stderr/imm32 -2274 # . . call -2275 e8/call write-buffered/disp32 -2276 # . . discard args -2277 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2278 # . print-int32-buffered(out, eax) -2279 # . . push args -2280 50/push-eax -2281 68/push Stderr/imm32 -2282 # . . call -2283 e8/call print-int32-buffered/disp32 -2284 # . . discard args -2285 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2286 # . write-buffered(Stderr, "\n") -2287 # . . push args -2288 68/push "\n"/imm32 -2289 68/push Stderr/imm32 -2290 # . . call -2291 e8/call write-buffered/disp32 -2292 # . . discard args -2293 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2294 # . flush(Stderr) -2295 # . . push args -2296 68/push Stderr/imm32 -2297 # . . call -2298 e8/call flush/disp32 -2299 # . . discard args -2300 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -2301 # . syscall(exit, 1) -2302 bb/copy-to-ebx 1/imm32 -2303 b8/copy-to-eax 1/imm32/exit -2304 cd/syscall 0x80/imm8 -2305 # never gets here -2306 -2307 $parse-effective-address:error3: -2308 # print(stderr, "error: unexpected character before displacement: " eax "\n") -2309 # . write-buffered(Stderr, "error: unexpected character before displacement: ") -2310 # . . push args -2311 68/push "error: unexpected character before displacement: "/imm32 -2312 68/push Stderr/imm32 -2313 # . . call -2314 e8/call write-buffered/disp32 -2315 # . . discard args -2316 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2317 # . print-int32-buffered(out, eax) -2318 # . . push args -2319 50/push-eax -2320 68/push Stderr/imm32 -2321 # . . call -2322 e8/call print-int32-buffered/disp32 -2323 # . . discard args -2324 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2325 # . write-buffered(Stderr, "\n") -2326 # . . push args -2327 68/push "\n"/imm32 -2328 68/push Stderr/imm32 -2329 # . . call -2330 e8/call write-buffered/disp32 -2331 # . . discard args -2332 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2333 # . flush(Stderr) -2334 # . . push args -2335 68/push Stderr/imm32 -2336 # . . call -2337 e8/call flush/disp32 -2338 # . . discard args -2339 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -2340 # . syscall(exit, 1) -2341 bb/copy-to-ebx 1/imm32 -2342 b8/copy-to-eax 1/imm32/exit -2343 cd/syscall 0x80/imm8 -2344 # never gets here -2345 -2346 $parse-effective-address:error4: -2347 # print(stderr, "error: unexpected character after displacement: " eax "; expected ')' to wrap up\n") -2348 # . write-buffered(Stderr, "error: unexpected character after displacement: ") -2349 # . . push args -2350 68/push "error: unexpected character after displacement: "/imm32 -2351 68/push Stderr/imm32 -2352 # . . call -2353 e8/call write-buffered/disp32 -2354 # . . discard args -2355 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2356 # . print-int32-buffered(out, eax) -2357 # . . push args -2358 50/push-eax -2359 68/push Stderr/imm32 -2360 # . . call -2361 e8/call print-int32-buffered/disp32 -2362 # . . discard args -2363 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2364 # . write-buffered(Stderr, "; expected ')' to wrap up\n") -2365 # . . push args -2366 68/push "; expected ')' to wrap up\n"/imm32 -2367 68/push Stderr/imm32 -2368 # . . call -2369 e8/call write-buffered/disp32 -2370 # . . discard args -2371 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2372 # . flush(Stderr) -2373 # . . push args -2374 68/push Stderr/imm32 -2375 # . . call -2376 e8/call flush/disp32 -2377 # . . discard args -2378 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -2379 # . syscall(exit, 1) -2380 bb/copy-to-ebx 1/imm32 -2381 b8/copy-to-eax 1/imm32/exit -2382 cd/syscall 0x80/imm8 -2383 # never gets here -2384 -2385 # assumes 'in' starts with a register name, and returns pointer to its code -2386 # side-effect: modifies 'in' to scan past the initial register name -2387 next-register: # in : (address slice) -> reg/eax : int -2388 # . prolog -2389 55/push-ebp -2390 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -2391 # . save registers -2392 51/push-ecx -2393 56/push-esi -2394 # esi = in -2395 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi -2396 # var reg-slice/ecx : (address slice) = {in->start, in->start + 3} -2397 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax -2398 05/add-to-eax 3/imm32 -2399 50/push-eax -2400 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi -2401 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -2402 # in->start += 3 -2403 81 0/subop/add 0/mod/indirect 6/rm32/esi . . . . . 3/imm32 # add to *esi -2404 # eax = get-slice(Registers, word, row-size=8) -2405 # . . push args -2406 68/push "next-register"/imm32 -2407 68/push 8/imm32/row-size -2408 51/push-ecx -2409 68/push Registers/imm32 -2410 # . . call -2411 e8/call get-slice/disp32 -2412 # . . discard args -2413 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp -2414 $next-register:end: -2415 # reclaim locals -2416 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2417 # . restore registers -2418 5e/pop-to-esi -2419 59/pop-to-ecx -2420 # . epilog -2421 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -2422 5d/pop-to-ebp -2423 c3/return -2424 -2425 test-parse-effective-address-simple: -2426 # . prolog -2427 55/push-ebp -2428 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -2429 # var slice/ecx = "*esi" -2430 b8/copy-to-eax "*esi"/imm32 -2431 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -2432 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 -2433 05/add-to-eax 4/imm32 -2434 # . ecx = {eax, ecx} -2435 51/push-ecx -2436 50/push-eax -2437 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -2438 # eax, ecx, edx, ebx = parse-effective-address(slice) -2439 # . . push args -2440 51/push-ecx -2441 # . . call -2442 e8/call parse-effective-address/disp32 -2443 # . . discard args -2444 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -2445 # slice clobbered beyond this point -2446 # check-ints-equal(eax, 6, msg) -2447 # . . push args -2448 68/push "F - test-parse-effective-address-simple/base"/imm32 -2449 68/push 6/imm32/esi -2450 50/push-eax -2451 # . . call -2452 e8/call check-ints-equal/disp32 -2453 # . . discard args -2454 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2455 # check-ints-equal(ecx, 4, msg) -2456 # . . push args -2457 68/push "F - test-parse-effective-address-simple/index"/imm32 -2458 68/push 4/imm32/none -2459 51/push-ecx -2460 # . . call -2461 e8/call check-ints-equal/disp32 -2462 # . . discard args -2463 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2464 # check-ints-equal(edx, 0, msg) -2465 # . . push args -2466 68/push "F - test-parse-effective-address-simple/scale"/imm32 -2467 68/push 0/imm32/none -2468 52/push-edx -2469 # . . call -2470 e8/call check-ints-equal/disp32 -2471 # . . discard args -2472 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2473 # check-ints-equal(ebx, 0, msg) -2474 # . . push args -2475 68/push "F - test-parse-effective-address-simple/displacement"/imm32 -2476 68/push 0/imm32/none -2477 53/push-ebx -2478 # . . call -2479 e8/call check-ints-equal/disp32 -2480 # . . discard args -2481 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2482 # . epilog -2483 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -2484 5d/pop-to-ebp -2485 c3/return -2486 -2487 test-parse-effective-address-base: -2488 # . prolog -2489 55/push-ebp -2490 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -2491 # var slice/ecx = "*(esi )" -2492 b8/copy-to-eax "*(esi )"/imm32 -2493 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -2494 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 -2495 05/add-to-eax 4/imm32 -2496 # . ecx = {eax, ecx} -2497 51/push-ecx -2498 50/push-eax -2499 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -2500 # eax, ecx, edx, ebx = parse-effective-address(slice) -2501 # . . push args -2502 51/push-ecx -2503 # . . call -2504 e8/call parse-effective-address/disp32 -2505 # . . discard args -2506 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -2507 # slice clobbered beyond this point -2508 # check-ints-equal(eax, 6, msg) -2509 # . . push args -2510 68/push "F - test-parse-effective-address-base/base"/imm32 -2511 68/push 6/imm32/esi -2512 50/push-eax -2513 # . . call -2514 e8/call check-ints-equal/disp32 -2515 # . . discard args -2516 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2517 # check-ints-equal(ecx, 4, msg) -2518 # . . push args -2519 68/push "F - test-parse-effective-address-base/index"/imm32 -2520 68/push 4/imm32/none -2521 51/push-ecx -2522 # . . call -2523 e8/call check-ints-equal/disp32 -2524 # . . discard args -2525 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2526 # check-ints-equal(edx, 0, msg) -2527 # . . push args -2528 68/push "F - test-parse-effective-address-base/scale"/imm32 -2529 68/push 0/imm32/none -2530 52/push-edx -2531 # . . call -2532 e8/call check-ints-equal/disp32 -2533 # . . discard args -2534 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2535 # check-ints-equal(ebx, 0, msg) -2536 # . . push args -2537 68/push "F - test-parse-effective-address-base/displacement"/imm32 -2538 68/push 0/imm32/none -2539 53/push-ebx -2540 # . . call -2541 e8/call check-ints-equal/disp32 -2542 # . . discard args -2543 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2544 # . epilog -2545 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -2546 5d/pop-to-ebp -2547 c3/return -2548 -2549 test-parse-effective-address-base-displacement: -2550 # . prolog -2551 55/push-ebp -2552 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -2553 # var slice/ecx = "*(esi+3)" -2554 b8/copy-to-eax "*(esi+3)"/imm32 -2555 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -2556 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 -2557 05/add-to-eax 4/imm32 -2558 # . ecx = {eax, ecx} -2559 51/push-ecx -2560 50/push-eax -2561 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -2562 # eax, ecx, edx, ebx = parse-effective-address(slice) -2563 # . . push args -2564 51/push-ecx -2565 # . . call -2566 e8/call parse-effective-address/disp32 -2567 # . . discard args -2568 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -2569 # slice clobbered beyond this point -2570 # check-ints-equal(eax, 6, msg) -2571 # . . push args -2572 68/push "F - test-parse-effective-address-base-displacement/base"/imm32 -2573 68/push 6/imm32/esi -2574 50/push-eax -2575 # . . call -2576 e8/call check-ints-equal/disp32 -2577 # . . discard args -2578 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2579 # check-ints-equal(ecx, 4, msg) -2580 # . . push args -2581 68/push "F - test-parse-effective-address-base-displacement/index"/imm32 -2582 68/push 4/imm32/none -2583 51/push-ecx -2584 # . . call -2585 e8/call check-ints-equal/disp32 -2586 # . . discard args -2587 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2588 # check-ints-equal(edx, 0, msg) -2589 # . . push args -2590 68/push "F - test-parse-effective-address-base-displacement/scale"/imm32 -2591 68/push 0/imm32/none -2592 52/push-edx -2593 # . . call -2594 e8/call check-ints-equal/disp32 -2595 # . . discard args -2596 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2597 # check-ints-equal(ebx, 3, msg) -2598 # . . push args -2599 68/push "F - test-parse-effective-address-base-displacement/displacement"/imm32 -2600 68/push 3/imm32 -2601 53/push-ebx -2602 # . . call -2603 e8/call check-ints-equal/disp32 -2604 # . . discard args -2605 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2606 # . epilog -2607 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -2608 5d/pop-to-ebp -2609 c3/return -2610 -2611 test-parse-effective-address-base-negative-displacement: -2612 # . prolog -2613 55/push-ebp -2614 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -2615 # var slice/ecx = "*(esi-3)" -2616 b8/copy-to-eax "*(esi-3)"/imm32 -2617 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -2618 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 -2619 05/add-to-eax 4/imm32 -2620 # . ecx = {eax, ecx} -2621 51/push-ecx -2622 50/push-eax -2623 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -2624 # eax, ecx, edx, ebx = parse-effective-address(slice) -2625 # . . push args -2626 51/push-ecx -2627 # . . call -2628 e8/call parse-effective-address/disp32 -2629 # . . discard args -2630 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -2631 # slice clobbered beyond this point -2632 # check-ints-equal(eax, 6, msg) -2633 # . . push args -2634 68/push "F - test-parse-effective-address-base-negative-displacement/base"/imm32 -2635 68/push 6/imm32/esi -2636 50/push-eax -2637 # . . call -2638 e8/call check-ints-equal/disp32 -2639 # . . discard args -2640 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2641 # check-ints-equal(ecx, 4, msg) -2642 # . . push args -2643 68/push "F - test-parse-effective-address-base-negative-displacement/index"/imm32 -2644 68/push 4/imm32/none -2645 51/push-ecx -2646 # . . call -2647 e8/call check-ints-equal/disp32 -2648 # . . discard args -2649 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2650 # check-ints-equal(edx, 0, msg) -2651 # . . push args -2652 68/push "F - test-parse-effective-address-base-negative-displacement/scale"/imm32 -2653 68/push 0/imm32/none -2654 52/push-edx -2655 # . . call -2656 e8/call check-ints-equal/disp32 -2657 # . . discard args -2658 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2659 # check-ints-equal(ebx, -3, msg) -2660 # . . push args -2661 68/push "F - test-parse-effective-address-base-negative-displacement/displacement"/imm32 -2662 68/push -3/imm32 -2663 53/push-ebx -2664 # . . call -2665 e8/call check-ints-equal/disp32 -2666 # . . discard args -2667 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2668 # . epilog -2669 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -2670 5d/pop-to-ebp -2671 c3/return -2672 -2673 test-parse-effective-address-base-index: -2674 # . prolog -2675 55/push-ebp -2676 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -2677 # var slice/ecx = "*(esi+ecx)" -2678 b8/copy-to-eax "*(esi+ecx)"/imm32 -2679 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -2680 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 -2681 05/add-to-eax 4/imm32 -2682 # . ecx = {eax, ecx} -2683 51/push-ecx -2684 50/push-eax -2685 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -2686 # eax, ecx, edx, ebx = parse-effective-address(slice) -2687 # . . push args -2688 51/push-ecx -2689 # . . call -2690 e8/call parse-effective-address/disp32 -2691 # . . discard args -2692 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -2693 # slice clobbered beyond this point -2694 # check-ints-equal(eax, 6, msg) -2695 # . . push args -2696 68/push "F - test-parse-effective-address-base-index/base"/imm32 -2697 68/push 6/imm32/esi -2698 50/push-eax -2699 # . . call -2700 e8/call check-ints-equal/disp32 -2701 # . . discard args -2702 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2703 # check-ints-equal(ecx, 1, msg) -2704 # . . push args -2705 68/push "F - test-parse-effective-address-base-index/index"/imm32 -2706 68/push 1/imm32/none -2707 51/push-ecx -2708 # . . call -2709 e8/call check-ints-equal/disp32 -2710 # . . discard args -2711 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2712 # check-ints-equal(edx, 0, msg) -2713 # . . push args -2714 68/push "F - test-parse-effective-address-base-index/scale"/imm32 -2715 68/push 0/imm32/none -2716 52/push-edx -2717 # . . call -2718 e8/call check-ints-equal/disp32 -2719 # . . discard args -2720 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2721 # check-ints-equal(ebx, 0, msg) -2722 # . . push args -2723 68/push "F - test-parse-effective-address-base-index/displacement"/imm32 -2724 68/push 0/imm32 -2725 53/push-ebx -2726 # . . call -2727 e8/call check-ints-equal/disp32 -2728 # . . discard args -2729 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2730 # . epilog -2731 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -2732 5d/pop-to-ebp -2733 c3/return -2734 -2735 test-parse-effective-address-base-index-scale: -2736 # . prolog -2737 55/push-ebp -2738 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -2739 # var slice/ecx = "*(esi+ecx<<2)" -2740 b8/copy-to-eax "*(esi+ecx<<2)"/imm32 -2741 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -2742 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 -2743 05/add-to-eax 4/imm32 -2744 # . ecx = {eax, ecx} -2745 51/push-ecx -2746 50/push-eax -2747 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -2748 # eax, ecx, edx, ebx = parse-effective-address(slice) -2749 # . . push args -2750 51/push-ecx -2751 # . . call -2752 e8/call parse-effective-address/disp32 -2753 # . . discard args -2754 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -2755 # slice clobbered beyond this point -2756 # check-ints-equal(eax, 6, msg) -2757 # . . push args -2758 68/push "F - test-parse-effective-address-base-index-scale/base"/imm32 -2759 68/push 6/imm32/esi -2760 50/push-eax -2761 # . . call -2762 e8/call check-ints-equal/disp32 -2763 # . . discard args -2764 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2765 # check-ints-equal(ecx, 1, msg) -2766 # . . push args -2767 68/push "F - test-parse-effective-address-base-index-scale/index"/imm32 -2768 68/push 1/imm32/none -2769 51/push-ecx -2770 # . . call -2771 e8/call check-ints-equal/disp32 -2772 # . . discard args -2773 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2774 # check-ints-equal(edx, 2, msg) -2775 # . . push args -2776 68/push "F - test-parse-effective-address-base-index-scale/scale"/imm32 -2777 68/push 2/imm32 -2778 52/push-edx -2779 # . . call -2780 e8/call check-ints-equal/disp32 -2781 # . . discard args -2782 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2783 # check-ints-equal(ebx, 0, msg) -2784 # . . push args -2785 68/push "F - test-parse-effective-address-base-index-scale/displacement"/imm32 -2786 68/push 0/imm32 -2787 53/push-ebx -2788 # . . call -2789 e8/call check-ints-equal/disp32 -2790 # . . discard args -2791 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2792 # . epilog -2793 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -2794 5d/pop-to-ebp -2795 c3/return -2796 -2797 test-parse-effective-address-base-index-scale-displacement: -2798 # . prolog -2799 55/push-ebp -2800 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -2801 # var slice/ecx = "*(esi + ecx<<2 - 0x34)" -2802 b8/copy-to-eax "*(esi + ecx<<2 - 0x34)"/imm32 -2803 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -2804 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 -2805 05/add-to-eax 4/imm32 -2806 # . ecx = {eax, ecx} -2807 51/push-ecx -2808 50/push-eax -2809 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -2810 # eax, ecx, edx, ebx = parse-effective-address(slice) -2811 # . . push args -2812 51/push-ecx -2813 # . . call -2814 e8/call parse-effective-address/disp32 -2815 # . . discard args -2816 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -2817 # slice clobbered beyond this point -2818 # check-ints-equal(eax, 6, msg) -2819 # . . push args -2820 68/push "F - test-parse-effective-address-base-index-scale/base"/imm32 -2821 68/push 6/imm32/esi -2822 50/push-eax -2823 # . . call -2824 e8/call check-ints-equal/disp32 -2825 # . . discard args -2826 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2827 # check-ints-equal(ecx, 1, msg) -2828 # . . push args -2829 68/push "F - test-parse-effective-address-base-index-scale/index"/imm32 -2830 68/push 1/imm32/none -2831 51/push-ecx -2832 # . . call -2833 e8/call check-ints-equal/disp32 -2834 # . . discard args -2835 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2836 # check-ints-equal(edx, 2, msg) -2837 # . . push args -2838 68/push "F - test-parse-effective-address-base-index-scale/scale"/imm32 -2839 68/push 2/imm32 -2840 52/push-edx -2841 # . . call -2842 e8/call check-ints-equal/disp32 -2843 # . . discard args -2844 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2845 # check-ints-equal(ebx, -0x34, msg) -2846 # . . push args -2847 68/push "F - test-parse-effective-address-base-index-scale/displacement"/imm32 -2848 68/push -0x34/imm32 -2849 53/push-ebx -2850 # . . call -2851 e8/call check-ints-equal/disp32 -2852 # . . discard args -2853 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -2854 # . epilog -2855 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -2856 5d/pop-to-ebp -2857 c3/return -2858 -2859 # Code generation: -2860 # if index is none and disp is 0, then mod = 0 and rm32 = base -2861 # if index is none, then mod = 2 and rm32 = base and disp32 = disp -2862 # if index is not none, then mod = 2 and rm32 = 4 and base = base and index = index and disp32 = disp -2863 emit-indirect-mode: # out : (address buffered-file), base : int, index : int, scale : int, disp : int -2864 # . prolog -2865 55/push-ebp -2866 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -2867 $emit-indirect-mode:check-for-sib: -2868 # if (index == 4/none) goto next check -2869 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 4/imm32 # compare *(ebp+16) -2870 0f 84/jump-if-equal $emit-indirect-mode:check-for-disp/disp32 -2871 $emit-indirect-mode:emit-sib: -2872 # emit(out, "2/mod/indirect 4/rm32/sib " base "/base " index "/index " scale "/scale " disp "/disp32") -2873 # . write-buffered(out, "2/mod/*+disp32 4/rm32/sib ") -2874 # . . push args -2875 68/push "2/mod/*+disp32 4/rm32/sib "/imm32 -2876 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2877 # . . call -2878 e8/call write-buffered/disp32 -2879 # . . discard args -2880 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2881 # . print-int32-buffered(out, base) -2882 # . . push args -2883 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) -2884 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2885 # . . call -2886 e8/call print-int32-buffered/disp32 -2887 # . . discard args -2888 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2889 # . write-buffered(out, "/base ") -2890 # . . push args -2891 68/push "/base "/imm32 -2892 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2893 # . . call -2894 e8/call write-buffered/disp32 -2895 # . . discard args -2896 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2897 # . print-int32-buffered(out, index) -2898 # . . push args -2899 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) -2900 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2901 # . . call -2902 e8/call print-int32-buffered/disp32 -2903 # . . discard args -2904 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2905 # . write-buffered(out, "/index ") -2906 # . . push args -2907 68/push "/index "/imm32 -2908 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2909 # . . call -2910 e8/call write-buffered/disp32 -2911 # . . discard args -2912 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2913 # . print-int32-buffered(out, scale) -2914 # . . push args -2915 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x14/disp8 . # push *(ebp+20) -2916 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2917 # . . call -2918 e8/call print-int32-buffered/disp32 -2919 # . . discard args -2920 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2921 # . write-buffered(out, "/scale ") -2922 # . . push args -2923 68/push "/scale "/imm32 -2924 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2925 # . . call -2926 e8/call write-buffered/disp32 -2927 # . . discard args -2928 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2929 # . print-int32-buffered(out, disp) -2930 # . . push args -2931 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x18/disp8 . # push *(ebp+24) -2932 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2933 # . . call -2934 e8/call print-int32-buffered/disp32 -2935 # . . discard args -2936 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2937 # . write-buffered(out, "/disp32") -2938 # . . push args -2939 68/push "/disp32"/imm32 -2940 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2941 # . . call -2942 e8/call write-buffered/disp32 -2943 # . . discard args -2944 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2945 e9/jump $emit-indirect-mode:end/disp32 -2946 $emit-indirect-mode:check-for-disp: -2947 # if (disp == 0) goto next check -2948 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 0x18/disp8 0/imm32 # compare *(ebp+24) -2949 74/jump-if-equal $emit-indirect-mode:emit-indirect/disp8 -2950 $emit-indirect-mode:emit-disp: -2951 # emit(out, "2/mod/*+disp32 " base "/rm32 " disp "/disp32") -2952 # . write-buffered(out, "2/mod/*+disp32 ") +1398 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 0/index/eax . 0/r32/eax 0xc/disp8 . # copy esi+eax+12 to eax +1399 89/copy 1/mod/*+disp8 7/rm32/edi . . . 0/r32/eax 4/disp8 . # copy eax to *(edi+4) +1400 # line->read = line->write # skip rest of line +1401 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax +1402 89/copy 1/mod/*+disp8 6/rm32/esi . . . 0/r32/eax 4/disp8 . # copy eax to *(esi+4) +1403 # return +1404 eb/jump $next-word-or-expression:end/disp8 +1405 $next-word-or-expression:check-for-string-literal: +1406 # if (line->data[line->read] != '"') goto next check +1407 # . eax = line->data[line->read] +1408 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax +1409 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL +1410 # . compare +1411 3d/compare-eax-and 0x22/imm32/dquote +1412 75/jump-if-not-equal $next-word-or-expression:check-for-paren/disp8 +1413 $next-word-or-expression:string-literal: +1414 # skip-string(line) +1415 # . . push args +1416 56/push-esi +1417 # . . call +1418 e8/call skip-string/disp32 +1419 # . . discard args +1420 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1421 # skip rest of word +1422 eb/jump $next-word-or-expression:regular-word/disp8 +1423 $next-word-or-expression:check-for-paren: +1424 # if (line->data[line->read] != '*') goto next check +1425 # . eax = line->data[line->read] +1426 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax +1427 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL +1428 # . compare +1429 3d/compare-eax-and 0x2a/imm32/asterisk +1430 75/jump-if-not-equal $next-word-or-expression:regular-word/disp8 +1431 # if (line->data[line->read] == ' ') goto error1 +1432 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xd/disp8 . # copy byte at *(esi+ecx+12+1) to AL +1433 # . compare +1434 3d/compare-eax-and 0x20/imm32/space +1435 74/jump-if-equal $next-word-or-expression:error1/disp8 +1436 # if (line->data[line->read] != '(') goto regular word +1437 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xd/disp8 . # copy byte at *(esi+ecx+12+1) to AL +1438 # . compare +1439 3d/compare-eax-and 0x28/imm32/open-paren +1440 75/jump-if-not-equal $next-word-or-expression:regular-word/disp8 +1441 $next-word-or-expression:paren: +1442 # skip-until-close-paren(line) +1443 # . . push args +1444 56/push-esi +1445 # . . call +1446 e8/call skip-until-close-paren/disp32 +1447 # . . discard args +1448 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1449 # if (line->data[line->read] != ')') goto error2 +1450 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx +1451 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/AL 0xc/disp8 . # copy byte at *(esi+ecx+12) to AL +1452 # . compare +1453 3d/compare-eax-and 0x29/imm32/close-paren +1454 75/jump-if-not-equal $next-word-or-expression:error2/disp8 +1455 # skip ')' +1456 ff 0/subop/increment 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # increment *(esi+4) +1457 # fall through +1458 $next-word-or-expression:regular-word: +1459 # skip-chars-not-matching-whitespace(line) # including trailing newline +1460 # . . push args +1461 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +1462 # . . call +1463 e8/call skip-chars-not-matching-whitespace/disp32 +1464 # . . discard args +1465 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1466 # out->end = &line->data[line->read] +1467 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 1/r32/ecx 4/disp8 . # copy *(esi+4) to ecx +1468 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/esi 1/index/ecx . 0/r32/eax 0xc/disp8 . # copy esi+ecx+12 to eax +1469 89/copy 1/mod/*+disp8 7/rm32/edi . . . 0/r32/eax 4/disp8 . # copy eax to *(edi+4) +1470 $next-word-or-expression:end: +1471 # . restore registers +1472 5f/pop-to-edi +1473 5e/pop-to-esi +1474 59/pop-to-ecx +1475 58/pop-to-eax +1476 # . epilog +1477 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +1478 5d/pop-to-ebp +1479 c3/return +1480 +1481 $next-word-or-expression:error1: +1482 # print(stderr, "error: no space allowed after '*' in '" line "'") +1483 # . write-buffered(Stderr, "error: no space allowed after '*' in '") +1484 # . . push args +1485 68/push "error: no space allowed after '*' in '"/imm32 +1486 68/push Stderr/imm32 +1487 # . . call +1488 e8/call write-buffered/disp32 +1489 # . . discard args +1490 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1491 # . write-stream-data(Stderr, line) +1492 # . . push args +1493 56/push-esi +1494 68/push Stderr/imm32 +1495 # . . call +1496 e8/call write-stream-data/disp32 +1497 # . . discard args +1498 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1499 # . write-buffered(Stderr, "'") +1500 # . . push args +1501 68/push "'"/imm32 +1502 68/push Stderr/imm32 +1503 # . . call +1504 e8/call write-buffered/disp32 +1505 # . . discard args +1506 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1507 # . flush(Stderr) +1508 # . . push args +1509 68/push Stderr/imm32 +1510 # . . call +1511 e8/call flush/disp32 +1512 # . . discard args +1513 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1514 # . syscall(exit, 1) +1515 bb/copy-to-ebx 1/imm32 +1516 b8/copy-to-eax 1/imm32/exit +1517 cd/syscall 0x80/imm8 +1518 # never gets here +1519 +1520 $next-word-or-expression:error2: +1521 # print(stderr, "error: no space allowed after '*' in '" line "'") +1522 # . write-buffered(Stderr, "error: *(...) expression must be all on a single line in '") +1523 # . . push args +1524 68/push "error: *(...) expression must be all on a single line in '"/imm32 +1525 68/push Stderr/imm32 +1526 # . . call +1527 e8/call write-buffered/disp32 +1528 # . . discard args +1529 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1530 # . write-stream-data(Stderr, line) +1531 # . . push args +1532 56/push-esi +1533 68/push Stderr/imm32 +1534 # . . call +1535 e8/call write-stream-data/disp32 +1536 # . . discard args +1537 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1538 # . write-buffered(Stderr, "'") +1539 # . . push args +1540 68/push "'"/imm32 +1541 68/push Stderr/imm32 +1542 # . . call +1543 e8/call write-buffered/disp32 +1544 # . . discard args +1545 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1546 # . flush(Stderr) +1547 # . . push args +1548 68/push Stderr/imm32 +1549 # . . call +1550 e8/call flush/disp32 +1551 # . . discard args +1552 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1553 # . syscall(exit, 1) +1554 bb/copy-to-ebx 1/imm32 +1555 b8/copy-to-eax 1/imm32/exit +1556 cd/syscall 0x80/imm8 +1557 # never gets here +1558 +1559 test-next-word-or-expression: +1560 # . prolog +1561 55/push-ebp +1562 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +1563 # setup +1564 # . clear-stream(_test-input-stream) +1565 # . . push args +1566 68/push _test-input-stream/imm32 +1567 # . . call +1568 e8/call clear-stream/disp32 +1569 # . . discard args +1570 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1571 # var slice/ecx = {0, 0} +1572 68/push 0/imm32/end +1573 68/push 0/imm32/start +1574 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +1575 # write(_test-input-stream, " ab") +1576 # . . push args +1577 68/push " ab"/imm32 +1578 68/push _test-input-stream/imm32 +1579 # . . call +1580 e8/call write/disp32 +1581 # . . discard args +1582 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1583 # next-word-or-expression(_test-input-stream, slice) +1584 # . . push args +1585 51/push-ecx +1586 68/push _test-input-stream/imm32 +1587 # . . call +1588 e8/call next-word-or-expression/disp32 +1589 # . . discard args +1590 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1591 # check-ints-equal(_test-input-stream->read, 4, msg) +1592 # . . push args +1593 68/push "F - test-next-word-or-expression/updates-stream-read-correctly"/imm32 +1594 68/push 4/imm32 +1595 b8/copy-to-eax _test-input-stream/imm32 +1596 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) +1597 # . . call +1598 e8/call check-ints-equal/disp32 +1599 # . . discard args +1600 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1601 # check-ints-equal(slice->start - _test-input-stream->data, 2, msg) +1602 # . check-ints-equal(slice->start - _test-input-stream, 14, msg) +1603 # . . push args +1604 68/push "F - test-next-word-or-expression: start"/imm32 +1605 68/push 0xe/imm32 +1606 # . . push slice->start - _test-input-stream +1607 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax +1608 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +1609 50/push-eax +1610 # . . call +1611 e8/call check-ints-equal/disp32 +1612 # . . discard args +1613 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1614 # check-ints-equal(slice->end - _test-input-stream->data, 4, msg) +1615 # . check-ints-equal(slice->end - _test-input-stream, 16, msg) +1616 # . . push args +1617 68/push "F - test-next-word-or-expression: end"/imm32 +1618 68/push 0x10/imm32 +1619 # . . push slice->end - _test-input-stream +1620 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax +1621 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +1622 50/push-eax +1623 # . . call +1624 e8/call check-ints-equal/disp32 +1625 # . . discard args +1626 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1627 # . epilog +1628 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +1629 5d/pop-to-ebp +1630 c3/return +1631 +1632 test-next-word-or-expression-returns-whole-comment: +1633 # . prolog +1634 55/push-ebp +1635 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +1636 # setup +1637 # . clear-stream(_test-input-stream) +1638 # . . push args +1639 68/push _test-input-stream/imm32 +1640 # . . call +1641 e8/call clear-stream/disp32 +1642 # . . discard args +1643 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1644 # var slice/ecx = {0, 0} +1645 68/push 0/imm32/end +1646 68/push 0/imm32/start +1647 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +1648 # write(_test-input-stream, " # a") +1649 # . . push args +1650 68/push " # a"/imm32 +1651 68/push _test-input-stream/imm32 +1652 # . . call +1653 e8/call write/disp32 +1654 # . . discard args +1655 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1656 # next-word-or-expression(_test-input-stream, slice) +1657 # . . push args +1658 51/push-ecx +1659 68/push _test-input-stream/imm32 +1660 # . . call +1661 e8/call next-word-or-expression/disp32 +1662 # . . discard args +1663 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1664 # check-ints-equal(_test-input-stream->read, 5, msg) +1665 # . . push args +1666 68/push "F - test-next-word-or-expression-returns-whole-comment/updates-stream-read-correctly"/imm32 +1667 68/push 5/imm32 +1668 b8/copy-to-eax _test-input-stream/imm32 +1669 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) +1670 # . . call +1671 e8/call check-ints-equal/disp32 +1672 # . . discard args +1673 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1674 # check-ints-equal(slice->start - _test-input-stream->data, 2, msg) +1675 # . check-ints-equal(slice->start - _test-input-stream, 14, msg) +1676 # . . push args +1677 68/push "F - test-next-word-or-expression-returns-whole-comment: start"/imm32 +1678 68/push 0xe/imm32 +1679 # . . push slice->start - _test-input-stream +1680 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax +1681 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +1682 50/push-eax +1683 # . . call +1684 e8/call check-ints-equal/disp32 +1685 # . . discard args +1686 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1687 # check-ints-equal(slice->end - _test-input-stream->data, 5, msg) +1688 # . check-ints-equal(slice->end - _test-input-stream, 17, msg) +1689 # . . push args +1690 68/push "F - test-next-word-or-expression-returns-whole-comment: end"/imm32 +1691 68/push 0x11/imm32 +1692 # . . push slice->end - _test-input-stream +1693 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax +1694 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +1695 50/push-eax +1696 # . . call +1697 e8/call check-ints-equal/disp32 +1698 # . . discard args +1699 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1700 # . epilog +1701 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +1702 5d/pop-to-ebp +1703 c3/return +1704 +1705 test-next-word-or-expression-returns-empty-slice-on-eof: +1706 # . prolog +1707 55/push-ebp +1708 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +1709 # setup +1710 # . clear-stream(_test-input-stream) +1711 # . . push args +1712 68/push _test-input-stream/imm32 +1713 # . . call +1714 e8/call clear-stream/disp32 +1715 # . . discard args +1716 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1717 # var slice/ecx = {0, 0} +1718 68/push 0/imm32/end +1719 68/push 0/imm32/start +1720 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +1721 # write nothing to _test-input-stream +1722 # next-word-or-expression(_test-input-stream, slice) +1723 # . . push args +1724 51/push-ecx +1725 68/push _test-input-stream/imm32 +1726 # . . call +1727 e8/call next-word-or-expression/disp32 +1728 # . . discard args +1729 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1730 # check-ints-equal(slice->end - slice->start, 0, msg) +1731 # . . push args +1732 68/push "F - test-next-word-or-expression-returns-empty-expression-on-eof"/imm32 +1733 68/push 0/imm32 +1734 # . . push slice->end - slice->start +1735 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax +1736 2b/subtract 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # subtract *ecx from eax +1737 50/push-eax +1738 # . . call +1739 e8/call check-ints-equal/disp32 +1740 # . . discard args +1741 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1742 # . epilog +1743 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +1744 5d/pop-to-ebp +1745 c3/return +1746 +1747 test-next-word-or-expression-returns-string-literal: +1748 # . prolog +1749 55/push-ebp +1750 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +1751 # setup +1752 # . clear-stream(_test-input-stream) +1753 # . . push args +1754 68/push _test-input-stream/imm32 +1755 # . . call +1756 e8/call clear-stream/disp32 +1757 # . . discard args +1758 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1759 # var slice/ecx = {0, 0} +1760 68/push 0/imm32/end +1761 68/push 0/imm32/start +1762 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +1763 # write(_test-input-stream, " \"a b\"/imm32 ") +1764 # . . push args +1765 68/push " \"a b\"/imm32 "/imm32 +1766 68/push _test-input-stream/imm32 +1767 # . . call +1768 e8/call write/disp32 +1769 # . . discard args +1770 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1771 # next-word-or-expression(_test-input-stream, slice) +1772 # . . push args +1773 51/push-ecx +1774 68/push _test-input-stream/imm32 +1775 # . . call +1776 e8/call next-word-or-expression/disp32 +1777 # . . discard args +1778 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1779 # check-ints-equal(slice->start - _test-input-stream->data, 1, msg) +1780 # . check-ints-equal(slice->start - _test-input-stream, 13, msg) +1781 # . . push args +1782 68/push "F - test-next-word-or-expression-returns-string-literal: start"/imm32 +1783 68/push 0xd/imm32 +1784 # . . push slice->start - _test-input-stream +1785 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax +1786 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +1787 50/push-eax +1788 # . . call +1789 e8/call check-ints-equal/disp32 +1790 # . . discard args +1791 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1792 # check-ints-equal(slice->end - _test-input-stream->data, 12, msg) +1793 # . check-ints-equal(slice->end - _test-input-stream, 24, msg) +1794 # . . push args +1795 68/push "F - test-next-word-or-expression-returns-string-literal: end"/imm32 +1796 68/push 0x18/imm32 +1797 # . . push slice->end - _test-input-stream +1798 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax +1799 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +1800 50/push-eax +1801 # . . call +1802 e8/call check-ints-equal/disp32 +1803 # . . discard args +1804 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1805 # . epilog +1806 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +1807 5d/pop-to-ebp +1808 c3/return +1809 +1810 test-next-word-or-expression-returns-string-with-escapes: +1811 # . prolog +1812 55/push-ebp +1813 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +1814 # setup +1815 # . clear-stream(_test-input-stream) +1816 # . . push args +1817 68/push _test-input-stream/imm32 +1818 # . . call +1819 e8/call clear-stream/disp32 +1820 # . . discard args +1821 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1822 # var slice/ecx = {0, 0} +1823 68/push 0/imm32/end +1824 68/push 0/imm32/start +1825 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +1826 # write(_test-input-stream, " \"a\\\"b\"/x") +1827 # . . push args +1828 68/push " \"a\\\"b\"/x"/imm32 +1829 68/push _test-input-stream/imm32 +1830 # . . call +1831 e8/call write/disp32 +1832 # . . discard args +1833 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1834 # next-word-or-expression(_test-input-stream, slice) +1835 # . . push args +1836 51/push-ecx +1837 68/push _test-input-stream/imm32 +1838 # . . call +1839 e8/call next-word-or-expression/disp32 +1840 # . . discard args +1841 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1842 # check-ints-equal(slice->start - _test-input-stream->data, 1, msg) +1843 # . check-ints-equal(slice->start - _test-input-stream, 13, msg) +1844 # . . push args +1845 68/push "F - test-next-word-or-expression-returns-string-with-escapes: start"/imm32 +1846 68/push 0xd/imm32 +1847 # . . push slice->start - _test-input-stream +1848 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax +1849 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +1850 50/push-eax +1851 # . . call +1852 e8/call check-ints-equal/disp32 +1853 # . . discard args +1854 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1855 # check-ints-equal(slice->end - _test-input-stream->data, 9, msg) +1856 # . check-ints-equal(slice->end - _test-input-stream, 21, msg) +1857 # . . push args +1858 68/push "F - test-next-word-or-expression-returns-string-with-escapes: end"/imm32 +1859 68/push 0x15/imm32 +1860 # . . push slice->end - _test-input-stream +1861 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax +1862 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +1863 50/push-eax +1864 # . . call +1865 e8/call check-ints-equal/disp32 +1866 # . . discard args +1867 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1868 # . epilog +1869 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +1870 5d/pop-to-ebp +1871 c3/return +1872 +1873 test-next-word-or-expression-returns-whole-expression: +1874 # . prolog +1875 55/push-ebp +1876 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +1877 # setup +1878 # . clear-stream(_test-input-stream) +1879 # . . push args +1880 68/push _test-input-stream/imm32 +1881 # . . call +1882 e8/call clear-stream/disp32 +1883 # . . discard args +1884 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +1885 # var slice/ecx = {0, 0} +1886 68/push 0/imm32/end +1887 68/push 0/imm32/start +1888 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +1889 # write(_test-input-stream, " *(a b)/imm32 ") +1890 # . . push args +1891 68/push " *(a b)/imm32 "/imm32 +1892 68/push _test-input-stream/imm32 +1893 # . . call +1894 e8/call write/disp32 +1895 # . . discard args +1896 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1897 # next-word-or-expression(_test-input-stream, slice) +1898 # . . push args +1899 51/push-ecx +1900 68/push _test-input-stream/imm32 +1901 # . . call +1902 e8/call next-word-or-expression/disp32 +1903 # . . discard args +1904 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +1905 # check-ints-equal(slice->start - _test-input-stream->data, 1, msg) +1906 # . check-ints-equal(slice->start - _test-input-stream, 13, msg) +1907 # . . push args +1908 68/push "F - test-next-word-or-expression-returns-whole-expression: start"/imm32 +1909 68/push 0xd/imm32 +1910 # . . push slice->start - _test-input-stream +1911 8b/copy 0/mod/indirect 1/rm32/ecx . . . 0/r32/eax . . # copy *ecx to eax +1912 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +1913 50/push-eax +1914 # . . call +1915 e8/call check-ints-equal/disp32 +1916 # . . discard args +1917 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1918 # check-ints-equal(slice->end - _test-input-stream->data, 13, msg) +1919 # . check-ints-equal(slice->end - _test-input-stream, 25, msg) +1920 # . . push args +1921 68/push "F - test-next-word-or-expression-returns-whole-expression: end"/imm32 +1922 68/push 0x19/imm32 +1923 # . . push slice->end - _test-input-stream +1924 8b/copy 1/mod/*+disp8 1/rm32/ecx . . . 0/r32/eax 4/disp8 . # copy *(ecx+4) to eax +1925 81 5/subop/subtract 3/mod/direct 0/rm32/eax . . . . . _test-input-stream/imm32 # subtract from eax +1926 50/push-eax +1927 # . . call +1928 e8/call check-ints-equal/disp32 +1929 # . . discard args +1930 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +1931 # . epilog +1932 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +1933 5d/pop-to-ebp +1934 c3/return +1935 +1936 # Grammar: +1937 # *reg -> 0/mod reg/rm32 +1938 # *(reg) -> 0/mod reg/rm32 +1939 # *(reg+disp) -> 2/mod reg/rm32 disp/disp32 +1940 # *(reg1+reg2<<s) -> 2/mod 4/rm32 reg1/base reg2/index s/scale 0/disp32 +1941 # *(reg1+reg2<<s+disp) -> 2/mod 4/rm32 reg1/base reg2/index s/scale disp/disp32 +1942 # Intermediate structure: base, index, scale, disp +1943 # Default values: base: 0, index: 4 (none), scale: 0, disp: 0 +1944 # beware: modifies 'word' +1945 parse-effective-address: # word : (address slice) -> base/eax, index/ecx, scale/edx, disp/ebx +1946 # pseudocode: +1947 # ++word->start to skip '*' +1948 # initialize defaults: base=0, index=4, scale=0, disp=0 +1949 # if (*word->start != '(') { +1950 # base = get-slice(Registers, word, row-size=8) +1951 # return +1952 # } +1953 # # compound expressions +1954 # skip whitespace +1955 # read register into base +1956 # skip whitespace +1957 # if (*word->start == ')') goto end +1958 # if (*word->start == '-') goto displacement +1959 # if (*word->start != '+') goto error1 +1960 # ++word->start to skip '+' +1961 # skip whitespace +1962 # if next 3 characters don't make a register, goto displacement +1963 # read register into index +1964 # skip whitespace +1965 # if (*word->start == ')') goto end +1966 # if (*word->start == '<') { +1967 # ++word->start to skip '<' +1968 # if (*word->start != '<') goto error2 +1969 # ++word->start to skip '<' +1970 # skip whitespace +1971 # read integer into scale +1972 # skip whitespace +1973 # if (*word->start == ')') goto end +1974 # } +1975 # if (*word->start not in '+' '-') goto error3 +1976 # displacement: +1977 # read integer into disp +1978 # skip whitespace +1979 # if (*word->start != ')') goto error4 +1980 # . prolog +1981 55/push-ebp +1982 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +1983 # . save registers +1984 56/push-esi +1985 57/push-edi +1986 # esi = word +1987 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi +1988 # ++word->start to skip '*' +1989 ff 0/subop/increment 0/mod/indirect 6/rm32/esi . . . . . . # increment *esi +1990 # initialize defaults +1991 # base is in edi; we'll move it to eax just before we return +1992 bf/copy-to-edi 0/imm32 +1993 b9/copy-to-ecx 4/imm32/no-index +1994 ba/copy-to-edx 0/imm32/.scale +1995 bb/copy-to-ebx 0/imm32/disp +1996 $parse-effective-address:check-for-simple-register: +1997 # if (*word->start == '(') goto compound expression +1998 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax +1999 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL +2000 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax +2001 3d/compare-eax-and 0x28/imm32/open-paren +2002 74/jump-if-equal $parse-effective-address:compound-expression/disp8 +2003 $parse-effective-address:simple-register: +2004 # base = get-slice(Registers, word, row-size=8) +2005 # . eax = get-slice(Registers, word, row-size=8) +2006 # . . push args +2007 68/push "Registers"/imm32 +2008 68/push 8/imm32/row-size +2009 56/push-esi +2010 68/push Registers/imm32 +2011 # . . call +2012 e8/call get-slice/disp32 +2013 # . . discard args +2014 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp +2015 # . base = *eax +2016 8b/copy 0/mod/indirect 0/rm32/eax . . . 7/r32/edi . . # copy *eax to edi +2017 # return +2018 e9/jump $parse-effective-address:end/disp32 +2019 $parse-effective-address:compound-expression: +2020 # ++word->start to skip '(' +2021 ff 0/subop/increment 0/mod/indirect 6/rm32/esi . . . . . . # increment *esi +2022 # skip whitespace +2023 # . eax = skip-chars-matching-whitespace-in-slice(word->start, word->end) +2024 # . . push args +2025 ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) +2026 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi +2027 # . . call +2028 e8/call skip-chars-matching-whitespace-in-slice/disp32 +2029 # . . discard args +2030 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2031 # . word->start = eax +2032 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi +2033 # read register into base +2034 # . eax = next-register(word) +2035 # . . push args +2036 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +2037 # . . call +2038 e8/call next-register/disp32 +2039 # . . discard args +2040 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +2041 # . edi = *eax +2042 8b/copy 0/mod/indirect 0/rm32/eax . . . 7/r32/edi . . # copy *eax to edi +2043 # skip whitespace +2044 # . eax = skip-chars-matching-whitespace-in-slice(word->start, word->end) +2045 # . . push args +2046 ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) +2047 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi +2048 # . . call +2049 e8/call skip-chars-matching-whitespace-in-slice/disp32 +2050 # . . discard args +2051 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2052 # . word->start = eax +2053 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi +2054 # if (*word->start == ')') goto end +2055 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL +2056 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax +2057 3d/compare-eax-and 0x29/imm32/close-paren +2058 0f 84/jump-if-equal $parse-effective-address:end/disp32 +2059 # if (*word->start == '-') goto displacement +2060 3d/compare-eax-and 0x2d/imm32/minus +2061 0f 84/jump-if-equal $parse-effective-address:displacement/disp32 +2062 # if (*word->start != '+') goto error1 +2063 3d/compare-eax-and 0x2b/imm32/plus +2064 0f 85/jump-if-not-equal $parse-effective-address:error1/disp32 +2065 $parse-effective-address:check-for-index: +2066 # ++word->start to skip '+' +2067 ff 0/subop/increment 0/mod/indirect 6/rm32/esi . . . . . . # increment *esi +2068 # skip whitespace +2069 # . eax = skip-chars-matching-whitespace-in-slice(word->start, word->end) +2070 # . . push args +2071 ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) +2072 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi +2073 # . . call +2074 e8/call skip-chars-matching-whitespace-in-slice/disp32 +2075 # . . discard args +2076 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2077 # . word->start = eax +2078 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi +2079 $parse-effective-address:resolve-ambiguity: +2080 # if next 3 characters don't make a register, goto displacement +2081 # . spill ecx +2082 51/push-ecx +2083 # . var tmp/ecx = {word->start, word->start+3} +2084 # . . ecx = word->start +2085 89/copy 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # copy eax to ecx +2086 # . . eax = word->start+3 +2087 05/add-to-eax 3/imm32 +2088 # . . push +2089 50/push-eax +2090 51/push-ecx +2091 # . . copy esp to ecx +2092 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +2093 # . eax = maybe-get-slice(Register, tmp, row-size=8) +2094 # . . push args +2095 68/push 8/imm32/row-size +2096 51/push-ecx +2097 68/push Registers/imm32 +2098 # . . call +2099 e8/call maybe-get-slice/disp32 +2100 # . . discard args +2101 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2102 # . reclaim tmp +2103 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2104 # . restore ecx +2105 59/pop-to-ecx +2106 # . if (eax == 0) goto displacement +2107 3d/compare-eax-and 0/imm32 +2108 0f 84/jump-if-equal $parse-effective-address:displacement/disp32 +2109 $parse-effective-address:index: +2110 # read register into index +2111 # . eax = next-register(word) +2112 # . . push args +2113 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +2114 # . . call +2115 e8/call next-register/disp32 +2116 # . . discard args +2117 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +2118 # . ecx = *eax +2119 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +2120 # skip whitespace +2121 # . eax = skip-chars-matching-whitespace-in-slice(word->start, word->end) +2122 # . . push args +2123 ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) +2124 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi +2125 # . . call +2126 e8/call skip-chars-matching-whitespace-in-slice/disp32 +2127 # . . discard args +2128 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2129 # . word->start = eax +2130 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi +2131 # if (*word->start == ')') goto end +2132 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL +2133 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax +2134 3d/compare-eax-and 0x29/imm32/close-paren +2135 0f 84/jump-if-equal $parse-effective-address:end/disp32 +2136 $parse-effective-address:check-for-scale: +2137 # if (*word->start != '<') goto next check +2138 3d/compare-eax-and 0x3c/imm32/less-than +2139 75/jump-if-not-equal $parse-effective-address:check-for-displacement/disp8 +2140 # ++word->start to skip '<' +2141 ff 0/subop/increment 0/mod/indirect 6/rm32/esi . . . . . . # increment *esi +2142 # if (*word->start != '<') goto error2 +2143 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax +2144 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL +2145 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax +2146 3d/compare-eax-and 0x3c/imm32/less-than +2147 0f 85/jump-if-not-equal $parse-effective-address:error2/disp32 +2148 # ++word->start to skip '<' +2149 ff 0/subop/increment 0/mod/indirect 6/rm32/esi . . . . . . # increment *esi +2150 # skip whitespace +2151 # . eax = skip-chars-matching-whitespace-in-slice(word->start, word->end) +2152 # . . push args +2153 ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) +2154 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi +2155 # . . call +2156 e8/call skip-chars-matching-whitespace-in-slice/disp32 +2157 # . . discard args +2158 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2159 # . word->start = eax +2160 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi +2161 $parse-effective-address:scale: +2162 # read positive integer into scale +2163 # . eax = next-positive-hex-int(word) +2164 # . . push args +2165 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +2166 # . . call +2167 e8/call next-positive-hex-int/disp32 +2168 # . . discard args +2169 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +2170 # . edx = eax +2171 89/copy 3/mod/direct 2/rm32/edx . . . 0/r32/eax . . # copy eax to edx +2172 # skip whitespace +2173 # . eax = skip-chars-matching-whitespace-in-slice(word->start, word->end) +2174 # . . push args +2175 ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) +2176 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi +2177 # . . call +2178 e8/call skip-chars-matching-whitespace-in-slice/disp32 +2179 # . . discard args +2180 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2181 # . word->start = eax +2182 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi +2183 # if (*word->start == ')') goto end +2184 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL +2185 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax +2186 3d/compare-eax-and 0x29/imm32/close-paren +2187 74/jump-if-equal $parse-effective-address:end/disp8 +2188 $parse-effective-address:check-for-displacement: +2189 # if (*word->start not in '+' '-') goto error3 +2190 3d/compare-eax-and 0x2b/imm32/plus +2191 74/jump-if-equal $parse-effective-address:displacement/disp8 +2192 3d/compare-eax-and 0x2d/imm32/minus +2193 74/jump-if-equal $parse-effective-address:displacement/disp8 +2194 e9/jump $parse-effective-address:error3/disp32 +2195 $parse-effective-address:displacement: +2196 # read integer into disp +2197 # . eax = next-hex-int(word) +2198 # . . push args +2199 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +2200 # . . call +2201 e8/call next-hex-int/disp32 +2202 # . . discard args +2203 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +2204 # . ebx = eax +2205 89/copy 3/mod/direct 3/rm32/ebx . . . 0/r32/eax . . # copy eax to ebx +2206 # skip whitespace +2207 # . eax = skip-chars-matching-whitespace-in-slice(word->start, word->end) +2208 # . . push args +2209 ff 6/subop/push 1/mod/*+disp8 6/rm32/esi . . . . 4/disp8 . # push *(esi+4) +2210 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi +2211 # . . call +2212 e8/call skip-chars-matching-whitespace-in-slice/disp32 +2213 # . . discard args +2214 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2215 # . word->start = eax +2216 89/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy eax to *esi +2217 # if (*word->start != ')') goto error4 +2218 8a/copy-byte 0/mod/indirect 0/rm32/eax . . . 0/r32/AL . . # copy byte at *eax to AL +2219 81 4/subop/and 3/mod/direct 0/rm32/eax . . . . . 0xff/imm32 # bitwise and of eax +2220 3d/compare-eax-and 0x29/imm32/close-paren +2221 0f 85/jump-if-not-equal $parse-effective-address:error4/disp32 +2222 $parse-effective-address:end: +2223 # return base in eax +2224 89/copy 3/mod/direct 0/rm32/eax . . . 7/r32/edi . . # copy edi to eax +2225 # . restore registers +2226 5f/pop-to-edi +2227 5e/pop-to-esi +2228 # . epilog +2229 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +2230 5d/pop-to-ebp +2231 c3/return +2232 +2233 $parse-effective-address:error1: +2234 # print(stderr, "error: unexpected character: " eax "\n") +2235 # . write-buffered(Stderr, "error: unexpected character: ") +2236 # . . push args +2237 68/push "error: unexpected character: "/imm32 +2238 68/push Stderr/imm32 +2239 # . . call +2240 e8/call write-buffered/disp32 +2241 # . . discard args +2242 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2243 # . print-int32-buffered(out, eax) +2244 # . . push args +2245 50/push-eax +2246 68/push Stderr/imm32 +2247 # . . call +2248 e8/call print-int32-buffered/disp32 +2249 # . . discard args +2250 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2251 # . write-buffered(Stderr, "\n") +2252 # . . push args +2253 68/push "\n"/imm32 +2254 68/push Stderr/imm32 +2255 # . . call +2256 e8/call write-buffered/disp32 +2257 # . . discard args +2258 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2259 # . flush(Stderr) +2260 # . . push args +2261 68/push Stderr/imm32 +2262 # . . call +2263 e8/call flush/disp32 +2264 # . . discard args +2265 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +2266 # . syscall(exit, 1) +2267 bb/copy-to-ebx 1/imm32 +2268 b8/copy-to-eax 1/imm32/exit +2269 cd/syscall 0x80/imm8 +2270 # never gets here +2271 +2272 $parse-effective-address:error2: +2273 # print(stderr, "error: '<' can only be followed by '<' but got: " eax "\n") +2274 # . write-buffered(Stderr, "error: '<' can only be followed by '<' but got: ") +2275 # . . push args +2276 68/push "error: '<' can only be followed by '<' but got: "/imm32 +2277 68/push Stderr/imm32 +2278 # . . call +2279 e8/call write-buffered/disp32 +2280 # . . discard args +2281 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2282 # . print-int32-buffered(out, eax) +2283 # . . push args +2284 50/push-eax +2285 68/push Stderr/imm32 +2286 # . . call +2287 e8/call print-int32-buffered/disp32 +2288 # . . discard args +2289 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2290 # . write-buffered(Stderr, "\n") +2291 # . . push args +2292 68/push "\n"/imm32 +2293 68/push Stderr/imm32 +2294 # . . call +2295 e8/call write-buffered/disp32 +2296 # . . discard args +2297 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2298 # . flush(Stderr) +2299 # . . push args +2300 68/push Stderr/imm32 +2301 # . . call +2302 e8/call flush/disp32 +2303 # . . discard args +2304 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +2305 # . syscall(exit, 1) +2306 bb/copy-to-ebx 1/imm32 +2307 b8/copy-to-eax 1/imm32/exit +2308 cd/syscall 0x80/imm8 +2309 # never gets here +2310 +2311 $parse-effective-address:error3: +2312 # print(stderr, "error: unexpected character before displacement: " eax "\n") +2313 # . write-buffered(Stderr, "error: unexpected character before displacement: ") +2314 # . . push args +2315 68/push "error: unexpected character before displacement: "/imm32 +2316 68/push Stderr/imm32 +2317 # . . call +2318 e8/call write-buffered/disp32 +2319 # . . discard args +2320 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2321 # . print-int32-buffered(out, eax) +2322 # . . push args +2323 50/push-eax +2324 68/push Stderr/imm32 +2325 # . . call +2326 e8/call print-int32-buffered/disp32 +2327 # . . discard args +2328 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2329 # . write-buffered(Stderr, "\n") +2330 # . . push args +2331 68/push "\n"/imm32 +2332 68/push Stderr/imm32 +2333 # . . call +2334 e8/call write-buffered/disp32 +2335 # . . discard args +2336 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2337 # . flush(Stderr) +2338 # . . push args +2339 68/push Stderr/imm32 +2340 # . . call +2341 e8/call flush/disp32 +2342 # . . discard args +2343 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +2344 # . syscall(exit, 1) +2345 bb/copy-to-ebx 1/imm32 +2346 b8/copy-to-eax 1/imm32/exit +2347 cd/syscall 0x80/imm8 +2348 # never gets here +2349 +2350 $parse-effective-address:error4: +2351 # print(stderr, "error: unexpected character after displacement: " eax "; expected ')' to wrap up\n") +2352 # . write-buffered(Stderr, "error: unexpected character after displacement: ") +2353 # . . push args +2354 68/push "error: unexpected character after displacement: "/imm32 +2355 68/push Stderr/imm32 +2356 # . . call +2357 e8/call write-buffered/disp32 +2358 # . . discard args +2359 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2360 # . print-int32-buffered(out, eax) +2361 # . . push args +2362 50/push-eax +2363 68/push Stderr/imm32 +2364 # . . call +2365 e8/call print-int32-buffered/disp32 +2366 # . . discard args +2367 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2368 # . write-buffered(Stderr, "; expected ')' to wrap up\n") +2369 # . . push args +2370 68/push "; expected ')' to wrap up\n"/imm32 +2371 68/push Stderr/imm32 +2372 # . . call +2373 e8/call write-buffered/disp32 +2374 # . . discard args +2375 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2376 # . flush(Stderr) +2377 # . . push args +2378 68/push Stderr/imm32 +2379 # . . call +2380 e8/call flush/disp32 +2381 # . . discard args +2382 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +2383 # . syscall(exit, 1) +2384 bb/copy-to-ebx 1/imm32 +2385 b8/copy-to-eax 1/imm32/exit +2386 cd/syscall 0x80/imm8 +2387 # never gets here +2388 +2389 # assumes 'in' starts with a register name, and returns pointer to its code +2390 # side-effect: modifies 'in' to scan past the initial register name +2391 next-register: # in : (address slice) -> reg/eax : int +2392 # . prolog +2393 55/push-ebp +2394 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +2395 # . save registers +2396 51/push-ecx +2397 56/push-esi +2398 # esi = in +2399 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi +2400 # var reg-slice/ecx : (address slice) = {in->start, in->start + 3} +2401 8b/copy 0/mod/indirect 6/rm32/esi . . . 0/r32/eax . . # copy *esi to eax +2402 05/add-to-eax 3/imm32 +2403 50/push-eax +2404 ff 6/subop/push 0/mod/indirect 6/rm32/esi . . . . . . # push *esi +2405 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +2406 # in->start += 3 +2407 81 0/subop/add 0/mod/indirect 6/rm32/esi . . . . . 3/imm32 # add to *esi +2408 # eax = get-slice(Registers, word, row-size=8) +2409 # . . push args +2410 68/push "next-register"/imm32 +2411 68/push 8/imm32/row-size +2412 51/push-ecx +2413 68/push Registers/imm32 +2414 # . . call +2415 e8/call get-slice/disp32 +2416 # . . discard args +2417 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x10/imm32 # add to esp +2418 $next-register:end: +2419 # reclaim locals +2420 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2421 # . restore registers +2422 5e/pop-to-esi +2423 59/pop-to-ecx +2424 # . epilog +2425 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +2426 5d/pop-to-ebp +2427 c3/return +2428 +2429 test-parse-effective-address-simple: +2430 # . prolog +2431 55/push-ebp +2432 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +2433 # var slice/ecx = "*esi" +2434 b8/copy-to-eax "*esi"/imm32 +2435 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +2436 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 +2437 05/add-to-eax 4/imm32 +2438 # . ecx = {eax, ecx} +2439 51/push-ecx +2440 50/push-eax +2441 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +2442 # eax, ecx, edx, ebx = parse-effective-address(slice) +2443 # . . push args +2444 51/push-ecx +2445 # . . call +2446 e8/call parse-effective-address/disp32 +2447 # . . discard args +2448 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +2449 # slice clobbered beyond this point +2450 # check-ints-equal(eax, 6, msg) +2451 # . . push args +2452 68/push "F - test-parse-effective-address-simple/base"/imm32 +2453 68/push 6/imm32/esi +2454 50/push-eax +2455 # . . call +2456 e8/call check-ints-equal/disp32 +2457 # . . discard args +2458 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2459 # check-ints-equal(ecx, 4, msg) +2460 # . . push args +2461 68/push "F - test-parse-effective-address-simple/index"/imm32 +2462 68/push 4/imm32/none +2463 51/push-ecx +2464 # . . call +2465 e8/call check-ints-equal/disp32 +2466 # . . discard args +2467 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2468 # check-ints-equal(edx, 0, msg) +2469 # . . push args +2470 68/push "F - test-parse-effective-address-simple/scale"/imm32 +2471 68/push 0/imm32/none +2472 52/push-edx +2473 # . . call +2474 e8/call check-ints-equal/disp32 +2475 # . . discard args +2476 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2477 # check-ints-equal(ebx, 0, msg) +2478 # . . push args +2479 68/push "F - test-parse-effective-address-simple/displacement"/imm32 +2480 68/push 0/imm32/none +2481 53/push-ebx +2482 # . . call +2483 e8/call check-ints-equal/disp32 +2484 # . . discard args +2485 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2486 # . epilog +2487 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +2488 5d/pop-to-ebp +2489 c3/return +2490 +2491 test-parse-effective-address-base: +2492 # . prolog +2493 55/push-ebp +2494 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +2495 # var slice/ecx = "*(esi )" +2496 b8/copy-to-eax "*(esi )"/imm32 +2497 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +2498 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 +2499 05/add-to-eax 4/imm32 +2500 # . ecx = {eax, ecx} +2501 51/push-ecx +2502 50/push-eax +2503 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +2504 # eax, ecx, edx, ebx = parse-effective-address(slice) +2505 # . . push args +2506 51/push-ecx +2507 # . . call +2508 e8/call parse-effective-address/disp32 +2509 # . . discard args +2510 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +2511 # slice clobbered beyond this point +2512 # check-ints-equal(eax, 6, msg) +2513 # . . push args +2514 68/push "F - test-parse-effective-address-base/base"/imm32 +2515 68/push 6/imm32/esi +2516 50/push-eax +2517 # . . call +2518 e8/call check-ints-equal/disp32 +2519 # . . discard args +2520 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2521 # check-ints-equal(ecx, 4, msg) +2522 # . . push args +2523 68/push "F - test-parse-effective-address-base/index"/imm32 +2524 68/push 4/imm32/none +2525 51/push-ecx +2526 # . . call +2527 e8/call check-ints-equal/disp32 +2528 # . . discard args +2529 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2530 # check-ints-equal(edx, 0, msg) +2531 # . . push args +2532 68/push "F - test-parse-effective-address-base/scale"/imm32 +2533 68/push 0/imm32/none +2534 52/push-edx +2535 # . . call +2536 e8/call check-ints-equal/disp32 +2537 # . . discard args +2538 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2539 # check-ints-equal(ebx, 0, msg) +2540 # . . push args +2541 68/push "F - test-parse-effective-address-base/displacement"/imm32 +2542 68/push 0/imm32/none +2543 53/push-ebx +2544 # . . call +2545 e8/call check-ints-equal/disp32 +2546 # . . discard args +2547 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2548 # . epilog +2549 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +2550 5d/pop-to-ebp +2551 c3/return +2552 +2553 test-parse-effective-address-base-displacement: +2554 # . prolog +2555 55/push-ebp +2556 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +2557 # var slice/ecx = "*(esi+3)" +2558 b8/copy-to-eax "*(esi+3)"/imm32 +2559 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +2560 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 +2561 05/add-to-eax 4/imm32 +2562 # . ecx = {eax, ecx} +2563 51/push-ecx +2564 50/push-eax +2565 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +2566 # eax, ecx, edx, ebx = parse-effective-address(slice) +2567 # . . push args +2568 51/push-ecx +2569 # . . call +2570 e8/call parse-effective-address/disp32 +2571 # . . discard args +2572 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +2573 # slice clobbered beyond this point +2574 # check-ints-equal(eax, 6, msg) +2575 # . . push args +2576 68/push "F - test-parse-effective-address-base-displacement/base"/imm32 +2577 68/push 6/imm32/esi +2578 50/push-eax +2579 # . . call +2580 e8/call check-ints-equal/disp32 +2581 # . . discard args +2582 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2583 # check-ints-equal(ecx, 4, msg) +2584 # . . push args +2585 68/push "F - test-parse-effective-address-base-displacement/index"/imm32 +2586 68/push 4/imm32/none +2587 51/push-ecx +2588 # . . call +2589 e8/call check-ints-equal/disp32 +2590 # . . discard args +2591 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2592 # check-ints-equal(edx, 0, msg) +2593 # . . push args +2594 68/push "F - test-parse-effective-address-base-displacement/scale"/imm32 +2595 68/push 0/imm32/none +2596 52/push-edx +2597 # . . call +2598 e8/call check-ints-equal/disp32 +2599 # . . discard args +2600 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2601 # check-ints-equal(ebx, 3, msg) +2602 # . . push args +2603 68/push "F - test-parse-effective-address-base-displacement/displacement"/imm32 +2604 68/push 3/imm32 +2605 53/push-ebx +2606 # . . call +2607 e8/call check-ints-equal/disp32 +2608 # . . discard args +2609 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2610 # . epilog +2611 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +2612 5d/pop-to-ebp +2613 c3/return +2614 +2615 test-parse-effective-address-base-negative-displacement: +2616 # . prolog +2617 55/push-ebp +2618 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +2619 # var slice/ecx = "*(esi-3)" +2620 b8/copy-to-eax "*(esi-3)"/imm32 +2621 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +2622 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 +2623 05/add-to-eax 4/imm32 +2624 # . ecx = {eax, ecx} +2625 51/push-ecx +2626 50/push-eax +2627 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +2628 # eax, ecx, edx, ebx = parse-effective-address(slice) +2629 # . . push args +2630 51/push-ecx +2631 # . . call +2632 e8/call parse-effective-address/disp32 +2633 # . . discard args +2634 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +2635 # slice clobbered beyond this point +2636 # check-ints-equal(eax, 6, msg) +2637 # . . push args +2638 68/push "F - test-parse-effective-address-base-negative-displacement/base"/imm32 +2639 68/push 6/imm32/esi +2640 50/push-eax +2641 # . . call +2642 e8/call check-ints-equal/disp32 +2643 # . . discard args +2644 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2645 # check-ints-equal(ecx, 4, msg) +2646 # . . push args +2647 68/push "F - test-parse-effective-address-base-negative-displacement/index"/imm32 +2648 68/push 4/imm32/none +2649 51/push-ecx +2650 # . . call +2651 e8/call check-ints-equal/disp32 +2652 # . . discard args +2653 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2654 # check-ints-equal(edx, 0, msg) +2655 # . . push args +2656 68/push "F - test-parse-effective-address-base-negative-displacement/scale"/imm32 +2657 68/push 0/imm32/none +2658 52/push-edx +2659 # . . call +2660 e8/call check-ints-equal/disp32 +2661 # . . discard args +2662 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2663 # check-ints-equal(ebx, -3, msg) +2664 # . . push args +2665 68/push "F - test-parse-effective-address-base-negative-displacement/displacement"/imm32 +2666 68/push -3/imm32 +2667 53/push-ebx +2668 # . . call +2669 e8/call check-ints-equal/disp32 +2670 # . . discard args +2671 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2672 # . epilog +2673 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +2674 5d/pop-to-ebp +2675 c3/return +2676 +2677 test-parse-effective-address-base-index: +2678 # . prolog +2679 55/push-ebp +2680 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +2681 # var slice/ecx = "*(esi+ecx)" +2682 b8/copy-to-eax "*(esi+ecx)"/imm32 +2683 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +2684 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 +2685 05/add-to-eax 4/imm32 +2686 # . ecx = {eax, ecx} +2687 51/push-ecx +2688 50/push-eax +2689 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +2690 # eax, ecx, edx, ebx = parse-effective-address(slice) +2691 # . . push args +2692 51/push-ecx +2693 # . . call +2694 e8/call parse-effective-address/disp32 +2695 # . . discard args +2696 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +2697 # slice clobbered beyond this point +2698 # check-ints-equal(eax, 6, msg) +2699 # . . push args +2700 68/push "F - test-parse-effective-address-base-index/base"/imm32 +2701 68/push 6/imm32/esi +2702 50/push-eax +2703 # . . call +2704 e8/call check-ints-equal/disp32 +2705 # . . discard args +2706 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2707 # check-ints-equal(ecx, 1, msg) +2708 # . . push args +2709 68/push "F - test-parse-effective-address-base-index/index"/imm32 +2710 68/push 1/imm32/none +2711 51/push-ecx +2712 # . . call +2713 e8/call check-ints-equal/disp32 +2714 # . . discard args +2715 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2716 # check-ints-equal(edx, 0, msg) +2717 # . . push args +2718 68/push "F - test-parse-effective-address-base-index/scale"/imm32 +2719 68/push 0/imm32/none +2720 52/push-edx +2721 # . . call +2722 e8/call check-ints-equal/disp32 +2723 # . . discard args +2724 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2725 # check-ints-equal(ebx, 0, msg) +2726 # . . push args +2727 68/push "F - test-parse-effective-address-base-index/displacement"/imm32 +2728 68/push 0/imm32 +2729 53/push-ebx +2730 # . . call +2731 e8/call check-ints-equal/disp32 +2732 # . . discard args +2733 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2734 # . epilog +2735 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +2736 5d/pop-to-ebp +2737 c3/return +2738 +2739 test-parse-effective-address-base-index-scale: +2740 # . prolog +2741 55/push-ebp +2742 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +2743 # var slice/ecx = "*(esi+ecx<<2)" +2744 b8/copy-to-eax "*(esi+ecx<<2)"/imm32 +2745 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +2746 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 +2747 05/add-to-eax 4/imm32 +2748 # . ecx = {eax, ecx} +2749 51/push-ecx +2750 50/push-eax +2751 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +2752 # eax, ecx, edx, ebx = parse-effective-address(slice) +2753 # . . push args +2754 51/push-ecx +2755 # . . call +2756 e8/call parse-effective-address/disp32 +2757 # . . discard args +2758 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +2759 # slice clobbered beyond this point +2760 # check-ints-equal(eax, 6, msg) +2761 # . . push args +2762 68/push "F - test-parse-effective-address-base-index-scale/base"/imm32 +2763 68/push 6/imm32/esi +2764 50/push-eax +2765 # . . call +2766 e8/call check-ints-equal/disp32 +2767 # . . discard args +2768 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2769 # check-ints-equal(ecx, 1, msg) +2770 # . . push args +2771 68/push "F - test-parse-effective-address-base-index-scale/index"/imm32 +2772 68/push 1/imm32/none +2773 51/push-ecx +2774 # . . call +2775 e8/call check-ints-equal/disp32 +2776 # . . discard args +2777 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2778 # check-ints-equal(edx, 2, msg) +2779 # . . push args +2780 68/push "F - test-parse-effective-address-base-index-scale/scale"/imm32 +2781 68/push 2/imm32 +2782 52/push-edx +2783 # . . call +2784 e8/call check-ints-equal/disp32 +2785 # . . discard args +2786 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2787 # check-ints-equal(ebx, 0, msg) +2788 # . . push args +2789 68/push "F - test-parse-effective-address-base-index-scale/displacement"/imm32 +2790 68/push 0/imm32 +2791 53/push-ebx +2792 # . . call +2793 e8/call check-ints-equal/disp32 +2794 # . . discard args +2795 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2796 # . epilog +2797 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +2798 5d/pop-to-ebp +2799 c3/return +2800 +2801 test-parse-effective-address-base-index-scale-displacement: +2802 # . prolog +2803 55/push-ebp +2804 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +2805 # var slice/ecx = "*(esi + ecx<<2 - 0x34)" +2806 b8/copy-to-eax "*(esi + ecx<<2 - 0x34)"/imm32 +2807 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +2808 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 +2809 05/add-to-eax 4/imm32 +2810 # . ecx = {eax, ecx} +2811 51/push-ecx +2812 50/push-eax +2813 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +2814 # eax, ecx, edx, ebx = parse-effective-address(slice) +2815 # . . push args +2816 51/push-ecx +2817 # . . call +2818 e8/call parse-effective-address/disp32 +2819 # . . discard args +2820 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +2821 # slice clobbered beyond this point +2822 # check-ints-equal(eax, 6, msg) +2823 # . . push args +2824 68/push "F - test-parse-effective-address-base-index-scale/base"/imm32 +2825 68/push 6/imm32/esi +2826 50/push-eax +2827 # . . call +2828 e8/call check-ints-equal/disp32 +2829 # . . discard args +2830 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2831 # check-ints-equal(ecx, 1, msg) +2832 # . . push args +2833 68/push "F - test-parse-effective-address-base-index-scale/index"/imm32 +2834 68/push 1/imm32/none +2835 51/push-ecx +2836 # . . call +2837 e8/call check-ints-equal/disp32 +2838 # . . discard args +2839 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2840 # check-ints-equal(edx, 2, msg) +2841 # . . push args +2842 68/push "F - test-parse-effective-address-base-index-scale/scale"/imm32 +2843 68/push 2/imm32 +2844 52/push-edx +2845 # . . call +2846 e8/call check-ints-equal/disp32 +2847 # . . discard args +2848 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2849 # check-ints-equal(ebx, -0x34, msg) +2850 # . . push args +2851 68/push "F - test-parse-effective-address-base-index-scale/displacement"/imm32 +2852 68/push -0x34/imm32 +2853 53/push-ebx +2854 # . . call +2855 e8/call check-ints-equal/disp32 +2856 # . . discard args +2857 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +2858 # . epilog +2859 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +2860 5d/pop-to-ebp +2861 c3/return +2862 +2863 # Code generation: +2864 # if base is esp, then goto emit-sib +2865 # if base is ebp, then goto emit-sib +2866 # if index is none and disp is 0, then mod = 0 and rm32 = base +2867 # if index is none, then mod = 2 and rm32 = base and disp32 = disp +2868 # emit-sib: +2869 # if index is not none, then mod = 2 and rm32 = 4 and base = base and index = index and disp32 = disp +2870 emit-indirect-mode: # out : (address buffered-file), base : int, index : int, scale : int, disp : int +2871 # . prolog +2872 55/push-ebp +2873 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +2874 $emit-indirect-mode:check-for-ebp: +2875 # if (base == 5) goto emit-sib +2876 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 5/imm32 # compare *(ebp+12) +2877 74/jump-if-equal $emit-indirect-mode:emit-sib/disp8 +2878 $emit-indirect-mode:check-for-esp: +2879 # if (base == 4) goto emit-sib +2880 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 4/imm32 # compare *(ebp+12) +2881 74/jump-if-equal $emit-indirect-mode:emit-sib/disp8 +2882 $emit-indirect-mode:check-for-sib: +2883 # if (index == 4/none) goto next check +2884 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 4/imm32 # compare *(ebp+16) +2885 0f 84/jump-if-equal $emit-indirect-mode:check-for-disp/disp32 +2886 $emit-indirect-mode:emit-sib: +2887 # emit(out, "2/mod/indirect 4/rm32/sib " base "/base " index "/index " scale "/scale " disp "/disp32") +2888 # . write-buffered(out, "2/mod/*+disp32 4/rm32/sib ") +2889 # . . push args +2890 68/push "2/mod/*+disp32 4/rm32/sib "/imm32 +2891 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +2892 # . . call +2893 e8/call write-buffered/disp32 +2894 # . . discard args +2895 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2896 # . print-int32-buffered(out, base) +2897 # . . push args +2898 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) +2899 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +2900 # . . call +2901 e8/call print-int32-buffered/disp32 +2902 # . . discard args +2903 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2904 # . write-buffered(out, "/base ") +2905 # . . push args +2906 68/push "/base "/imm32 +2907 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +2908 # . . call +2909 e8/call write-buffered/disp32 +2910 # . . discard args +2911 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2912 # . print-int32-buffered(out, index) +2913 # . . push args +2914 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x10/disp8 . # push *(ebp+16) +2915 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +2916 # . . call +2917 e8/call print-int32-buffered/disp32 +2918 # . . discard args +2919 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2920 # . write-buffered(out, "/index ") +2921 # . . push args +2922 68/push "/index "/imm32 +2923 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +2924 # . . call +2925 e8/call write-buffered/disp32 +2926 # . . discard args +2927 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2928 # . print-int32-buffered(out, scale) +2929 # . . push args +2930 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x14/disp8 . # push *(ebp+20) +2931 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +2932 # . . call +2933 e8/call print-int32-buffered/disp32 +2934 # . . discard args +2935 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2936 # . write-buffered(out, "/scale ") +2937 # . . push args +2938 68/push "/scale "/imm32 +2939 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +2940 # . . call +2941 e8/call write-buffered/disp32 +2942 # . . discard args +2943 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2944 # . print-int32-buffered(out, disp) +2945 # . . push args +2946 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x18/disp8 . # push *(ebp+24) +2947 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +2948 # . . call +2949 e8/call print-int32-buffered/disp32 +2950 # . . discard args +2951 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2952 # . write-buffered(out, "/disp32") 2953 # . . push args -2954 68/push "2/mod/*+disp32 "/imm32 +2954 68/push "/disp32"/imm32 2955 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) 2956 # . . call 2957 e8/call write-buffered/disp32 2958 # . . discard args 2959 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2960 # . print-int32-buffered(out, base) -2961 # . . push args -2962 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) -2963 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2964 # . . call -2965 e8/call print-int32-buffered/disp32 -2966 # . . discard args -2967 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2968 # . write-buffered(out, "/rm32 ") -2969 # . . push args -2970 68/push "/rm32 "/imm32 -2971 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2972 # . . call -2973 e8/call write-buffered/disp32 -2974 # . . discard args -2975 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2976 # . print-int32-buffered(out, disp) -2977 # . . push args -2978 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x18/disp8 . # push *(ebp+24) -2979 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2980 # . . call -2981 e8/call print-int32-buffered/disp32 -2982 # . . discard args -2983 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2984 # . write-buffered(out, "/disp32") -2985 # . . push args -2986 68/push "/disp32"/imm32 -2987 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2988 # . . call -2989 e8/call write-buffered/disp32 -2990 # . . discard args -2991 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -2992 eb/jump $emit-indirect-mode:end/disp8 -2993 $emit-indirect-mode:emit-indirect: -2994 # emit(out, "0/mod/indirect " base "/rm32") -2995 # . write-buffered(out, "0/mod/indirect ") -2996 # . . push args -2997 68/push "0/mod/indirect "/imm32 -2998 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -2999 # . . call -3000 e8/call write-buffered/disp32 -3001 # . . discard args -3002 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -3003 # . print-int32-buffered(out, base) -3004 # . . push args -3005 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) -3006 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -3007 # . . call -3008 e8/call print-int32-buffered/disp32 -3009 # . . discard args -3010 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -3011 # . write-buffered(out, "/rm32") -3012 # . . push args -3013 68/push "/rm32"/imm32 -3014 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) -3015 # . . call -3016 e8/call write-buffered/disp32 -3017 # . . discard args -3018 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -3019 $emit-indirect-mode:end: -3020 # . epilog -3021 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -3022 5d/pop-to-ebp -3023 c3/return -3024 -3025 test-emit-indirect-mode: -3026 # . prolog -3027 55/push-ebp -3028 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -3029 # setup -3030 # . clear-stream(_test-output-stream) -3031 # . . push args -3032 68/push _test-output-stream/imm32 -3033 # . . call -3034 e8/call clear-stream/disp32 -3035 # . . discard args -3036 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3037 # . clear-stream(_test-output-buffered-file+4) -3038 # . . push args -3039 b8/copy-to-eax _test-output-buffered-file/imm32 -3040 05/add-to-eax 4/imm32 -3041 50/push-eax -3042 # . . call -3043 e8/call clear-stream/disp32 -3044 # . . discard args -3045 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3046 # emit-indirect-mode(_test-output-buffered-file, 0, 4/none, 0, 0) -3047 # . . write args -3048 68/push 0/imm32/.disp -3049 68/push 0/imm32/.scale -3050 68/push 4/imm32/.index/none -3051 68/push 0/imm32/.base -3052 68/push _test-output-buffered-file/imm32 -3053 # . . call -3054 e8/call emit-indirect-mode/disp32 -3055 # . . discard args -3056 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp -3057 # . flush(_test-output-buffered-file) -3058 # . . push args -3059 68/push _test-output-buffered-file/imm32 -3060 # . . call -3061 e8/call flush/disp32 -3062 # . . discard args -3063 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3064 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -3090 # check-stream-equal(_test-output-stream, "0/mod/indirect 0/rm32", msg) -3091 # . . push args -3092 68/push "F - test-emit-indirect-mode"/imm32 -3093 68/push "0/mod/indirect 0x00000000/rm32"/imm32 -3094 68/push _test-output-stream/imm32 -3095 # . . call -3096 e8/call check-stream-equal/disp32 -3097 # . . discard args -3098 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -3099 # . epilog -3100 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -3101 5d/pop-to-ebp -3102 c3/return -3103 -3104 test-emit-indirect-mode-2: -3105 # . prolog -3106 55/push-ebp -3107 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -3108 # setup -3109 # . clear-stream(_test-output-stream) -3110 # . . push args -3111 68/push _test-output-stream/imm32 -3112 # . . call -3113 e8/call clear-stream/disp32 -3114 # . . discard args -3115 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3116 # . clear-stream(_test-output-buffered-file+4) -3117 # . . push args -3118 b8/copy-to-eax _test-output-buffered-file/imm32 -3119 05/add-to-eax 4/imm32 -3120 50/push-eax -3121 # . . call -3122 e8/call clear-stream/disp32 -3123 # . . discard args -3124 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3125 # emit-indirect-mode(_test-output-buffered-file, 6, 4/none, 0, 0) -3126 # . . write args -3127 68/push 0/imm32/.disp -3128 68/push 0/imm32/.scale -3129 68/push 4/imm32/.index/none -3130 68/push 7/imm32/.base -3131 68/push _test-output-buffered-file/imm32 -3132 # . . call -3133 e8/call emit-indirect-mode/disp32 -3134 # . . discard args -3135 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp -3136 # . flush(_test-output-buffered-file) -3137 # . . push args -3138 68/push _test-output-buffered-file/imm32 -3139 # . . call -3140 e8/call flush/disp32 -3141 # . . discard args -3142 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3143 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -3169 # check-stream-equal(_test-output-stream, "0/mod/indirect 7/rm32", msg) -3170 # . . push args -3171 68/push "F - test-emit-indirect-mode-2"/imm32 -3172 68/push "0/mod/indirect 0x00000007/rm32"/imm32 -3173 68/push _test-output-stream/imm32 -3174 # . . call -3175 e8/call check-stream-equal/disp32 -3176 # . . discard args -3177 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -3178 # . epilog -3179 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -3180 5d/pop-to-ebp -3181 c3/return -3182 -3183 test-emit-indirect-mode-with-disp: -3184 # . prolog -3185 55/push-ebp -3186 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -3187 # setup -3188 # . clear-stream(_test-output-stream) -3189 # . . push args -3190 68/push _test-output-stream/imm32 -3191 # . . call -3192 e8/call clear-stream/disp32 -3193 # . . discard args -3194 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3195 # . clear-stream(_test-output-buffered-file+4) -3196 # . . push args -3197 b8/copy-to-eax _test-output-buffered-file/imm32 -3198 05/add-to-eax 4/imm32 -3199 50/push-eax -3200 # . . call -3201 e8/call clear-stream/disp32 -3202 # . . discard args -3203 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3204 # emit-indirect-mode(_test-output-buffered-file, 6, 4/none, 0, 4) -3205 # . . write args -3206 68/push 4/imm32/.disp -3207 68/push 0/imm32/.scale -3208 68/push 4/imm32/.index/none -3209 68/push 6/imm32/.base -3210 68/push _test-output-buffered-file/imm32 -3211 # . . call -3212 e8/call emit-indirect-mode/disp32 -3213 # . . discard args -3214 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp -3215 # . flush(_test-output-buffered-file) -3216 # . . push args -3217 68/push _test-output-buffered-file/imm32 -3218 # . . call -3219 e8/call flush/disp32 -3220 # . . discard args -3221 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3222 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -3248 # check-stream-equal(_test-output-stream, "2/mod/*+disp32 6/rm32 4/disp32", msg) -3249 # . . push args -3250 68/push "F - test-emit-indirect-mode-with-disp"/imm32 -3251 68/push "2/mod/*+disp32 0x00000006/rm32 0x00000004/disp32"/imm32 -3252 68/push _test-output-stream/imm32 -3253 # . . call -3254 e8/call check-stream-equal/disp32 -3255 # . . discard args -3256 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -3257 # . epilog -3258 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -3259 5d/pop-to-ebp -3260 c3/return -3261 -3262 test-emit-indirect-mode-with-disp-negative: -3263 # . prolog -3264 55/push-ebp -3265 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -3266 # setup -3267 # . clear-stream(_test-output-stream) -3268 # . . push args -3269 68/push _test-output-stream/imm32 -3270 # . . call -3271 e8/call clear-stream/disp32 -3272 # . . discard args -3273 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3274 # . clear-stream(_test-output-buffered-file+4) -3275 # . . push args -3276 b8/copy-to-eax _test-output-buffered-file/imm32 -3277 05/add-to-eax 4/imm32 -3278 50/push-eax -3279 # . . call -3280 e8/call clear-stream/disp32 -3281 # . . discard args -3282 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3283 # emit-indirect-mode(_test-output-buffered-file, 6, 4/none, 0, -4) -3284 # . . write args -3285 68/push -4/imm32/.disp -3286 68/push 0/imm32/.scale -3287 68/push 4/imm32/.index/none -3288 68/push 6/imm32/.base -3289 68/push _test-output-buffered-file/imm32 -3290 # . . call -3291 e8/call emit-indirect-mode/disp32 -3292 # . . discard args -3293 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp -3294 # . flush(_test-output-buffered-file) -3295 # . . push args -3296 68/push _test-output-buffered-file/imm32 -3297 # . . call -3298 e8/call flush/disp32 -3299 # . . discard args -3300 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3301 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -3327 # check-stream-equal(_test-output-stream, "2/mod/*+disp32 6/rm32 -4/disp32", msg) -3328 # . . push args -3329 68/push "F - test-emit-indirect-mode-with-disp"/imm32 -3330 68/push "2/mod/*+disp32 0x00000006/rm32 0xfffffffc/disp32"/imm32 -3331 68/push _test-output-stream/imm32 -3332 # . . call -3333 e8/call check-stream-equal/disp32 -3334 # . . discard args -3335 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -3336 # . epilog -3337 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -3338 5d/pop-to-ebp -3339 c3/return -3340 -3341 test-emit-indirect-mode-with-sib: -3342 # . prolog -3343 55/push-ebp -3344 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -3345 # setup -3346 # . clear-stream(_test-output-stream) -3347 # . . push args -3348 68/push _test-output-stream/imm32 -3349 # . . call -3350 e8/call clear-stream/disp32 -3351 # . . discard args -3352 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3353 # . clear-stream(_test-output-buffered-file+4) -3354 # . . push args -3355 b8/copy-to-eax _test-output-buffered-file/imm32 -3356 05/add-to-eax 4/imm32 -3357 50/push-eax -3358 # . . call -3359 e8/call clear-stream/disp32 -3360 # . . discard args -3361 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3362 # emit-indirect-mode(_test-output-buffered-file, 6/base, 1/index, 2/scale, 4/disp) -3363 # . . write args -3364 68/push 4/imm32/.disp -3365 68/push 2/imm32/.scale -3366 68/push 1/imm32/.index -3367 68/push 6/imm32/.base -3368 68/push _test-output-buffered-file/imm32 -3369 # . . call -3370 e8/call emit-indirect-mode/disp32 -3371 # . . discard args -3372 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp -3373 # . flush(_test-output-buffered-file) -3374 # . . push args -3375 68/push _test-output-buffered-file/imm32 -3376 # . . call -3377 e8/call flush/disp32 -3378 # . . discard args -3379 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3380 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -3406 # check-stream-equal(_test-output-stream, "2/mod/indirect 4/rm32/sib 6/base 1/index 2/scale 4/disp", msg) -3407 # . . push args -3408 68/push "F - test-emit-indirect-mode-with-sib"/imm32 -3409 68/push "2/mod/*+disp32 4/rm32/sib 0x00000006/base 0x00000001/index 0x00000002/scale 0x00000004/disp32"/imm32 -3410 68/push _test-output-stream/imm32 -3411 # . . call -3412 e8/call check-stream-equal/disp32 -3413 # . . discard args -3414 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -3415 # . epilog -3416 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -3417 5d/pop-to-ebp -3418 c3/return -3419 -3420 # update line->read to ')' -3421 # line->read ends at ')' -3422 skip-until-close-paren: # line : (address stream) -3423 # . prolog -3424 55/push-ebp -3425 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -3426 # . save registers -3427 50/push-eax -3428 51/push-ecx -3429 52/push-edx -3430 # ecx = line -3431 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx -3432 # eax = skip-until-close-paren-in-slice(&line->data[line->read], &line->data[line->write]) -3433 # . . push &line->data[line->write] -3434 8b/copy 1/mod/*+disp8 1/rm32/ecx . . 2/r32/edx 8/disp8 . # copy *(ecx+8) to edx -3435 8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx 0xc/disp8 . # copy ecx+edx+12 to edx -3436 52/push-edx -3437 # . . push &line->data[line->read] -3438 8b/copy 1/mod/*+disp8 1/rm32/ecx . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx -3439 8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx 0xc/disp8 . # copy ecx+edx+12 to edx -3440 52/push-edx -3441 # . . call -3442 e8/call skip-until-close-paren-in-slice/disp32 -3443 # . . discard args -3444 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -3445 # line->read = eax - line->data -3446 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax -3447 2d/subtract-from-eax 0xc/imm32 -3448 89/copy 1/mod/*+disp8 1/rm32/ecx . . 0/r32/eax 4/disp8 . # copy eax to *(ecx+4) -3449 $skip-until-close-paren:end: -3450 # . restore registers -3451 5a/pop-to-edx -3452 59/pop-to-ecx -3453 58/pop-to-eax -3454 # . epilog -3455 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -3456 5d/pop-to-ebp -3457 c3/return -3458 -3459 test-skip-until-close-paren: -3460 # . prolog -3461 55/push-ebp -3462 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -3463 # setup -3464 # . clear-stream(_test-input-stream) -3465 # . . push args -3466 68/push _test-input-stream/imm32 -3467 # . . call -3468 e8/call clear-stream/disp32 -3469 # . . discard args -3470 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3471 # . write(_test-input-stream, "*(abc) def") -3472 # . indices: 0123 45 -3473 # . . push args -3474 68/push "*(abc) def"/imm32 -3475 68/push _test-input-stream/imm32 -3476 # . . call -3477 e8/call write/disp32 -3478 # . . discard args -3479 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -3480 # precondition: line->read == 0 -3481 # . . push args -3482 68/push "F - test-skip-until-close-paren/precondition"/imm32 -3483 68/push 0/imm32 -3484 b8/copy-to-eax _test-input-stream/imm32 -3485 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) -3486 # . . call -3487 e8/call check-ints-equal/disp32 -3488 # . . discard args -3489 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -3490 # skip-until-close-paren(_test-input-stream) -3491 # . . push args -3492 68/push _test-input-stream/imm32 -3493 # . . call -3494 e8/call skip-until-close-paren/disp32 -3495 # . . discard args -3496 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3497 # check-ints-equal(line->read, 5, msg) -3498 # . . push args -3499 68/push "F - test-skip-until-close-paren"/imm32 -3500 68/push 5/imm32 -3501 b8/copy-to-eax _test-input-stream/imm32 -3502 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) -3503 # . . call -3504 e8/call check-ints-equal/disp32 -3505 # . . discard args -3506 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -3507 # . epilog -3508 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -3509 5d/pop-to-ebp -3510 c3/return -3511 -3512 test-skip-until-close-paren-ignores-spaces: -3513 # . prolog -3514 55/push-ebp -3515 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -3516 # setup -3517 # . clear-stream(_test-input-stream) -3518 # . . push args -3519 68/push _test-input-stream/imm32 -3520 # . . call -3521 e8/call clear-stream/disp32 -3522 # . . discard args -3523 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3524 # . write(_test-input-stream, "*(a b)/yz") -3525 # . . push args -3526 68/push "*(a b)/yz"/imm32 -3527 68/push _test-input-stream/imm32 -3528 # . . call -3529 e8/call write/disp32 -3530 # . . discard args -3531 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -3532 # precondition: line->read == 0 -3533 # . . push args -3534 68/push "F - test-skip-until-close-paren-ignores-spaces/precondition"/imm32 -3535 68/push 0/imm32 -3536 b8/copy-to-eax _test-input-stream/imm32 -3537 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) -3538 # . . call -3539 e8/call check-ints-equal/disp32 -3540 # . . discard args -3541 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -3542 # skip-until-close-paren(_test-input-stream) -3543 # . . push args -3544 68/push _test-input-stream/imm32 -3545 # . . call -3546 e8/call skip-until-close-paren/disp32 -3547 # . . discard args -3548 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3549 # check-ints-equal(line->read, 5, msg) -3550 # . . push args -3551 68/push "F - test-skip-until-close-paren-ignores-spaces"/imm32 -3552 68/push 5/imm32 -3553 b8/copy-to-eax _test-input-stream/imm32 -3554 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) -3555 # . . call -3556 e8/call check-ints-equal/disp32 -3557 # . . discard args -3558 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -3559 # . epilog -3560 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -3561 5d/pop-to-ebp -3562 c3/return -3563 -3564 test-skip-until-close-paren-works-from-mid-stream: -3565 # . prolog -3566 55/push-ebp -3567 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -3568 # setup -3569 # . clear-stream(_test-input-stream) -3570 # . . push args -3571 68/push _test-input-stream/imm32 -3572 # . . call -3573 e8/call clear-stream/disp32 -3574 # . . discard args -3575 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3576 # . write(_test-input-stream, "0 *(a b)/yz") -3577 # . . push args -3578 68/push "0 *(a b)/yz"/imm32 -3579 68/push _test-input-stream/imm32 -3580 # . . call -3581 e8/call write/disp32 -3582 # . . discard args -3583 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -3584 # precondition: _test-input-stream->read == 2 -3585 c7 0/subop/copy 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 2/imm32 # copy to *(eax+4) -3586 # skip-until-close-paren(_test-input-stream) -3587 # . . push args -3588 68/push _test-input-stream/imm32 -3589 # . . call -3590 e8/call skip-until-close-paren/disp32 -3591 # . . discard args -3592 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3593 # check-ints-equal(_test-input-stream->read, 7, msg) -3594 # . . push args -3595 68/push "F - test-skip-until-close-paren-works-from-mid-stream"/imm32 -3596 68/push 7/imm32 -3597 b8/copy-to-eax _test-input-stream/imm32 -3598 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) -3599 # . . call -3600 e8/call check-ints-equal/disp32 -3601 # . . discard args -3602 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -3603 # . epilog -3604 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -3605 5d/pop-to-ebp -3606 c3/return -3607 -3608 skip-until-close-paren-in-slice: # curr : (address byte), end : (address byte) -> new_curr/eax -3609 # . prolog -3610 55/push-ebp -3611 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -3612 # . save registers -3613 51/push-ecx -3614 52/push-edx -3615 # ecx = curr -3616 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx -3617 # edx = end -3618 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx -3619 # eax = 0 -3620 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax -3621 # skip initial dquote -3622 41/increment-ecx -3623 $skip-until-close-paren-in-slice:loop: -3624 # if (curr >= end) break -3625 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx -3626 73/jump-if-greater-unsigned-or-equal $skip-until-close-paren-in-slice:break/disp8 -3627 # AL = *curr -3628 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL -3629 $skip-until-close-paren-in-slice:check-close: -3630 # if (eax == ')') break -3631 3d/compare-eax-and 0x29/imm32/close-paren -3632 74/jump-if-equal $skip-until-close-paren-in-slice:break/disp8 -3633 # ++curr -3634 41/increment-ecx -3635 eb/jump $skip-until-close-paren-in-slice:loop/disp8 -3636 $skip-until-close-paren-in-slice:break: -3637 # return curr -3638 89/copy 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to eax -3639 $skip-until-close-paren-in-slice:end: -3640 # . restore registers -3641 5a/pop-to-edx -3642 59/pop-to-ecx -3643 # . epilog -3644 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -3645 5d/pop-to-ebp -3646 c3/return -3647 -3648 test-skip-until-close-paren-in-slice: -3649 # . prolog -3650 55/push-ebp -3651 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -3652 # setup: (eax..ecx) = "*(abc) def" -3653 b8/copy-to-eax "*(abc) def"/imm32 -3654 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -3655 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 -3656 05/add-to-eax 4/imm32 -3657 # eax = skip-until-close-paren-in-slice(eax, ecx) -3658 # . . push args -3659 51/push-ecx -3660 50/push-eax -3661 # . . call -3662 e8/call skip-until-close-paren-in-slice/disp32 -3663 # . . discard args -3664 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -3665 # check-ints-equal(ecx-eax, 5, msg) # eax is at the ')' -3666 # . . push args -3667 68/push "F - test-skip-until-close-paren-in-slice"/imm32 -3668 68/push 5/imm32 -3669 # . . push ecx-eax -3670 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx -3671 51/push-ecx -3672 # . . call -3673 e8/call check-ints-equal/disp32 -3674 # . . discard args -3675 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -3676 # . epilog -3677 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -3678 5d/pop-to-ebp -3679 c3/return -3680 -3681 test-skip-until-close-paren-in-slice-ignores-spaces: -3682 # . prolog -3683 55/push-ebp -3684 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -3685 # setup: (eax..ecx) = "*(a b)/yz" -3686 b8/copy-to-eax "*(a b)/yz"/imm32 -3687 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -3688 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 -3689 05/add-to-eax 4/imm32 -3690 # eax = skip-until-close-paren-in-slice(eax, ecx) +2960 e9/jump $emit-indirect-mode:end/disp32 +2961 $emit-indirect-mode:check-for-disp: +2962 # if (disp == 0) goto next check +2963 81 7/subop/compare 1/mod/*+disp8 5/rm32/ebp . . . . 0x18/disp8 0/imm32 # compare *(ebp+24) +2964 74/jump-if-equal $emit-indirect-mode:emit-indirect/disp8 +2965 $emit-indirect-mode:emit-disp: +2966 # emit(out, "2/mod/*+disp32 " base "/rm32 " disp "/disp32") +2967 # . write-buffered(out, "2/mod/*+disp32 ") +2968 # . . push args +2969 68/push "2/mod/*+disp32 "/imm32 +2970 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +2971 # . . call +2972 e8/call write-buffered/disp32 +2973 # . . discard args +2974 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2975 # . print-int32-buffered(out, base) +2976 # . . push args +2977 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) +2978 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +2979 # . . call +2980 e8/call print-int32-buffered/disp32 +2981 # . . discard args +2982 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2983 # . write-buffered(out, "/rm32 ") +2984 # . . push args +2985 68/push "/rm32 "/imm32 +2986 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +2987 # . . call +2988 e8/call write-buffered/disp32 +2989 # . . discard args +2990 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2991 # . print-int32-buffered(out, disp) +2992 # . . push args +2993 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0x18/disp8 . # push *(ebp+24) +2994 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +2995 # . . call +2996 e8/call print-int32-buffered/disp32 +2997 # . . discard args +2998 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +2999 # . write-buffered(out, "/disp32") +3000 # . . push args +3001 68/push "/disp32"/imm32 +3002 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +3003 # . . call +3004 e8/call write-buffered/disp32 +3005 # . . discard args +3006 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +3007 eb/jump $emit-indirect-mode:end/disp8 +3008 $emit-indirect-mode:emit-indirect: +3009 # emit(out, "0/mod/indirect " base "/rm32") +3010 # . write-buffered(out, "0/mod/indirect ") +3011 # . . push args +3012 68/push "0/mod/indirect "/imm32 +3013 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +3014 # . . call +3015 e8/call write-buffered/disp32 +3016 # . . discard args +3017 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +3018 # . print-int32-buffered(out, base) +3019 # . . push args +3020 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 0xc/disp8 . # push *(ebp+12) +3021 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +3022 # . . call +3023 e8/call print-int32-buffered/disp32 +3024 # . . discard args +3025 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +3026 # . write-buffered(out, "/rm32") +3027 # . . push args +3028 68/push "/rm32"/imm32 +3029 ff 6/subop/push 1/mod/*+disp8 5/rm32/ebp . . . . 8/disp8 . # push *(ebp+8) +3030 # . . call +3031 e8/call write-buffered/disp32 +3032 # . . discard args +3033 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +3034 $emit-indirect-mode:end: +3035 # . epilog +3036 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +3037 5d/pop-to-ebp +3038 c3/return +3039 +3040 test-emit-indirect-mode: +3041 # . prolog +3042 55/push-ebp +3043 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +3044 # setup +3045 # . clear-stream(_test-output-stream) +3046 # . . push args +3047 68/push _test-output-stream/imm32 +3048 # . . call +3049 e8/call clear-stream/disp32 +3050 # . . discard args +3051 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3052 # . clear-stream(_test-output-buffered-file+4) +3053 # . . push args +3054 b8/copy-to-eax _test-output-buffered-file/imm32 +3055 05/add-to-eax 4/imm32 +3056 50/push-eax +3057 # . . call +3058 e8/call clear-stream/disp32 +3059 # . . discard args +3060 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3061 # emit-indirect-mode(_test-output-buffered-file, 0, 4/none, 0, 0) +3062 # . . write args +3063 68/push 0/imm32/.disp +3064 68/push 0/imm32/.scale +3065 68/push 4/imm32/.index/none +3066 68/push 0/imm32/.base +3067 68/push _test-output-buffered-file/imm32 +3068 # . . call +3069 e8/call emit-indirect-mode/disp32 +3070 # . . discard args +3071 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp +3072 # . flush(_test-output-buffered-file) +3073 # . . push args +3074 68/push _test-output-buffered-file/imm32 +3075 # . . call +3076 e8/call flush/disp32 +3077 # . . discard args +3078 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3079 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +3105 # check-stream-equal(_test-output-stream, "0/mod/indirect 0/rm32", msg) +3106 # . . push args +3107 68/push "F - test-emit-indirect-mode"/imm32 +3108 68/push "0/mod/indirect 0x00000000/rm32"/imm32 +3109 68/push _test-output-stream/imm32 +3110 # . . call +3111 e8/call check-stream-equal/disp32 +3112 # . . discard args +3113 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +3114 # . epilog +3115 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +3116 5d/pop-to-ebp +3117 c3/return +3118 +3119 test-emit-indirect-mode-2: +3120 # . prolog +3121 55/push-ebp +3122 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +3123 # setup +3124 # . clear-stream(_test-output-stream) +3125 # . . push args +3126 68/push _test-output-stream/imm32 +3127 # . . call +3128 e8/call clear-stream/disp32 +3129 # . . discard args +3130 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3131 # . clear-stream(_test-output-buffered-file+4) +3132 # . . push args +3133 b8/copy-to-eax _test-output-buffered-file/imm32 +3134 05/add-to-eax 4/imm32 +3135 50/push-eax +3136 # . . call +3137 e8/call clear-stream/disp32 +3138 # . . discard args +3139 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3140 # emit-indirect-mode(_test-output-buffered-file, 6, 4/none, 0, 0) +3141 # . . write args +3142 68/push 0/imm32/.disp +3143 68/push 0/imm32/.scale +3144 68/push 4/imm32/.index/none +3145 68/push 7/imm32/.base +3146 68/push _test-output-buffered-file/imm32 +3147 # . . call +3148 e8/call emit-indirect-mode/disp32 +3149 # . . discard args +3150 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp +3151 # . flush(_test-output-buffered-file) +3152 # . . push args +3153 68/push _test-output-buffered-file/imm32 +3154 # . . call +3155 e8/call flush/disp32 +3156 # . . discard args +3157 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3158 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +3184 # check-stream-equal(_test-output-stream, "0/mod/indirect 7/rm32", msg) +3185 # . . push args +3186 68/push "F - test-emit-indirect-mode-2"/imm32 +3187 68/push "0/mod/indirect 0x00000007/rm32"/imm32 +3188 68/push _test-output-stream/imm32 +3189 # . . call +3190 e8/call check-stream-equal/disp32 +3191 # . . discard args +3192 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +3193 # . epilog +3194 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +3195 5d/pop-to-ebp +3196 c3/return +3197 +3198 test-emit-indirect-mode-with-disp: +3199 # . prolog +3200 55/push-ebp +3201 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +3202 # setup +3203 # . clear-stream(_test-output-stream) +3204 # . . push args +3205 68/push _test-output-stream/imm32 +3206 # . . call +3207 e8/call clear-stream/disp32 +3208 # . . discard args +3209 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3210 # . clear-stream(_test-output-buffered-file+4) +3211 # . . push args +3212 b8/copy-to-eax _test-output-buffered-file/imm32 +3213 05/add-to-eax 4/imm32 +3214 50/push-eax +3215 # . . call +3216 e8/call clear-stream/disp32 +3217 # . . discard args +3218 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3219 # emit-indirect-mode(_test-output-buffered-file, 6, 4/none, 0, 4) +3220 # . . write args +3221 68/push 4/imm32/.disp +3222 68/push 0/imm32/.scale +3223 68/push 4/imm32/.index/none +3224 68/push 6/imm32/.base +3225 68/push _test-output-buffered-file/imm32 +3226 # . . call +3227 e8/call emit-indirect-mode/disp32 +3228 # . . discard args +3229 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp +3230 # . flush(_test-output-buffered-file) +3231 # . . push args +3232 68/push _test-output-buffered-file/imm32 +3233 # . . call +3234 e8/call flush/disp32 +3235 # . . discard args +3236 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3237 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +3263 # check-stream-equal(_test-output-stream, "2/mod/*+disp32 6/rm32 4/disp32", msg) +3264 # . . push args +3265 68/push "F - test-emit-indirect-mode-with-disp"/imm32 +3266 68/push "2/mod/*+disp32 0x00000006/rm32 0x00000004/disp32"/imm32 +3267 68/push _test-output-stream/imm32 +3268 # . . call +3269 e8/call check-stream-equal/disp32 +3270 # . . discard args +3271 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +3272 # . epilog +3273 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +3274 5d/pop-to-ebp +3275 c3/return +3276 +3277 test-emit-indirect-mode-with-disp-negative: +3278 # . prolog +3279 55/push-ebp +3280 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +3281 # setup +3282 # . clear-stream(_test-output-stream) +3283 # . . push args +3284 68/push _test-output-stream/imm32 +3285 # . . call +3286 e8/call clear-stream/disp32 +3287 # . . discard args +3288 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3289 # . clear-stream(_test-output-buffered-file+4) +3290 # . . push args +3291 b8/copy-to-eax _test-output-buffered-file/imm32 +3292 05/add-to-eax 4/imm32 +3293 50/push-eax +3294 # . . call +3295 e8/call clear-stream/disp32 +3296 # . . discard args +3297 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3298 # emit-indirect-mode(_test-output-buffered-file, 6, 4/none, 0, -4) +3299 # . . write args +3300 68/push -4/imm32/.disp +3301 68/push 0/imm32/.scale +3302 68/push 4/imm32/.index/none +3303 68/push 6/imm32/.base +3304 68/push _test-output-buffered-file/imm32 +3305 # . . call +3306 e8/call emit-indirect-mode/disp32 +3307 # . . discard args +3308 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp +3309 # . flush(_test-output-buffered-file) +3310 # . . push args +3311 68/push _test-output-buffered-file/imm32 +3312 # . . call +3313 e8/call flush/disp32 +3314 # . . discard args +3315 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3316 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +3342 # check-stream-equal(_test-output-stream, "2/mod/*+disp32 6/rm32 -4/disp32", msg) +3343 # . . push args +3344 68/push "F - test-emit-indirect-mode-with-disp"/imm32 +3345 68/push "2/mod/*+disp32 0x00000006/rm32 0xfffffffc/disp32"/imm32 +3346 68/push _test-output-stream/imm32 +3347 # . . call +3348 e8/call check-stream-equal/disp32 +3349 # . . discard args +3350 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +3351 # . epilog +3352 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +3353 5d/pop-to-ebp +3354 c3/return +3355 +3356 test-emit-indirect-mode-with-sib: +3357 # . prolog +3358 55/push-ebp +3359 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +3360 # setup +3361 # . clear-stream(_test-output-stream) +3362 # . . push args +3363 68/push _test-output-stream/imm32 +3364 # . . call +3365 e8/call clear-stream/disp32 +3366 # . . discard args +3367 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3368 # . clear-stream(_test-output-buffered-file+4) +3369 # . . push args +3370 b8/copy-to-eax _test-output-buffered-file/imm32 +3371 05/add-to-eax 4/imm32 +3372 50/push-eax +3373 # . . call +3374 e8/call clear-stream/disp32 +3375 # . . discard args +3376 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3377 # emit-indirect-mode(_test-output-buffered-file, 6/base, 1/index, 2/scale, 4/disp) +3378 # . . write args +3379 68/push 4/imm32/.disp +3380 68/push 2/imm32/.scale +3381 68/push 1/imm32/.index +3382 68/push 6/imm32/.base +3383 68/push _test-output-buffered-file/imm32 +3384 # . . call +3385 e8/call emit-indirect-mode/disp32 +3386 # . . discard args +3387 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp +3388 # . flush(_test-output-buffered-file) +3389 # . . push args +3390 68/push _test-output-buffered-file/imm32 +3391 # . . call +3392 e8/call flush/disp32 +3393 # . . discard args +3394 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3395 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +3421 # check-stream-equal(_test-output-stream, "2/mod/indirect 4/rm32/sib 6/base 1/index 2/scale 4/disp", msg) +3422 # . . push args +3423 68/push "F - test-emit-indirect-mode-with-sib"/imm32 +3424 68/push "2/mod/*+disp32 4/rm32/sib 0x00000006/base 0x00000001/index 0x00000002/scale 0x00000004/disp32"/imm32 +3425 68/push _test-output-stream/imm32 +3426 # . . call +3427 e8/call check-stream-equal/disp32 +3428 # . . discard args +3429 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +3430 # . epilog +3431 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +3432 5d/pop-to-ebp +3433 c3/return +3434 +3435 test-emit-indirect-mode-ebp: +3436 # . prolog +3437 55/push-ebp +3438 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +3439 # setup +3440 # . clear-stream(_test-output-stream) +3441 # . . push args +3442 68/push _test-output-stream/imm32 +3443 # . . call +3444 e8/call clear-stream/disp32 +3445 # . . discard args +3446 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3447 # . clear-stream(_test-output-buffered-file+4) +3448 # . . push args +3449 b8/copy-to-eax _test-output-buffered-file/imm32 +3450 05/add-to-eax 4/imm32 +3451 50/push-eax +3452 # . . call +3453 e8/call clear-stream/disp32 +3454 # . . discard args +3455 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3456 # emit-indirect-mode(_test-output-buffered-file, 5/base, 0/index, 0/scale, 0/disp) +3457 # . . write args +3458 68/push 0/imm32/.disp +3459 68/push 0/imm32/.scale +3460 68/push 0/imm32/.index +3461 68/push 5/imm32/.base/ebp +3462 68/push _test-output-buffered-file/imm32 +3463 # . . call +3464 e8/call emit-indirect-mode/disp32 +3465 # . . discard args +3466 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp +3467 # . flush(_test-output-buffered-file) +3468 # . . push args +3469 68/push _test-output-buffered-file/imm32 +3470 # . . call +3471 e8/call flush/disp32 +3472 # . . discard args +3473 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3474 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +3500 # check-stream-equal(_test-output-stream, "2/mod/*+disp32 4/rm32/sib 5/base/ebp 0/index 0/scale 0/disp32", msg) +3501 # . . push args +3502 68/push "F - test-emit-indirect-mode-ebp"/imm32 +3503 68/push "2/mod/*+disp32 4/rm32/sib 0x00000005/base 0x00000000/index 0x00000000/scale 0x00000000/disp32"/imm32 +3504 68/push _test-output-stream/imm32 +3505 # . . call +3506 e8/call check-stream-equal/disp32 +3507 # . . discard args +3508 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +3509 # . epilog +3510 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +3511 5d/pop-to-ebp +3512 c3/return +3513 +3514 test-emit-indirect-mode-esp: +3515 # . prolog +3516 55/push-ebp +3517 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +3518 # setup +3519 # . clear-stream(_test-output-stream) +3520 # . . push args +3521 68/push _test-output-stream/imm32 +3522 # . . call +3523 e8/call clear-stream/disp32 +3524 # . . discard args +3525 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3526 # . clear-stream(_test-output-buffered-file+4) +3527 # . . push args +3528 b8/copy-to-eax _test-output-buffered-file/imm32 +3529 05/add-to-eax 4/imm32 +3530 50/push-eax +3531 # . . call +3532 e8/call clear-stream/disp32 +3533 # . . discard args +3534 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3535 # emit-indirect-mode(_test-output-buffered-file, 4/base, 0/index, 0/scale, 0/disp) +3536 # . . write args +3537 68/push 0/imm32/.disp +3538 68/push 0/imm32/.scale +3539 68/push 0/imm32/.index +3540 68/push 4/imm32/.base/esp +3541 68/push _test-output-buffered-file/imm32 +3542 # . . call +3543 e8/call emit-indirect-mode/disp32 +3544 # . . discard args +3545 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0x14/imm32 # add to esp +3546 # . flush(_test-output-buffered-file) +3547 # . . push args +3548 68/push _test-output-buffered-file/imm32 +3549 # . . call +3550 e8/call flush/disp32 +3551 # . . discard args +3552 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3553 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +3579 # check-stream-equal(_test-output-stream, "2/mod/*+disp32 4/rm32/sib 4/base/ebp 0/index 0/scale 0/disp32", msg) +3580 # . . push args +3581 68/push "F - test-emit-indirect-mode-esp"/imm32 +3582 68/push "2/mod/*+disp32 4/rm32/sib 0x00000004/base 0x00000000/index 0x00000000/scale 0x00000000/disp32"/imm32 +3583 68/push _test-output-stream/imm32 +3584 # . . call +3585 e8/call check-stream-equal/disp32 +3586 # . . discard args +3587 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +3588 # . epilog +3589 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +3590 5d/pop-to-ebp +3591 c3/return +3592 +3593 # update line->read to ')' +3594 # line->read ends at ')' +3595 skip-until-close-paren: # line : (address stream) +3596 # . prolog +3597 55/push-ebp +3598 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +3599 # . save registers +3600 50/push-eax +3601 51/push-ecx +3602 52/push-edx +3603 # ecx = line +3604 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx +3605 # eax = skip-until-close-paren-in-slice(&line->data[line->read], &line->data[line->write]) +3606 # . . push &line->data[line->write] +3607 8b/copy 1/mod/*+disp8 1/rm32/ecx . . 2/r32/edx 8/disp8 . # copy *(ecx+8) to edx +3608 8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx 0xc/disp8 . # copy ecx+edx+12 to edx +3609 52/push-edx +3610 # . . push &line->data[line->read] +3611 8b/copy 1/mod/*+disp8 1/rm32/ecx . . 2/r32/edx 4/disp8 . # copy *(ecx+4) to edx +3612 8d/copy-address 1/mod/*+disp8 4/rm32/sib 1/base/ecx 2/index/edx . 2/r32/edx 0xc/disp8 . # copy ecx+edx+12 to edx +3613 52/push-edx +3614 # . . call +3615 e8/call skip-until-close-paren-in-slice/disp32 +3616 # . . discard args +3617 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +3618 # line->read = eax - line->data +3619 29/subtract 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # subtract ecx from eax +3620 2d/subtract-from-eax 0xc/imm32 +3621 89/copy 1/mod/*+disp8 1/rm32/ecx . . 0/r32/eax 4/disp8 . # copy eax to *(ecx+4) +3622 $skip-until-close-paren:end: +3623 # . restore registers +3624 5a/pop-to-edx +3625 59/pop-to-ecx +3626 58/pop-to-eax +3627 # . epilog +3628 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +3629 5d/pop-to-ebp +3630 c3/return +3631 +3632 test-skip-until-close-paren: +3633 # . prolog +3634 55/push-ebp +3635 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +3636 # setup +3637 # . clear-stream(_test-input-stream) +3638 # . . push args +3639 68/push _test-input-stream/imm32 +3640 # . . call +3641 e8/call clear-stream/disp32 +3642 # . . discard args +3643 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3644 # . write(_test-input-stream, "*(abc) def") +3645 # . indices: 0123 45 +3646 # . . push args +3647 68/push "*(abc) def"/imm32 +3648 68/push _test-input-stream/imm32 +3649 # . . call +3650 e8/call write/disp32 +3651 # . . discard args +3652 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +3653 # precondition: line->read == 0 +3654 # . . push args +3655 68/push "F - test-skip-until-close-paren/precondition"/imm32 +3656 68/push 0/imm32 +3657 b8/copy-to-eax _test-input-stream/imm32 +3658 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) +3659 # . . call +3660 e8/call check-ints-equal/disp32 +3661 # . . discard args +3662 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +3663 # skip-until-close-paren(_test-input-stream) +3664 # . . push args +3665 68/push _test-input-stream/imm32 +3666 # . . call +3667 e8/call skip-until-close-paren/disp32 +3668 # . . discard args +3669 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3670 # check-ints-equal(line->read, 5, msg) +3671 # . . push args +3672 68/push "F - test-skip-until-close-paren"/imm32 +3673 68/push 5/imm32 +3674 b8/copy-to-eax _test-input-stream/imm32 +3675 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) +3676 # . . call +3677 e8/call check-ints-equal/disp32 +3678 # . . discard args +3679 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +3680 # . epilog +3681 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +3682 5d/pop-to-ebp +3683 c3/return +3684 +3685 test-skip-until-close-paren-ignores-spaces: +3686 # . prolog +3687 55/push-ebp +3688 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +3689 # setup +3690 # . clear-stream(_test-input-stream) 3691 # . . push args -3692 51/push-ecx -3693 50/push-eax -3694 # . . call -3695 e8/call skip-until-close-paren-in-slice/disp32 -3696 # . . discard args -3697 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -3698 # check-ints-equal(ecx-eax, 4, msg) # eax is at the ')' -3699 # . . push args -3700 68/push "F - test-skip-until-close-paren-in-slice-ignores-spaces"/imm32 -3701 68/push 4/imm32 -3702 # . . push ecx-eax -3703 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx -3704 51/push-ecx -3705 # . . call -3706 e8/call check-ints-equal/disp32 -3707 # . . discard args -3708 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -3709 # . epilog -3710 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -3711 5d/pop-to-ebp -3712 c3/return -3713 -3714 test-skip-until-close-paren-in-slice-stops-at-end: -3715 # . prolog -3716 55/push-ebp -3717 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -3718 # setup: (eax..ecx) = "*(abc" # unbalanced dquote -3719 b8/copy-to-eax "*(abc"/imm32 -3720 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -3721 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 -3722 05/add-to-eax 4/imm32 -3723 # eax = skip-until-close-paren-in-slice(eax, ecx) -3724 # . . push args -3725 51/push-ecx -3726 50/push-eax -3727 # . . call -3728 e8/call skip-until-close-paren-in-slice/disp32 -3729 # . . discard args -3730 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -3731 # check-ints-equal(ecx-eax, 0, msg) # skipped to end of slice -3732 # . . push args -3733 68/push "F - test-skip-until-close-paren-in-slice-stops-at-end"/imm32 -3734 68/push 0/imm32 -3735 # . . push ecx-eax -3736 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx -3737 51/push-ecx -3738 # . . call -3739 e8/call check-ints-equal/disp32 -3740 # . . discard args -3741 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -3742 # . epilog -3743 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -3744 5d/pop-to-ebp -3745 c3/return -3746 -3747 # assumes 'in' starts with optional '+' or '-', optional whitespace, and an unsigned integer -3748 # returns the value of the integer -3749 # side-effect: modifies 'in' to skip past the integer -3750 next-hex-int: # in : (address slice) -> result/eax -3751 # . prolog -3752 55/push-ebp -3753 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -3754 # . save registers -3755 51/push-ecx -3756 52/push-edx -3757 53/push-ebx -3758 56/push-esi -3759 57/push-edi -3760 # result/edi = 0 -3761 31/xor 3/mod/direct 7/rm32/edi . . . 7/r32/edi . . # clear edi -3762 # esi = in -3763 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi -3764 # edx = in->end -3765 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 2/r32/edx 4/disp8 . # copy *(esi+4) to edx -3766 # curr/ecx = in->start -3767 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx -3768 # negate?/ebx = false -3769 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx -3770 # eax = *curr -3771 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax -3772 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL -3773 $next-hex-int:positive: -3774 # if (*curr == '+') ++curr -3775 3d/compare-eax-and 0x2b/imm32/+ -3776 75/jump-if-not-equal $next-hex-int:negative/disp8 -3777 # . ++curr -3778 41/increment-ecx -3779 eb/jump $next-hex-int:skip-whitespace/disp8 -3780 $next-hex-int:negative: -3781 # else if (*curr == '-') ++curr, negate = true -3782 3d/compare-eax-and 0x2d/imm32/- -3783 75/jump-if-not-equal $next-hex-int:skip-whitespace/disp8 -3784 $next-hex-int:need-to-negate: -3785 # . ++curr -3786 41/increment-ecx -3787 # . negate = true -3788 bb/copy-to-ebx 1/imm32/true -3789 # fall through -3790 $next-hex-int:skip-whitespace: -3791 # spill eax -3792 50/push-eax -3793 # eax = skip-chars-matching-whitespace-in-slice(word->start, word->end) -3794 # . . push args -3795 52/push-edx -3796 51/push-ecx -3797 # . . call -3798 e8/call skip-chars-matching-whitespace-in-slice/disp32 -3799 # . . discard args -3800 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -3801 # ecx = eax -3802 89/copy 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # copy eax to ecx -3803 # restore eax -3804 58/pop-to-eax -3805 $next-hex-int:initial-0: -3806 # skip past leading '0x' -3807 # . if (*curr != '0') jump to loop -3808 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL -3809 3d/compare-eax-and 0x30/imm32/0 -3810 75/jump-if-not-equal $next-hex-int:loop/disp8 -3811 # . ++curr -3812 41/increment-ecx -3813 $next-hex-int:initial-0x: -3814 # . if (curr >= in->end) return result -3815 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx -3816 73/jump-if-greater-or-equal-unsigned $next-hex-int:end/disp8 -3817 # . if (*curr != 'x') jump to loop # the previous '0' is still valid so doesn't need to be checked again -3818 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax -3819 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL -3820 3d/compare-eax-and 0x78/imm32/x -3821 75/jump-if-not-equal $next-hex-int:loop/disp8 -3822 # . ++curr -3823 41/increment-ecx -3824 $next-hex-int:loop: -3825 # if (curr >= in->end) break -3826 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx -3827 73/jump-if-greater-or-equal-unsigned $next-hex-int:break/disp8 -3828 # if (!is-hex-digit?(*curr)) break -3829 # . eax = *curr -3830 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL -3831 # . eax = is-hex-digit?(*curr) -3832 # . . push args +3692 68/push _test-input-stream/imm32 +3693 # . . call +3694 e8/call clear-stream/disp32 +3695 # . . discard args +3696 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3697 # . write(_test-input-stream, "*(a b)/yz") +3698 # . . push args +3699 68/push "*(a b)/yz"/imm32 +3700 68/push _test-input-stream/imm32 +3701 # . . call +3702 e8/call write/disp32 +3703 # . . discard args +3704 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +3705 # precondition: line->read == 0 +3706 # . . push args +3707 68/push "F - test-skip-until-close-paren-ignores-spaces/precondition"/imm32 +3708 68/push 0/imm32 +3709 b8/copy-to-eax _test-input-stream/imm32 +3710 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) +3711 # . . call +3712 e8/call check-ints-equal/disp32 +3713 # . . discard args +3714 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +3715 # skip-until-close-paren(_test-input-stream) +3716 # . . push args +3717 68/push _test-input-stream/imm32 +3718 # . . call +3719 e8/call skip-until-close-paren/disp32 +3720 # . . discard args +3721 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3722 # check-ints-equal(line->read, 5, msg) +3723 # . . push args +3724 68/push "F - test-skip-until-close-paren-ignores-spaces"/imm32 +3725 68/push 5/imm32 +3726 b8/copy-to-eax _test-input-stream/imm32 +3727 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) +3728 # . . call +3729 e8/call check-ints-equal/disp32 +3730 # . . discard args +3731 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +3732 # . epilog +3733 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +3734 5d/pop-to-ebp +3735 c3/return +3736 +3737 test-skip-until-close-paren-works-from-mid-stream: +3738 # . prolog +3739 55/push-ebp +3740 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +3741 # setup +3742 # . clear-stream(_test-input-stream) +3743 # . . push args +3744 68/push _test-input-stream/imm32 +3745 # . . call +3746 e8/call clear-stream/disp32 +3747 # . . discard args +3748 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3749 # . write(_test-input-stream, "0 *(a b)/yz") +3750 # . . push args +3751 68/push "0 *(a b)/yz"/imm32 +3752 68/push _test-input-stream/imm32 +3753 # . . call +3754 e8/call write/disp32 +3755 # . . discard args +3756 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +3757 # precondition: _test-input-stream->read == 2 +3758 c7 0/subop/copy 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 2/imm32 # copy to *(eax+4) +3759 # skip-until-close-paren(_test-input-stream) +3760 # . . push args +3761 68/push _test-input-stream/imm32 +3762 # . . call +3763 e8/call skip-until-close-paren/disp32 +3764 # . . discard args +3765 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +3766 # check-ints-equal(_test-input-stream->read, 7, msg) +3767 # . . push args +3768 68/push "F - test-skip-until-close-paren-works-from-mid-stream"/imm32 +3769 68/push 7/imm32 +3770 b8/copy-to-eax _test-input-stream/imm32 +3771 ff 6/subop/push 1/mod/*+disp8 0/rm32/eax . . . . 4/disp8 . # push *(eax+4) +3772 # . . call +3773 e8/call check-ints-equal/disp32 +3774 # . . discard args +3775 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +3776 # . epilog +3777 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +3778 5d/pop-to-ebp +3779 c3/return +3780 +3781 skip-until-close-paren-in-slice: # curr : (address byte), end : (address byte) -> new_curr/eax +3782 # . prolog +3783 55/push-ebp +3784 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +3785 # . save registers +3786 51/push-ecx +3787 52/push-edx +3788 # ecx = curr +3789 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 1/r32/ecx 8/disp8 . # copy *(ebp+8) to ecx +3790 # edx = end +3791 8b/copy 1/mod/*+disp8 5/rm32/ebp . . 2/r32/edx 0xc/disp8 . # copy *(ebp+12) to edx +3792 # eax = 0 +3793 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax +3794 # skip initial dquote +3795 41/increment-ecx +3796 $skip-until-close-paren-in-slice:loop: +3797 # if (curr >= end) break +3798 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx +3799 73/jump-if-greater-unsigned-or-equal $skip-until-close-paren-in-slice:break/disp8 +3800 # AL = *curr +3801 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL +3802 $skip-until-close-paren-in-slice:check-close: +3803 # if (eax == ')') break +3804 3d/compare-eax-and 0x29/imm32/close-paren +3805 74/jump-if-equal $skip-until-close-paren-in-slice:break/disp8 +3806 # ++curr +3807 41/increment-ecx +3808 eb/jump $skip-until-close-paren-in-slice:loop/disp8 +3809 $skip-until-close-paren-in-slice:break: +3810 # return curr +3811 89/copy 3/mod/direct 0/rm32/eax . . . 1/r32/ecx . . # copy ecx to eax +3812 $skip-until-close-paren-in-slice:end: +3813 # . restore registers +3814 5a/pop-to-edx +3815 59/pop-to-ecx +3816 # . epilog +3817 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +3818 5d/pop-to-ebp +3819 c3/return +3820 +3821 test-skip-until-close-paren-in-slice: +3822 # . prolog +3823 55/push-ebp +3824 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +3825 # setup: (eax..ecx) = "*(abc) def" +3826 b8/copy-to-eax "*(abc) def"/imm32 +3827 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +3828 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 +3829 05/add-to-eax 4/imm32 +3830 # eax = skip-until-close-paren-in-slice(eax, ecx) +3831 # . . push args +3832 51/push-ecx 3833 50/push-eax 3834 # . . call -3835 e8/call is-hex-digit?/disp32 +3835 e8/call skip-until-close-paren-in-slice/disp32 3836 # . . discard args -3837 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3838 # . if (eax == 0) break -3839 3d/compare-eax-and 0/imm32 -3840 74/jump-if-equal $next-hex-int:break/disp8 -3841 # eax = from-hex-char(*curr) -3842 # . . copy arg to eax -3843 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL -3844 # . . call -3845 e8/call from-hex-char/disp32 -3846 # result = result * 16 + eax -3847 c1/shift 4/subop/left 3/mod/direct 7/rm32/edi . . . . . 4/imm8 # shift edi left by 4 bits -3848 01/add 3/mod/direct 7/rm32/edi . . . 0/r32/eax . . # add eax to edi -3849 # ++curr -3850 41/increment-ecx -3851 # loop -3852 eb/jump $next-hex-int:loop/disp8 -3853 $next-hex-int:break: -3854 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0/imm32 # compare ebx -3855 74/jump-if-equal $next-hex-int:end/disp8 -3856 $next-hex-int:negate: -3857 f7 3/subop/negate 3/mod/direct 7/rm32/edi . . . . . . # negate edi -3858 $next-hex-int:end: -3859 # word->start = curr -3860 89/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy ecx to *esi -3861 # return edi -3862 89/copy 3/mod/direct 0/rm32/eax . . . 7/r32/edi . . # copy edi to eax -3863 # . restore registers -3864 5f/pop-to-edi -3865 5e/pop-to-esi -3866 5b/pop-to-ebx -3867 5a/pop-to-edx -3868 59/pop-to-ecx -3869 # . epilog -3870 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -3871 5d/pop-to-ebp -3872 c3/return -3873 -3874 $next-hex-int:abort: -3875 # . _write(2/stderr, error) -3876 # . . push args -3877 68/push "next-hex-int: invalid hex char: "/imm32 -3878 68/push 2/imm32/stderr -3879 # . . call -3880 e8/call _write/disp32 -3881 # . . discard args -3882 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -3883 # . clear-stream(Stderr+4) -3884 # . . save eax -3885 50/push-eax -3886 # . . push args -3887 b8/copy-to-eax Stderr/imm32 -3888 05/add-to-eax 4/imm32 -3889 50/push-eax -3890 # . . call -3891 e8/call clear-stream/disp32 -3892 # . . discard args -3893 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3894 # . . restore eax -3895 58/pop-to-eax -3896 # . print-int32-buffered(Stderr, eax) +3837 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +3838 # check-ints-equal(ecx-eax, 5, msg) # eax is at the ')' +3839 # . . push args +3840 68/push "F - test-skip-until-close-paren-in-slice"/imm32 +3841 68/push 5/imm32 +3842 # . . push ecx-eax +3843 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx +3844 51/push-ecx +3845 # . . call +3846 e8/call check-ints-equal/disp32 +3847 # . . discard args +3848 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +3849 # . epilog +3850 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +3851 5d/pop-to-ebp +3852 c3/return +3853 +3854 test-skip-until-close-paren-in-slice-ignores-spaces: +3855 # . prolog +3856 55/push-ebp +3857 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +3858 # setup: (eax..ecx) = "*(a b)/yz" +3859 b8/copy-to-eax "*(a b)/yz"/imm32 +3860 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +3861 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 +3862 05/add-to-eax 4/imm32 +3863 # eax = skip-until-close-paren-in-slice(eax, ecx) +3864 # . . push args +3865 51/push-ecx +3866 50/push-eax +3867 # . . call +3868 e8/call skip-until-close-paren-in-slice/disp32 +3869 # . . discard args +3870 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +3871 # check-ints-equal(ecx-eax, 4, msg) # eax is at the ')' +3872 # . . push args +3873 68/push "F - test-skip-until-close-paren-in-slice-ignores-spaces"/imm32 +3874 68/push 4/imm32 +3875 # . . push ecx-eax +3876 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx +3877 51/push-ecx +3878 # . . call +3879 e8/call check-ints-equal/disp32 +3880 # . . discard args +3881 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +3882 # . epilog +3883 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +3884 5d/pop-to-ebp +3885 c3/return +3886 +3887 test-skip-until-close-paren-in-slice-stops-at-end: +3888 # . prolog +3889 55/push-ebp +3890 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +3891 # setup: (eax..ecx) = "*(abc" # unbalanced dquote +3892 b8/copy-to-eax "*(abc"/imm32 +3893 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +3894 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 +3895 05/add-to-eax 4/imm32 +3896 # eax = skip-until-close-paren-in-slice(eax, ecx) 3897 # . . push args -3898 50/push-eax -3899 68/push Stderr/imm32 +3898 51/push-ecx +3899 50/push-eax 3900 # . . call -3901 e8/call print-int32-buffered/disp32 +3901 e8/call skip-until-close-paren-in-slice/disp32 3902 # . . discard args 3903 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -3904 # . flush(Stderr) +3904 # check-ints-equal(ecx-eax, 0, msg) # skipped to end of slice 3905 # . . push args -3906 68/push Stderr/imm32 -3907 # . . call -3908 e8/call flush/disp32 -3909 # . . discard args -3910 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3911 # . _write(2/stderr, "\n") -3912 # . . push args -3913 68/push "\n"/imm32 -3914 68/push 2/imm32/stderr -3915 # . . call -3916 e8/call _write/disp32 -3917 # . . discard args -3918 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp -3919 # . syscall(exit, 1) -3920 bb/copy-to-ebx 1/imm32 -3921 b8/copy-to-eax 1/imm32/exit -3922 cd/syscall 0x80/imm8 -3923 # never gets here -3924 -3925 test-next-hex-int-single-digit: -3926 # . prolog -3927 55/push-ebp -3928 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -3929 # (eax..ecx) = "+a)" -3930 b8/copy-to-eax "+a)"/imm32 -3931 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -3932 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 -3933 05/add-to-eax 4/imm32 -3934 # var slice/ecx = {eax, ecx} -3935 51/push-ecx -3936 50/push-eax -3937 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -3938 # eax = next-hex-int(slice) -3939 # . . push args -3940 51/push-ecx -3941 # . . call -3942 e8/call next-hex-int/disp32 -3943 # . . discard args -3944 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3945 # check-ints-equal(eax, 0xa, msg) -3946 # . . push args -3947 68/push "F - test-next-hex-int-single-digit"/imm32 -3948 68/push 0xa/imm32 -3949 50/push-eax -3950 # . . call -3951 e8/call check-ints-equal/disp32 -3952 # . . discard args -3953 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -3954 # . epilog -3955 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -3956 5d/pop-to-ebp -3957 c3/return -3958 -3959 test-next-hex-int-multi-digit: -3960 # . prolog -3961 55/push-ebp -3962 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -3963 # (eax..ecx) = "+ 34a)" -3964 b8/copy-to-eax "+ 34a)"/imm32 -3965 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -3966 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 -3967 05/add-to-eax 4/imm32 -3968 # var slice/ecx = {eax, ecx} +3906 68/push "F - test-skip-until-close-paren-in-slice-stops-at-end"/imm32 +3907 68/push 0/imm32 +3908 # . . push ecx-eax +3909 29/subtract 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # subtract eax from ecx +3910 51/push-ecx +3911 # . . call +3912 e8/call check-ints-equal/disp32 +3913 # . . discard args +3914 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +3915 # . epilog +3916 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +3917 5d/pop-to-ebp +3918 c3/return +3919 +3920 # assumes 'in' starts with optional '+' or '-', optional whitespace, and an unsigned integer +3921 # returns the value of the integer +3922 # side-effect: modifies 'in' to skip past the integer +3923 next-hex-int: # in : (address slice) -> result/eax +3924 # . prolog +3925 55/push-ebp +3926 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +3927 # . save registers +3928 51/push-ecx +3929 52/push-edx +3930 53/push-ebx +3931 56/push-esi +3932 57/push-edi +3933 # result/edi = 0 +3934 31/xor 3/mod/direct 7/rm32/edi . . . 7/r32/edi . . # clear edi +3935 # esi = in +3936 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi +3937 # edx = in->end +3938 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 2/r32/edx 4/disp8 . # copy *(esi+4) to edx +3939 # curr/ecx = in->start +3940 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx +3941 # negate?/ebx = false +3942 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx +3943 # eax = *curr +3944 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax +3945 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL +3946 $next-hex-int:positive: +3947 # if (*curr == '+') ++curr +3948 3d/compare-eax-and 0x2b/imm32/+ +3949 75/jump-if-not-equal $next-hex-int:negative/disp8 +3950 # . ++curr +3951 41/increment-ecx +3952 eb/jump $next-hex-int:skip-whitespace/disp8 +3953 $next-hex-int:negative: +3954 # else if (*curr == '-') ++curr, negate = true +3955 3d/compare-eax-and 0x2d/imm32/- +3956 75/jump-if-not-equal $next-hex-int:skip-whitespace/disp8 +3957 $next-hex-int:need-to-negate: +3958 # . ++curr +3959 41/increment-ecx +3960 # . negate = true +3961 bb/copy-to-ebx 1/imm32/true +3962 # fall through +3963 $next-hex-int:skip-whitespace: +3964 # spill eax +3965 50/push-eax +3966 # eax = skip-chars-matching-whitespace-in-slice(word->start, word->end) +3967 # . . push args +3968 52/push-edx 3969 51/push-ecx -3970 50/push-eax -3971 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -3972 # eax = next-hex-int(slice) -3973 # . . push args -3974 51/push-ecx -3975 # . . call -3976 e8/call next-hex-int/disp32 -3977 # . . discard args -3978 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -3979 # check-ints-equal(eax, 0x34a, msg) -3980 # . . push args -3981 68/push "F - test-next-hex-int-multi-digit"/imm32 -3982 68/push 0x34a/imm32 -3983 50/push-eax -3984 # . . call -3985 e8/call check-ints-equal/disp32 -3986 # . . discard args -3987 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -3988 # . epilog -3989 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -3990 5d/pop-to-ebp -3991 c3/return -3992 -3993 test-next-hex-int-0x-prefix: -3994 # . prolog -3995 55/push-ebp -3996 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -3997 # (eax..ecx) = "+0x34)" -3998 b8/copy-to-eax "+0x34)"/imm32 -3999 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -4000 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 -4001 05/add-to-eax 4/imm32 -4002 # var slice/ecx = {eax, ecx} -4003 51/push-ecx -4004 50/push-eax -4005 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -4006 # eax = next-hex-int(slice) -4007 # . . push args -4008 51/push-ecx -4009 # . . call -4010 e8/call next-hex-int/disp32 -4011 # . . discard args -4012 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -4013 # check-ints-equal(eax, 0x34, msg) -4014 # . . push args -4015 68/push "F - test-next-hex-int-0x-prefix"/imm32 -4016 68/push 0x34/imm32 -4017 50/push-eax -4018 # . . call -4019 e8/call check-ints-equal/disp32 -4020 # . . discard args -4021 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -4022 # . epilog -4023 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -4024 5d/pop-to-ebp -4025 c3/return -4026 -4027 test-next-hex-int-zero: -4028 # . prolog -4029 55/push-ebp -4030 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -4031 # (eax..ecx) = "+0)" -4032 b8/copy-to-eax "+0)"/imm32 -4033 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -4034 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 -4035 05/add-to-eax 4/imm32 -4036 # var slice/ecx = {eax, ecx} -4037 51/push-ecx -4038 50/push-eax -4039 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -4040 # eax = next-hex-int(slice) -4041 # . . push args -4042 51/push-ecx -4043 # . . call -4044 e8/call next-hex-int/disp32 -4045 # . . discard args -4046 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -4047 # check-ints-equal(eax, 0, msg) -4048 # . . push args -4049 68/push "F - test-next-hex-int-zero"/imm32 -4050 68/push 0/imm32 -4051 50/push-eax +3970 # . . call +3971 e8/call skip-chars-matching-whitespace-in-slice/disp32 +3972 # . . discard args +3973 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +3974 # ecx = eax +3975 89/copy 3/mod/direct 1/rm32/ecx . . . 0/r32/eax . . # copy eax to ecx +3976 # restore eax +3977 58/pop-to-eax +3978 $next-hex-int:initial-0: +3979 # skip past leading '0x' +3980 # . if (*curr != '0') jump to loop +3981 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL +3982 3d/compare-eax-and 0x30/imm32/0 +3983 75/jump-if-not-equal $next-hex-int:loop/disp8 +3984 # . ++curr +3985 41/increment-ecx +3986 $next-hex-int:initial-0x: +3987 # . if (curr >= in->end) return result +3988 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx +3989 73/jump-if-greater-or-equal-unsigned $next-hex-int:end/disp8 +3990 # . if (*curr != 'x') jump to loop # the previous '0' is still valid so doesn't need to be checked again +3991 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax +3992 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL +3993 3d/compare-eax-and 0x78/imm32/x +3994 75/jump-if-not-equal $next-hex-int:loop/disp8 +3995 # . ++curr +3996 41/increment-ecx +3997 $next-hex-int:loop: +3998 # if (curr >= in->end) break +3999 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx +4000 73/jump-if-greater-or-equal-unsigned $next-hex-int:break/disp8 +4001 # if (!is-hex-digit?(*curr)) break +4002 # . eax = *curr +4003 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL +4004 # . eax = is-hex-digit?(*curr) +4005 # . . push args +4006 50/push-eax +4007 # . . call +4008 e8/call is-hex-digit?/disp32 +4009 # . . discard args +4010 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +4011 # . if (eax == 0) break +4012 3d/compare-eax-and 0/imm32 +4013 74/jump-if-equal $next-hex-int:break/disp8 +4014 # eax = from-hex-char(*curr) +4015 # . . copy arg to eax +4016 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL +4017 # . . call +4018 e8/call from-hex-char/disp32 +4019 # result = result * 16 + eax +4020 c1/shift 4/subop/left 3/mod/direct 7/rm32/edi . . . . . 4/imm8 # shift edi left by 4 bits +4021 01/add 3/mod/direct 7/rm32/edi . . . 0/r32/eax . . # add eax to edi +4022 # ++curr +4023 41/increment-ecx +4024 # loop +4025 eb/jump $next-hex-int:loop/disp8 +4026 $next-hex-int:break: +4027 81 7/subop/compare 3/mod/direct 3/rm32/ebx . . . . . 0/imm32 # compare ebx +4028 74/jump-if-equal $next-hex-int:end/disp8 +4029 $next-hex-int:negate: +4030 f7 3/subop/negate 3/mod/direct 7/rm32/edi . . . . . . # negate edi +4031 $next-hex-int:end: +4032 # word->start = curr +4033 89/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy ecx to *esi +4034 # return edi +4035 89/copy 3/mod/direct 0/rm32/eax . . . 7/r32/edi . . # copy edi to eax +4036 # . restore registers +4037 5f/pop-to-edi +4038 5e/pop-to-esi +4039 5b/pop-to-ebx +4040 5a/pop-to-edx +4041 59/pop-to-ecx +4042 # . epilog +4043 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +4044 5d/pop-to-ebp +4045 c3/return +4046 +4047 $next-hex-int:abort: +4048 # . _write(2/stderr, error) +4049 # . . push args +4050 68/push "next-hex-int: invalid hex char: "/imm32 +4051 68/push 2/imm32/stderr 4052 # . . call -4053 e8/call check-ints-equal/disp32 +4053 e8/call _write/disp32 4054 # . . discard args -4055 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -4056 # . epilog -4057 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -4058 5d/pop-to-ebp -4059 c3/return -4060 -4061 test-next-hex-int-0-prefix: -4062 # . prolog -4063 55/push-ebp -4064 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -4065 # (eax..ecx) = "+ 03)" -4066 b8/copy-to-eax "+ 03)"/imm32 -4067 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -4068 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 -4069 05/add-to-eax 4/imm32 -4070 # var slice/ecx = {eax, ecx} -4071 51/push-ecx -4072 50/push-eax -4073 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -4074 # eax = next-hex-int(slice) -4075 # . . push args -4076 51/push-ecx -4077 # . . call -4078 e8/call next-hex-int/disp32 -4079 # . . discard args -4080 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -4081 # check-ints-equal(eax, 3, msg) -4082 # . . push args -4083 68/push "F - test-next-hex-int-0-prefix"/imm32 -4084 68/push 3/imm32 -4085 50/push-eax -4086 # . . call -4087 e8/call check-ints-equal/disp32 -4088 # . . discard args -4089 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -4090 # . epilog -4091 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -4092 5d/pop-to-ebp -4093 c3/return -4094 -4095 test-next-hex-int-negative: -4096 # . prolog -4097 55/push-ebp -4098 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -4099 # (eax..ecx) = "-03)" -4100 b8/copy-to-eax "-03)"/imm32 -4101 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -4102 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 -4103 05/add-to-eax 4/imm32 -4104 # var slice/ecx = {eax, ecx} -4105 51/push-ecx -4106 50/push-eax -4107 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -4108 # eax = next-hex-int(slice) -4109 # . . push args -4110 51/push-ecx -4111 # . . call -4112 e8/call next-hex-int/disp32 -4113 # . . discard args -4114 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -4115 # check-ints-equal(eax, -3, msg) -4116 # . . push args -4117 68/push "F - test-next-hex-int-negative"/imm32 -4118 68/push -3/imm32 -4119 50/push-eax -4120 # . . call -4121 e8/call check-ints-equal/disp32 -4122 # . . discard args -4123 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -4124 # . epilog -4125 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -4126 5d/pop-to-ebp -4127 c3/return -4128 -4129 test-next-hex-int-negative-with-space: -4130 # . prolog -4131 55/push-ebp -4132 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -4133 # (eax..ecx) = "- 03)" -4134 b8/copy-to-eax "- 03)"/imm32 -4135 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -4136 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 -4137 05/add-to-eax 4/imm32 -4138 # var slice/ecx = {eax, ecx} -4139 51/push-ecx -4140 50/push-eax -4141 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -4142 # eax = next-hex-int(slice) -4143 # . . push args -4144 51/push-ecx -4145 # . . call -4146 e8/call next-hex-int/disp32 -4147 # . . discard args -4148 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -4149 # check-ints-equal(eax, -3, msg) -4150 # . . push args -4151 68/push "F - test-next-hex-int-negative-with-space"/imm32 -4152 68/push -3/imm32 -4153 50/push-eax -4154 # . . call -4155 e8/call check-ints-equal/disp32 -4156 # . . discard args -4157 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -4158 # . epilog -4159 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -4160 5d/pop-to-ebp -4161 c3/return -4162 -4163 # assumes 'in' starts a positive unsigned integer -4164 # returns the value of the integer -4165 # side-effect: modifies 'in' to skip past the integer -4166 next-positive-hex-int: # in : (address slice) -> result/eax +4055 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +4056 # . clear-stream(Stderr+4) +4057 # . . save eax +4058 50/push-eax +4059 # . . push args +4060 b8/copy-to-eax Stderr/imm32 +4061 05/add-to-eax 4/imm32 +4062 50/push-eax +4063 # . . call +4064 e8/call clear-stream/disp32 +4065 # . . discard args +4066 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +4067 # . . restore eax +4068 58/pop-to-eax +4069 # . print-int32-buffered(Stderr, eax) +4070 # . . push args +4071 50/push-eax +4072 68/push Stderr/imm32 +4073 # . . call +4074 e8/call print-int32-buffered/disp32 +4075 # . . discard args +4076 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +4077 # . flush(Stderr) +4078 # . . push args +4079 68/push Stderr/imm32 +4080 # . . call +4081 e8/call flush/disp32 +4082 # . . discard args +4083 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +4084 # . _write(2/stderr, "\n") +4085 # . . push args +4086 68/push "\n"/imm32 +4087 68/push 2/imm32/stderr +4088 # . . call +4089 e8/call _write/disp32 +4090 # . . discard args +4091 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 8/imm32 # add to esp +4092 # . syscall(exit, 1) +4093 bb/copy-to-ebx 1/imm32 +4094 b8/copy-to-eax 1/imm32/exit +4095 cd/syscall 0x80/imm8 +4096 # never gets here +4097 +4098 test-next-hex-int-single-digit: +4099 # . prolog +4100 55/push-ebp +4101 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +4102 # (eax..ecx) = "+a)" +4103 b8/copy-to-eax "+a)"/imm32 +4104 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +4105 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 +4106 05/add-to-eax 4/imm32 +4107 # var slice/ecx = {eax, ecx} +4108 51/push-ecx +4109 50/push-eax +4110 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +4111 # eax = next-hex-int(slice) +4112 # . . push args +4113 51/push-ecx +4114 # . . call +4115 e8/call next-hex-int/disp32 +4116 # . . discard args +4117 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +4118 # check-ints-equal(eax, 0xa, msg) +4119 # . . push args +4120 68/push "F - test-next-hex-int-single-digit"/imm32 +4121 68/push 0xa/imm32 +4122 50/push-eax +4123 # . . call +4124 e8/call check-ints-equal/disp32 +4125 # . . discard args +4126 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +4127 # . epilog +4128 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +4129 5d/pop-to-ebp +4130 c3/return +4131 +4132 test-next-hex-int-multi-digit: +4133 # . prolog +4134 55/push-ebp +4135 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +4136 # (eax..ecx) = "+ 34a)" +4137 b8/copy-to-eax "+ 34a)"/imm32 +4138 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +4139 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 +4140 05/add-to-eax 4/imm32 +4141 # var slice/ecx = {eax, ecx} +4142 51/push-ecx +4143 50/push-eax +4144 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +4145 # eax = next-hex-int(slice) +4146 # . . push args +4147 51/push-ecx +4148 # . . call +4149 e8/call next-hex-int/disp32 +4150 # . . discard args +4151 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +4152 # check-ints-equal(eax, 0x34a, msg) +4153 # . . push args +4154 68/push "F - test-next-hex-int-multi-digit"/imm32 +4155 68/push 0x34a/imm32 +4156 50/push-eax +4157 # . . call +4158 e8/call check-ints-equal/disp32 +4159 # . . discard args +4160 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +4161 # . epilog +4162 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +4163 5d/pop-to-ebp +4164 c3/return +4165 +4166 test-next-hex-int-0x-prefix: 4167 # . prolog 4168 55/push-ebp 4169 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -4170 # . save registers -4171 51/push-ecx -4172 52/push-edx -4173 53/push-ebx -4174 56/push-esi -4175 57/push-edi -4176 # result/edi = 0 -4177 31/xor 3/mod/direct 7/rm32/edi . . . 7/r32/edi . . # clear edi -4178 # esi = in -4179 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi -4180 # edx = in->end -4181 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 2/r32/edx 4/disp8 . # copy *(esi+4) to edx -4182 # curr/ecx = in->start -4183 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx -4184 # negate?/ebx = false -4185 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx -4186 # eax = *curr -4187 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax -4188 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL -4189 $next-positive-hex-int:initial-0: -4190 # skip past leading '0x' -4191 # . if (*curr != '0') jump to loop -4192 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL -4193 3d/compare-eax-and 0x30/imm32/0 -4194 75/jump-if-not-equal $next-positive-hex-int:loop/disp8 -4195 # . ++curr -4196 41/increment-ecx -4197 $next-positive-hex-int:initial-0x: -4198 # . if (curr >= in->end) return result -4199 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx -4200 73/jump-if-greater-or-equal-unsigned $next-positive-hex-int:end/disp8 -4201 # . if (*curr != 'x') jump to loop # the previous '0' is still valid so doesn't need to be checked again -4202 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax -4203 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL -4204 3d/compare-eax-and 0x78/imm32/x -4205 75/jump-if-not-equal $next-positive-hex-int:loop/disp8 -4206 # . ++curr -4207 41/increment-ecx -4208 $next-positive-hex-int:loop: -4209 # if (curr >= in->end) break -4210 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx -4211 73/jump-if-greater-or-equal-unsigned $next-positive-hex-int:end/disp8 -4212 # if (!is-hex-digit?(*curr)) break -4213 # . eax = *curr -4214 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL -4215 # . eax = is-hex-digit?(*curr) -4216 # . . push args -4217 50/push-eax -4218 # . . call -4219 e8/call is-hex-digit?/disp32 -4220 # . . discard args -4221 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -4222 # . if (eax == 0) break -4223 3d/compare-eax-and 0/imm32 -4224 74/jump-if-equal $next-positive-hex-int:end/disp8 -4225 # eax = from-hex-char(*curr) -4226 # . . copy arg to eax -4227 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL -4228 # . . call -4229 e8/call from-hex-char/disp32 -4230 # result = result * 16 + eax -4231 c1/shift 4/subop/left 3/mod/direct 7/rm32/edi . . . . . 4/imm8 # shift edi left by 4 bits -4232 01/add 3/mod/direct 7/rm32/edi . . . 0/r32/eax . . # add eax to edi -4233 # ++curr -4234 41/increment-ecx -4235 # loop -4236 eb/jump $next-positive-hex-int:loop/disp8 -4237 $next-positive-hex-int:end: -4238 # word->start = curr -4239 89/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy ecx to *esi -4240 # return edi -4241 89/copy 3/mod/direct 0/rm32/eax . . . 7/r32/edi . . # copy edi to eax -4242 # . restore registers -4243 5f/pop-to-edi -4244 5e/pop-to-esi -4245 5b/pop-to-ebx -4246 5a/pop-to-edx -4247 59/pop-to-ecx -4248 # . epilog -4249 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -4250 5d/pop-to-ebp -4251 c3/return -4252 -4253 test-next-positive-hex-int-single-digit: -4254 # . prolog -4255 55/push-ebp -4256 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -4257 # (eax..ecx) = "a)" -4258 b8/copy-to-eax "a)"/imm32 -4259 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -4260 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 -4261 05/add-to-eax 4/imm32 -4262 # var slice/ecx = {eax, ecx} -4263 51/push-ecx -4264 50/push-eax -4265 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -4266 # eax = next-positive-hex-int(slice) -4267 # . . push args -4268 51/push-ecx -4269 # . . call -4270 e8/call next-positive-hex-int/disp32 -4271 # . . discard args -4272 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -4273 # check-ints-equal(eax, 0xa, msg) -4274 # . . push args -4275 68/push "F - test-next-positive-hex-int-single-digit"/imm32 -4276 68/push 0xa/imm32 -4277 50/push-eax -4278 # . . call -4279 e8/call check-ints-equal/disp32 -4280 # . . discard args -4281 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -4282 # . epilog -4283 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -4284 5d/pop-to-ebp -4285 c3/return -4286 -4287 test-next-positive-hex-int-multi-digit: -4288 # . prolog -4289 55/push-ebp -4290 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -4291 # (eax..ecx) = "34a)" -4292 b8/copy-to-eax "34a)"/imm32 -4293 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -4294 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 -4295 05/add-to-eax 4/imm32 -4296 # var slice/ecx = {eax, ecx} -4297 51/push-ecx -4298 50/push-eax -4299 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -4300 # eax = next-positive-hex-int(slice) -4301 # . . push args -4302 51/push-ecx -4303 # . . call -4304 e8/call next-positive-hex-int/disp32 -4305 # . . discard args -4306 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -4307 # check-ints-equal(eax, 0x34a, msg) -4308 # . . push args -4309 68/push "F - test-next-positive-hex-int-multi-digit"/imm32 -4310 68/push 0x34a/imm32 -4311 50/push-eax -4312 # . . call -4313 e8/call check-ints-equal/disp32 -4314 # . . discard args -4315 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -4316 # . epilog -4317 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -4318 5d/pop-to-ebp -4319 c3/return -4320 -4321 test-next-positive-hex-int-0x-prefix: -4322 # . prolog -4323 55/push-ebp -4324 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -4325 # (eax..ecx) = "0x34)" -4326 b8/copy-to-eax "0x34)"/imm32 -4327 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -4328 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 -4329 05/add-to-eax 4/imm32 -4330 # var slice/ecx = {eax, ecx} -4331 51/push-ecx -4332 50/push-eax -4333 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -4334 # eax = next-positive-hex-int(slice) -4335 # . . push args -4336 51/push-ecx -4337 # . . call -4338 e8/call next-positive-hex-int/disp32 -4339 # . . discard args -4340 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -4341 # check-ints-equal(eax, 0x34, msg) -4342 # . . push args -4343 68/push "F - test-next-positive-hex-int-0x-prefix"/imm32 -4344 68/push 0x34/imm32 -4345 50/push-eax -4346 # . . call -4347 e8/call check-ints-equal/disp32 -4348 # . . discard args -4349 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -4350 # . epilog -4351 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -4352 5d/pop-to-ebp -4353 c3/return -4354 -4355 test-next-positive-hex-int-zero: -4356 # . prolog -4357 55/push-ebp -4358 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -4359 # (eax..ecx) = "0" -4360 b8/copy-to-eax "0"/imm32 -4361 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -4362 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 -4363 05/add-to-eax 4/imm32 -4364 # var slice/ecx = {eax, ecx} -4365 51/push-ecx -4366 50/push-eax -4367 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -4368 # eax = next-positive-hex-int(slice) -4369 # . . push args -4370 51/push-ecx -4371 # . . call -4372 e8/call next-positive-hex-int/disp32 -4373 # . . discard args -4374 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -4375 # check-ints-equal(eax, 0, msg) -4376 # . . push args -4377 68/push "F - test-next-positive-hex-int-zero"/imm32 -4378 68/push 0/imm32 -4379 50/push-eax -4380 # . . call -4381 e8/call check-ints-equal/disp32 -4382 # . . discard args -4383 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -4384 # . epilog -4385 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -4386 5d/pop-to-ebp -4387 c3/return -4388 -4389 test-next-positive-hex-int-0-prefix: -4390 # . prolog -4391 55/push-ebp -4392 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp -4393 # (eax..ecx) = "03)" -4394 b8/copy-to-eax "03)"/imm32 -4395 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx -4396 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 -4397 05/add-to-eax 4/imm32 -4398 # var slice/ecx = {eax, ecx} -4399 51/push-ecx -4400 50/push-eax -4401 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx -4402 # eax = next-positive-hex-int(slice) -4403 # . . push args -4404 51/push-ecx -4405 # . . call -4406 e8/call next-positive-hex-int/disp32 -4407 # . . discard args -4408 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp -4409 # check-ints-equal(eax, 3, msg) -4410 # . . push args -4411 68/push "F - test-next-positive-hex-int-0-prefix"/imm32 -4412 68/push 3/imm32 -4413 50/push-eax -4414 # . . call -4415 e8/call check-ints-equal/disp32 -4416 # . . discard args -4417 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp -4418 # . epilog -4419 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp -4420 5d/pop-to-ebp -4421 c3/return -4422 -4423 == data -4424 Registers: # (table string int) -4425 # a table is a stream -4426 0x40/imm32/write -4427 0/imm32/read -4428 0x40/imm32/length -4429 # data -4430 "eax"/imm32 0/imm32 -4431 "ecx"/imm32 1/imm32 -4432 "edx"/imm32 2/imm32 -4433 "ebx"/imm32 3/imm32 -4434 "esp"/imm32 4/imm32 -4435 "ebp"/imm32 5/imm32 -4436 "esi"/imm32 6/imm32 -4437 "edi"/imm32 7/imm32 -4438 -4439 # . . vim:nowrap:textwidth=0 +4170 # (eax..ecx) = "+0x34)" +4171 b8/copy-to-eax "+0x34)"/imm32 +4172 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +4173 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 +4174 05/add-to-eax 4/imm32 +4175 # var slice/ecx = {eax, ecx} +4176 51/push-ecx +4177 50/push-eax +4178 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +4179 # eax = next-hex-int(slice) +4180 # . . push args +4181 51/push-ecx +4182 # . . call +4183 e8/call next-hex-int/disp32 +4184 # . . discard args +4185 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +4186 # check-ints-equal(eax, 0x34, msg) +4187 # . . push args +4188 68/push "F - test-next-hex-int-0x-prefix"/imm32 +4189 68/push 0x34/imm32 +4190 50/push-eax +4191 # . . call +4192 e8/call check-ints-equal/disp32 +4193 # . . discard args +4194 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +4195 # . epilog +4196 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +4197 5d/pop-to-ebp +4198 c3/return +4199 +4200 test-next-hex-int-zero: +4201 # . prolog +4202 55/push-ebp +4203 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +4204 # (eax..ecx) = "+0)" +4205 b8/copy-to-eax "+0)"/imm32 +4206 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +4207 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 +4208 05/add-to-eax 4/imm32 +4209 # var slice/ecx = {eax, ecx} +4210 51/push-ecx +4211 50/push-eax +4212 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +4213 # eax = next-hex-int(slice) +4214 # . . push args +4215 51/push-ecx +4216 # . . call +4217 e8/call next-hex-int/disp32 +4218 # . . discard args +4219 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +4220 # check-ints-equal(eax, 0, msg) +4221 # . . push args +4222 68/push "F - test-next-hex-int-zero"/imm32 +4223 68/push 0/imm32 +4224 50/push-eax +4225 # . . call +4226 e8/call check-ints-equal/disp32 +4227 # . . discard args +4228 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +4229 # . epilog +4230 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +4231 5d/pop-to-ebp +4232 c3/return +4233 +4234 test-next-hex-int-0-prefix: +4235 # . prolog +4236 55/push-ebp +4237 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +4238 # (eax..ecx) = "+ 03)" +4239 b8/copy-to-eax "+ 03)"/imm32 +4240 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +4241 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 +4242 05/add-to-eax 4/imm32 +4243 # var slice/ecx = {eax, ecx} +4244 51/push-ecx +4245 50/push-eax +4246 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +4247 # eax = next-hex-int(slice) +4248 # . . push args +4249 51/push-ecx +4250 # . . call +4251 e8/call next-hex-int/disp32 +4252 # . . discard args +4253 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +4254 # check-ints-equal(eax, 3, msg) +4255 # . . push args +4256 68/push "F - test-next-hex-int-0-prefix"/imm32 +4257 68/push 3/imm32 +4258 50/push-eax +4259 # . . call +4260 e8/call check-ints-equal/disp32 +4261 # . . discard args +4262 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +4263 # . epilog +4264 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +4265 5d/pop-to-ebp +4266 c3/return +4267 +4268 test-next-hex-int-negative: +4269 # . prolog +4270 55/push-ebp +4271 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +4272 # (eax..ecx) = "-03)" +4273 b8/copy-to-eax "-03)"/imm32 +4274 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +4275 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 +4276 05/add-to-eax 4/imm32 +4277 # var slice/ecx = {eax, ecx} +4278 51/push-ecx +4279 50/push-eax +4280 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +4281 # eax = next-hex-int(slice) +4282 # . . push args +4283 51/push-ecx +4284 # . . call +4285 e8/call next-hex-int/disp32 +4286 # . . discard args +4287 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +4288 # check-ints-equal(eax, -3, msg) +4289 # . . push args +4290 68/push "F - test-next-hex-int-negative"/imm32 +4291 68/push -3/imm32 +4292 50/push-eax +4293 # . . call +4294 e8/call check-ints-equal/disp32 +4295 # . . discard args +4296 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +4297 # . epilog +4298 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +4299 5d/pop-to-ebp +4300 c3/return +4301 +4302 test-next-hex-int-negative-with-space: +4303 # . prolog +4304 55/push-ebp +4305 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +4306 # (eax..ecx) = "- 03)" +4307 b8/copy-to-eax "- 03)"/imm32 +4308 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +4309 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 +4310 05/add-to-eax 4/imm32 +4311 # var slice/ecx = {eax, ecx} +4312 51/push-ecx +4313 50/push-eax +4314 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +4315 # eax = next-hex-int(slice) +4316 # . . push args +4317 51/push-ecx +4318 # . . call +4319 e8/call next-hex-int/disp32 +4320 # . . discard args +4321 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +4322 # check-ints-equal(eax, -3, msg) +4323 # . . push args +4324 68/push "F - test-next-hex-int-negative-with-space"/imm32 +4325 68/push -3/imm32 +4326 50/push-eax +4327 # . . call +4328 e8/call check-ints-equal/disp32 +4329 # . . discard args +4330 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +4331 # . epilog +4332 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +4333 5d/pop-to-ebp +4334 c3/return +4335 +4336 # assumes 'in' starts a positive unsigned integer +4337 # returns the value of the integer +4338 # side-effect: modifies 'in' to skip past the integer +4339 next-positive-hex-int: # in : (address slice) -> result/eax +4340 # . prolog +4341 55/push-ebp +4342 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +4343 # . save registers +4344 51/push-ecx +4345 52/push-edx +4346 53/push-ebx +4347 56/push-esi +4348 57/push-edi +4349 # result/edi = 0 +4350 31/xor 3/mod/direct 7/rm32/edi . . . 7/r32/edi . . # clear edi +4351 # esi = in +4352 8b/copy 1/mod/*+disp8 5/rm32/ebp . . . 6/r32/esi 8/disp8 . # copy *(ebp+8) to esi +4353 # edx = in->end +4354 8b/copy 1/mod/*+disp8 6/rm32/esi . . . 2/r32/edx 4/disp8 . # copy *(esi+4) to edx +4355 # curr/ecx = in->start +4356 8b/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy *esi to ecx +4357 # negate?/ebx = false +4358 31/xor 3/mod/direct 3/rm32/ebx . . . 3/r32/ebx . . # clear ebx +4359 # eax = *curr +4360 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax +4361 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL +4362 $next-positive-hex-int:initial-0: +4363 # skip past leading '0x' +4364 # . if (*curr != '0') jump to loop +4365 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL +4366 3d/compare-eax-and 0x30/imm32/0 +4367 75/jump-if-not-equal $next-positive-hex-int:loop/disp8 +4368 # . ++curr +4369 41/increment-ecx +4370 $next-positive-hex-int:initial-0x: +4371 # . if (curr >= in->end) return result +4372 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx +4373 73/jump-if-greater-or-equal-unsigned $next-positive-hex-int:end/disp8 +4374 # . if (*curr != 'x') jump to loop # the previous '0' is still valid so doesn't need to be checked again +4375 31/xor 3/mod/direct 0/rm32/eax . . . 0/r32/eax . . # clear eax +4376 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL +4377 3d/compare-eax-and 0x78/imm32/x +4378 75/jump-if-not-equal $next-positive-hex-int:loop/disp8 +4379 # . ++curr +4380 41/increment-ecx +4381 $next-positive-hex-int:loop: +4382 # if (curr >= in->end) break +4383 39/compare 3/mod/direct 1/rm32/ecx . . . 2/r32/edx . . # compare ecx with edx +4384 73/jump-if-greater-or-equal-unsigned $next-positive-hex-int:end/disp8 +4385 # if (!is-hex-digit?(*curr)) break +4386 # . eax = *curr +4387 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL +4388 # . eax = is-hex-digit?(*curr) +4389 # . . push args +4390 50/push-eax +4391 # . . call +4392 e8/call is-hex-digit?/disp32 +4393 # . . discard args +4394 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +4395 # . if (eax == 0) break +4396 3d/compare-eax-and 0/imm32 +4397 74/jump-if-equal $next-positive-hex-int:end/disp8 +4398 # eax = from-hex-char(*curr) +4399 # . . copy arg to eax +4400 8a/copy-byte 0/mod/indirect 1/rm32/ecx . . . 0/r32/AL . . # copy byte at *ecx to AL +4401 # . . call +4402 e8/call from-hex-char/disp32 +4403 # result = result * 16 + eax +4404 c1/shift 4/subop/left 3/mod/direct 7/rm32/edi . . . . . 4/imm8 # shift edi left by 4 bits +4405 01/add 3/mod/direct 7/rm32/edi . . . 0/r32/eax . . # add eax to edi +4406 # ++curr +4407 41/increment-ecx +4408 # loop +4409 eb/jump $next-positive-hex-int:loop/disp8 +4410 $next-positive-hex-int:end: +4411 # word->start = curr +4412 89/copy 0/mod/indirect 6/rm32/esi . . . 1/r32/ecx . . # copy ecx to *esi +4413 # return edi +4414 89/copy 3/mod/direct 0/rm32/eax . . . 7/r32/edi . . # copy edi to eax +4415 # . restore registers +4416 5f/pop-to-edi +4417 5e/pop-to-esi +4418 5b/pop-to-ebx +4419 5a/pop-to-edx +4420 59/pop-to-ecx +4421 # . epilog +4422 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +4423 5d/pop-to-ebp +4424 c3/return +4425 +4426 test-next-positive-hex-int-single-digit: +4427 # . prolog +4428 55/push-ebp +4429 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +4430 # (eax..ecx) = "a)" +4431 b8/copy-to-eax "a)"/imm32 +4432 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +4433 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 +4434 05/add-to-eax 4/imm32 +4435 # var slice/ecx = {eax, ecx} +4436 51/push-ecx +4437 50/push-eax +4438 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +4439 # eax = next-positive-hex-int(slice) +4440 # . . push args +4441 51/push-ecx +4442 # . . call +4443 e8/call next-positive-hex-int/disp32 +4444 # . . discard args +4445 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +4446 # check-ints-equal(eax, 0xa, msg) +4447 # . . push args +4448 68/push "F - test-next-positive-hex-int-single-digit"/imm32 +4449 68/push 0xa/imm32 +4450 50/push-eax +4451 # . . call +4452 e8/call check-ints-equal/disp32 +4453 # . . discard args +4454 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +4455 # . epilog +4456 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +4457 5d/pop-to-ebp +4458 c3/return +4459 +4460 test-next-positive-hex-int-multi-digit: +4461 # . prolog +4462 55/push-ebp +4463 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +4464 # (eax..ecx) = "34a)" +4465 b8/copy-to-eax "34a)"/imm32 +4466 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +4467 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 +4468 05/add-to-eax 4/imm32 +4469 # var slice/ecx = {eax, ecx} +4470 51/push-ecx +4471 50/push-eax +4472 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +4473 # eax = next-positive-hex-int(slice) +4474 # . . push args +4475 51/push-ecx +4476 # . . call +4477 e8/call next-positive-hex-int/disp32 +4478 # . . discard args +4479 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +4480 # check-ints-equal(eax, 0x34a, msg) +4481 # . . push args +4482 68/push "F - test-next-positive-hex-int-multi-digit"/imm32 +4483 68/push 0x34a/imm32 +4484 50/push-eax +4485 # . . call +4486 e8/call check-ints-equal/disp32 +4487 # . . discard args +4488 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +4489 # . epilog +4490 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +4491 5d/pop-to-ebp +4492 c3/return +4493 +4494 test-next-positive-hex-int-0x-prefix: +4495 # . prolog +4496 55/push-ebp +4497 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +4498 # (eax..ecx) = "0x34)" +4499 b8/copy-to-eax "0x34)"/imm32 +4500 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +4501 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 +4502 05/add-to-eax 4/imm32 +4503 # var slice/ecx = {eax, ecx} +4504 51/push-ecx +4505 50/push-eax +4506 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +4507 # eax = next-positive-hex-int(slice) +4508 # . . push args +4509 51/push-ecx +4510 # . . call +4511 e8/call next-positive-hex-int/disp32 +4512 # . . discard args +4513 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +4514 # check-ints-equal(eax, 0x34, msg) +4515 # . . push args +4516 68/push "F - test-next-positive-hex-int-0x-prefix"/imm32 +4517 68/push 0x34/imm32 +4518 50/push-eax +4519 # . . call +4520 e8/call check-ints-equal/disp32 +4521 # . . discard args +4522 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +4523 # . epilog +4524 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +4525 5d/pop-to-ebp +4526 c3/return +4527 +4528 test-next-positive-hex-int-zero: +4529 # . prolog +4530 55/push-ebp +4531 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +4532 # (eax..ecx) = "0" +4533 b8/copy-to-eax "0"/imm32 +4534 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +4535 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 +4536 05/add-to-eax 4/imm32 +4537 # var slice/ecx = {eax, ecx} +4538 51/push-ecx +4539 50/push-eax +4540 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +4541 # eax = next-positive-hex-int(slice) +4542 # . . push args +4543 51/push-ecx +4544 # . . call +4545 e8/call next-positive-hex-int/disp32 +4546 # . . discard args +4547 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +4548 # check-ints-equal(eax, 0, msg) +4549 # . . push args +4550 68/push "F - test-next-positive-hex-int-zero"/imm32 +4551 68/push 0/imm32 +4552 50/push-eax +4553 # . . call +4554 e8/call check-ints-equal/disp32 +4555 # . . discard args +4556 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +4557 # . epilog +4558 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +4559 5d/pop-to-ebp +4560 c3/return +4561 +4562 test-next-positive-hex-int-0-prefix: +4563 # . prolog +4564 55/push-ebp +4565 89/copy 3/mod/direct 5/rm32/ebp . . . 4/r32/esp . . # copy esp to ebp +4566 # (eax..ecx) = "03)" +4567 b8/copy-to-eax "03)"/imm32 +4568 8b/copy 0/mod/indirect 0/rm32/eax . . . 1/r32/ecx . . # copy *eax to ecx +4569 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 +4570 05/add-to-eax 4/imm32 +4571 # var slice/ecx = {eax, ecx} +4572 51/push-ecx +4573 50/push-eax +4574 89/copy 3/mod/direct 1/rm32/ecx . . . 4/r32/esp . . # copy esp to ecx +4575 # eax = next-positive-hex-int(slice) +4576 # . . push args +4577 51/push-ecx +4578 # . . call +4579 e8/call next-positive-hex-int/disp32 +4580 # . . discard args +4581 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 4/imm32 # add to esp +4582 # check-ints-equal(eax, 3, msg) +4583 # . . push args +4584 68/push "F - test-next-positive-hex-int-0-prefix"/imm32 +4585 68/push 3/imm32 +4586 50/push-eax +4587 # . . call +4588 e8/call check-ints-equal/disp32 +4589 # . . discard args +4590 81 0/subop/add 3/mod/direct 4/rm32/esp . . . . . 0xc/imm32 # add to esp +4591 # . epilog +4592 89/copy 3/mod/direct 4/rm32/esp . . . 5/r32/ebp . . # copy ebp to esp +4593 5d/pop-to-ebp +4594 c3/return +4595 +4596 == data +4597 Registers: # (table string int) +4598 # a table is a stream +4599 0x40/imm32/write +4600 0/imm32/read +4601 0x40/imm32/length +4602 # data +4603 "eax"/imm32 0/imm32 +4604 "ecx"/imm32 1/imm32 +4605 "edx"/imm32 2/imm32 +4606 "ebx"/imm32 3/imm32 +4607 "esp"/imm32 4/imm32 +4608 "ebp"/imm32 5/imm32 +4609 "esi"/imm32 6/imm32 +4610 "edi"/imm32 7/imm32 +4611 +4612 # . . vim:nowrap:textwidth=0 -- cgit 1.4.1-2-gfad0