diff --git a/apps/assort.subx b/apps/assort.subx index 917dfb5c..e150a924 100644 --- a/apps/assort.subx +++ b/apps/assort.subx @@ -7,7 +7,7 @@ # because we don't know if they refer to the line above or the line below. # # To run: -# $ ./subx translate *.subx apps/assort.subx -o apps/assort +# $ ./subx translate 0*.subx apps/subx-common.subx apps/assort.subx -o apps/assort # $ cat x # == code # abc diff --git a/apps/crenshaw2-1.subx b/apps/crenshaw2-1.subx index bd8cc5d6..7f91d06e 100644 --- a/apps/crenshaw2-1.subx +++ b/apps/crenshaw2-1.subx @@ -3,7 +3,7 @@ # except that we support hex digits. # # To run: -# $ ./subx translate *.subx apps/crenshaw2-1.subx -o apps/crenshaw2-1 +# $ ./subx translate 0*.subx apps/crenshaw2-1.subx -o apps/crenshaw2-1 # $ echo '3' |./subx run apps/crenshaw2-1 # Expected output: # # syscall(exit, 3) diff --git a/apps/crenshaw2-1b.subx b/apps/crenshaw2-1b.subx index cb75033f..e19d5aeb 100644 --- a/apps/crenshaw2-1b.subx +++ b/apps/crenshaw2-1b.subx @@ -3,7 +3,7 @@ # except that we support hex numbers of multiple digits. # # To run: -# $ ./subx translate *.subx apps/crenshaw2-1b.subx -o apps/crenshaw2-1b +# $ ./subx translate 0*.subx apps/crenshaw2-1b.subx -o apps/crenshaw2-1b # $ echo '1a' |./subx run apps/crenshaw2-1b # Expected output: # # syscall(exit, 1a) diff --git a/apps/desugar.subx b/apps/desugar.subx index 4110ddec..e66e58b1 100644 --- a/apps/desugar.subx +++ b/apps/desugar.subx @@ -1,5 +1,8 @@ # Experimental syntax sugar for SubX programs. # +# To run: +# $ ./subx translate 0*.subx apps/subx-common.subx apps/desugar.subx -o apps/desugar +# # We're experimenting with the following expressions: # # 1. diff --git a/apps/dquotes.subx b/apps/dquotes.subx index 20343d15..1375211c 100644 --- a/apps/dquotes.subx +++ b/apps/dquotes.subx @@ -2,7 +2,7 @@ # Replace them with references to new variables in the data segment. # # To run: -# $ ./subx translate *.subx apps/dquotes.subx -o apps/dquotes +# $ ./subx translate 0*.subx apps/subx-common.subx apps/dquotes.subx -o apps/dquotes # $ cat x # == code # ab "cd ef"/imm32 diff --git a/apps/factorial.subx b/apps/factorial.subx index f28a3657..8bbcedbd 100644 --- a/apps/factorial.subx +++ b/apps/factorial.subx @@ -1,7 +1,7 @@ ## compute the factorial of 5, and return the result in the exit code # # To run: -# $ ./subx translate apps/factorial.subx -o apps/factorial +# $ ./subx translate 0*.subx apps/factorial.subx -o apps/factorial # $ ./subx run apps/factorial # Expected result: # $ echo $? diff --git a/apps/handle.subx b/apps/handle.subx index 95364821..01e6adf9 100644 --- a/apps/handle.subx +++ b/apps/handle.subx @@ -13,7 +13,7 @@ # offset 4: address # # To run: -# $ ./subx translate *.subx apps/handle.subx -o apps/handle +# $ ./subx translate 0*.subx apps/handle.subx -o apps/handle # $ ./subx run apps/handle # Expected result is a successful lookup followed by a hard abort: # lookup succeeded diff --git a/apps/hex.subx b/apps/hex.subx index a2580e66..d5be93f4 100644 --- a/apps/hex.subx +++ b/apps/hex.subx @@ -3,7 +3,7 @@ # comments between '#' and newline. # # To run: -# $ ./subx translate *.subx apps/hex.subx -o apps/hex +# $ ./subx translate 0*.subx apps/subx-common.subx apps/hex.subx -o apps/hex # $ echo '80 81 82 # comment' |./subx run apps/hex |xxd - # Expected output: # 00000000: 8081 82 diff --git a/apps/pack.subx b/apps/pack.subx index 9499f3b3..029952e3 100644 --- a/apps/pack.subx +++ b/apps/pack.subx @@ -3,7 +3,7 @@ # uses are left untouched. # # To run: -# $ ./subx translate *.subx apps/pack.subx -o apps/pack +# $ ./subx translate 0*.subx apps/subx-common.subx apps/pack.subx -o apps/pack # $ echo '05/add-to-EAX 0x20/imm32' |./subx run apps/pack # Expected output: # 05 20 00 00 00 # 05/add-to-EAX 0x20/imm32 diff --git a/apps/survey.subx b/apps/survey.subx index d226ecc0..ee9f637d 100644 --- a/apps/survey.subx +++ b/apps/survey.subx @@ -5,7 +5,7 @@ # b) add segment headers with addresses and offsets correctly filled in # # To build: -# $ ./subx translate *.subx apps/survey.subx -o apps/survey +# $ ./subx translate 0*.subx apps/subx-common.subx apps/survey.subx -o apps/survey # # The expected input is a stream of bytes with segment headers, comments and # some interspersed labels. diff --git a/apps/tests.subx b/apps/tests.subx index 12f4902b..70456506 100644 --- a/apps/tests.subx +++ b/apps/tests.subx @@ -1,5 +1,8 @@ # Generate code for a new function called 'run-tests' which calls in sequence # all functions starting with 'test-'. +# +# To build: +# $ ./subx translate 0*.subx apps/subx-common.subx apps/tests.subx -o apps/tests == code # instruction effective address register displacement immediate diff --git a/html/apps/assort.subx.html b/html/apps/assort.subx.html index 466f6591..e392fa95 100644 --- a/html/apps/assort.subx.html +++ b/html/apps/assort.subx.html @@ -69,7 +69,7 @@ if ('onhashchange' in window) { 7 # because we don't know if they refer to the line above or the line below. 8 # 9 # To run: - 10 # $ ./subx translate *.subx apps/assort.subx -o apps/assort + 10 # $ ./subx translate 0*.subx apps/subx-common.subx apps/assort.subx -o apps/assort 11 # $ cat x 12 # == code 13 # abc diff --git a/html/apps/crenshaw2-1.subx.html b/html/apps/crenshaw2-1.subx.html index bc5eb083..d1efdecf 100644 --- a/html/apps/crenshaw2-1.subx.html +++ b/html/apps/crenshaw2-1.subx.html @@ -64,7 +64,7 @@ if ('onhashchange' in window) { 3 # except that we support hex digits. 4 # 5 # To run: - 6 # $ ./subx translate *.subx apps/crenshaw2-1.subx -o apps/crenshaw2-1 + 6 # $ ./subx translate 0*.subx apps/crenshaw2-1.subx -o apps/crenshaw2-1 7 # $ echo '3' |./subx run apps/crenshaw2-1 8 # Expected output: 9 # # syscall(exit, 3) diff --git a/html/apps/crenshaw2-1b.subx.html b/html/apps/crenshaw2-1b.subx.html index 5db393ba..72652b97 100644 --- a/html/apps/crenshaw2-1b.subx.html +++ b/html/apps/crenshaw2-1b.subx.html @@ -64,7 +64,7 @@ if ('onhashchange' in window) { 3 # except that we support hex numbers of multiple digits. 4 # 5 # To run: - 6 # $ ./subx translate *.subx apps/crenshaw2-1b.subx -o apps/crenshaw2-1b + 6 # $ ./subx translate 0*.subx apps/crenshaw2-1b.subx -o apps/crenshaw2-1b 7 # $ echo '1a' |./subx run apps/crenshaw2-1b 8 # Expected output: 9 # # syscall(exit, 1a) diff --git a/html/apps/desugar.subx.html b/html/apps/desugar.subx.html index 404e846f..6655a4bd 100644 --- a/html/apps/desugar.subx.html +++ b/html/apps/desugar.subx.html @@ -62,3900 +62,4047 @@ if ('onhashchange' in window) {
1 # Experimental syntax sugar for SubX programs. 2 # - 3 # We're experimenting with the following expressions: - 4 # - 5 # 1. - 6 # $ echo "ab %eax" | ./subx run apps/desugar - 7 # ab 3/mod 0/rm32 - 8 # - 9 # 2. - 10 # $ echo "ab *eax" | ./subx run apps/desugar - 11 # ab 0/mod 0/rm32 - 12 # - 13 # 3. - 14 # $ echo "ab *(eax+4)" | ./subx run apps/desugar - 15 # ab 2/mod 0/rm32 4/disp32 - 16 # - 17 # 4. - 18 # $ echo "ab *(eax+ecx)" | ./subx run apps/desugar - 19 # ab 0/mod 4/rm32 0/base 1/index 0/scale - 20 # - 21 # 5. - 22 # $ echo "ab *(eax+ecx+4)" | ./subx run apps/desugar - 23 # ab 2/mod 4/rm32 0/base 1/index 0/scale 4/disp32 - 24 # - 25 # 6. - 26 # $ echo "ab *(eax+ecx<<2+4)" | ./subx run apps/desugar - 27 # ab 2/mod 4/rm32 0/base 1/index 2/scale 4/disp32 - 28 # - 29 # Addition isn't commutative here. Template must always be (base+index<<scale+disp), - 30 # though some components are optional as described above. + 3 # To run: + 4 # $ ./subx translate 0*.subx apps/subx-common.subx apps/desugar.subx -o apps/desugar + 5 # + 6 # We're experimenting with the following expressions: + 7 # + 8 # 1. + 9 # $ echo "ab %eax" | ./subx run apps/desugar + 10 # ab 3/mod 0/rm32 + 11 # + 12 # 2. + 13 # $ echo "ab *eax" | ./subx run apps/desugar + 14 # ab 0/mod 0/rm32 + 15 # + 16 # 3. + 17 # $ echo "ab *(eax+4)" | ./subx run apps/desugar + 18 # ab 2/mod 0/rm32 4/disp32 + 19 # + 20 # 4. + 21 # $ echo "ab *(eax+ecx)" | ./subx run apps/desugar + 22 # ab 0/mod 4/rm32 0/base 1/index 0/scale + 23 # + 24 # 5. + 25 # $ echo "ab *(eax+ecx+4)" | ./subx run apps/desugar + 26 # ab 2/mod 4/rm32 0/base 1/index 0/scale 4/disp32 + 27 # + 28 # 6. + 29 # $ echo "ab *(eax+ecx<<2+4)" | ./subx run apps/desugar + 30 # ab 2/mod 4/rm32 0/base 1/index 2/scale 4/disp32 31 # - 32 # No metadata allowed inside '*(...)'. - 33 # Whitespace inside '*(...)' is ok. But not immediately after the '*' or '%'. - 34 - 35 == code - 36 # instruction effective address register displacement immediate - 37 # . op subop mod rm32 base index scale r32 - 38 # . 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 - 39 - 40 Entry: # run tests if necessary, convert stdin if not - 41 # initialize heap - 42 # . Heap = new-segment(Heap-size) - 43 # . . push args - 44 68/push Heap/imm32 - 45 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Heap-size/disp32 # push *Heap-size - 46 # . . call - 47 e8/call new-segment/disp32 - 48 # . . discard args - 49 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 50 - 51 # run tests if necessary, convert stdin if not - 52 # . prolog - 53 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 54 # - if argc > 1 and argv[1] == "test", then return run_tests() - 55 # . argc > 1 - 56 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP - 57 7e/jump-if-lesser-or-equal $run-main/disp8 - 58 # . argv[1] == "test" - 59 # . . push args - 60 68/push "test"/imm32 - 61 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 62 # . . call - 63 e8/call kernel-string-equal?/disp32 - 64 # . . discard args - 65 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 66 # . check result - 67 3d/compare-EAX-and 1/imm32 - 68 75/jump-if-not-equal $run-main/disp8 - 69 # . run-tests() - 70 e8/call run-tests/disp32 - 71 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX - 72 eb/jump $main:end/disp8 - 73 $run-main: - 74 # - otherwise convert stdin - 75 # convert(Stdin, Stdout) - 76 # . . push args - 77 68/push Stdout/imm32 - 78 68/push Stdin/imm32 - 79 # . . call - 80 e8/call convert/disp32 - 81 # . . discard args - 82 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x8/imm32 # add to ESP - 83 # . syscall(exit, 0) - 84 bb/copy-to-EBX 0/imm32 - 85 $main:end: - 86 b8/copy-to-EAX 1/imm32/exit - 87 cd/syscall 0x80/imm8 - 88 - 89 # error messages considered: - 90 # *x + 34 -> error: base+disp addressing must be within '()' - 91 convert: # in : (address buffered-file), out : (address buffered-file) -> <void> - 92 # pseudocode: - 93 # var line = new-stream(512, 1) - 94 # while true - 95 # clear-stream(line) - 96 # read-line-buffered(in, line) - 97 # if (line->write == 0) break # end of file - 98 # while true - 99 # var word-slice = next-word-or-expression(line) - 100 # if slice-empty?(word-slice) # end of line - 101 # break - 102 # if slice-starts-with?(word-slice, "#") # comment - 103 # continue - 104 # if slice-starts-with?(word-slice, '%') # direct mode - 105 # emit-direct-mode(word-slice, out) - 106 # else if slice-starts-with?(word-slice, '*') # indirect mode - 107 # base, index, scale, disp = parse-effective-address(word-slice) - 108 # emit-indirect-mode(out, base, index, scale, disp) - 109 # else if slice-starts-with?(word-slice, '+') - 110 # abort("'+' only permitted within '*(...)'") - 111 # else - 112 # write-slice-buffered(out, word-slice) - 113 # write(out, " ") - 114 # write(out, "\n") - 115 # flush(out) - 116 # - 117 # . prolog - 118 55/push-EBP - 119 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 120 # . save registers - 121 50/push-EAX - 122 51/push-ECX - 123 52/push-EDX - 124 53/push-EBX - 125 # var line/ECX : (address stream byte) = stream(512) - 126 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0x200/imm32 # subtract from ESP - 127 68/push 0x200/imm32/length - 128 68/push 0/imm32/read - 129 68/push 0/imm32/write - 130 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 131 # var word-slice/EDX = {0, 0} - 132 68/push 0/imm32/end - 133 68/push 0/imm32/start - 134 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX - 135 $convert:line-loop: - 136 # clear-stream(line) - 137 # . . push args - 138 51/push-ECX - 139 # . . call - 140 e8/call clear-stream/disp32 - 141 # . . discard args - 142 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 143 # read-line-buffered(in, line) - 144 # . . push args - 145 51/push-ECX - 146 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 147 # . . call - 148 e8/call read-line-buffered/disp32 - 149 # . . discard args - 150 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 151 $convert:check0: - 152 # if (line->write == 0) break - 153 81 7/subop/compare 0/mod/indirect 1/rm32/ECX . . . . . 0/imm32 # compare *ECX - 154 0f 84/jump-if-equal $convert:break/disp32 - 155 $convert:word-loop: - 156 # next-word-or-expression(line, word-slice) - 157 # . . push args - 158 52/push-EDX - 159 51/push-ECX - 160 # . . call - 161 e8/call next-word-or-expression/disp32 - 162 # . . discard args - 163 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 164 $convert:check1: - 165 # if (slice-empty?(word-slice)) break - 166 # . EAX = slice-empty?(word-slice) - 167 # . . push args - 168 52/push-EDX - 169 # . . call - 170 e8/call slice-empty?/disp32 - 171 # . . discard args - 172 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 173 # . if (EAX != 0) break - 174 3d/compare-EAX-and 0/imm32 - 175 0f 85/jump-if-not-equal $convert:next-line/disp32 - 176 $convert:check-for-comment: - 177 # if (slice-starts-with?(word-slice, "#")) continue - 178 # . start/EBX = word-slice->start - 179 8b/copy 0/mod/indirect 2/rm32/EDX . . . 3/r32/EBX . . # copy *EDX to EBX - 180 # . c/EAX = *start - 181 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX - 182 8a/copy-byte 0/mod/indirect 3/rm32/EBX . . . 0/r32/AL . . # copy byte at *EBX to AL - 183 # . if (EAX == '#') continue - 184 3d/compare-EAX-and 0x23/imm32/hash - 185 74/jump-if-equal $convert:word-loop/disp8 - 186 $convert:check-for-direct-mode: - 187 # if (!slice-starts-with?(word-slice, "%")) goto next check - 188 3d/compare-EAX-and 0x25/imm32/percent - 189 75/jump-if-not-equal $convert:check-for-indirect-mode/disp8 - 190 $convert:direct-mode: - 191 +-- 46 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- - 237 # emit-direct-mode(word-slice, out) - 238 # . . push args - 239 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 240 52/push-EDX - 241 # . . call - 242 e8/call emit-direct-mode/disp32 - 243 # . . discard args - 244 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 245 # continue - 246 e9/jump $convert:next-word/disp32 - 247 $convert:check-for-indirect-mode: - 248 # if (!slice-starts-with?(word-slice, "*")) goto next check - 249 3d/compare-EAX-and 0x2a/imm32/asterisk - 250 75/jump-if-not-equal $convert:check-for-invalid-addition/disp8 - 251 $convert:indirect-mode: - 252 # spill registers - 253 50/push-EAX - 254 51/push-ECX - 255 52/push-EDX - 256 53/push-EBX - 257 # base/EAX, index/ECX, scale/EDX, disp/EBX = parse-effective-address(word-slice) - 258 # . . push args - 259 52/push-EDX - 260 # . . call - 261 e8/call parse-effective-address/disp32 - 262 # . . discard args - 263 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 264 # emit-indirect-mode(out, base, index, scale, disp) - 265 # . . push args - 266 53/push-EBX - 267 52/push-EDX - 268 51/push-ECX - 269 50/push-EAX - 270 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 271 # . . call - 272 e8/call emit-indirect-mode/disp32 - 273 # . . discard args - 274 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP - 275 # restore registers - 276 5b/pop-to-EBX - 277 5a/pop-to-EDX - 278 59/pop-to-ECX - 279 58/pop-to-EAX - 280 # continue - 281 e9/jump $convert:next-word/disp32 - 282 $convert:check-for-invalid-addition: - 283 # if (slice-starts-with?(word-slice, "+")) goto error1 - 284 3d/compare-EAX-and 0x2b/imm32/plus - 285 74/jump-if-equal $convert:error1/disp8 - 286 $convert:check-for-invalid-left-shift: - 287 # if (slice-starts-with?(word-slice, "<")) goto error1 - 288 3d/compare-EAX-and 0x3c/imm32/less-than - 289 74/jump-if-equal $convert:error1/disp8 - 290 $convert:regular-word: - 291 # write-slice-buffered(out, word-slice) - 292 # . . push args - 293 52/push-EDX - 294 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 295 # . . call - 296 e8/call write-slice-buffered/disp32 - 297 # . . discard args - 298 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 299 # fall through - 300 $convert:next-word: - 301 # write-buffered(out, " ") - 302 # . . push args - 303 68/push " "/imm32 - 304 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 305 # . . call - 306 e8/call write-buffered/disp32 - 307 # . . discard args - 308 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 309 # loop - 310 e9/jump $convert:word-loop/disp32 - 311 $convert:next-line: - 312 # write-buffered(out, "\n") - 313 # . . push args - 314 68/push Newline/imm32 - 315 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 316 # . . call - 317 e8/call write-buffered/disp32 - 318 # . . discard args - 319 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 320 # loop - 321 e9/jump $convert:line-loop/disp32 - 322 $convert:break: - 323 # flush(out) - 324 # . . push args - 325 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 326 # . . call - 327 e8/call flush/disp32 - 328 # . . discard args - 329 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 330 $convert:end: - 331 # . reclaim locals - 332 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x214/imm32 # add to ESP - 333 # . restore registers - 334 5b/pop-to-EBX - 335 5a/pop-to-EDX - 336 59/pop-to-ECX - 337 58/pop-to-EAX - 338 # . epilog - 339 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 340 5d/pop-to-EBP - 341 c3/return - 342 - 343 $convert:error1: - 344 # print(stderr, "error: '" EAX "' only permitted within '*(...)' in '" line "'") - 345 # . write-buffered(Stderr, "error: '") - 346 # . . push args - 347 68/push "error: '"/imm32 - 348 68/push Stderr/imm32 - 349 # . . call - 350 e8/call write-buffered/disp32 - 351 # . . discard args - 352 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 353 # . write-byte-buffered(Stderr, EAX) - 354 # . . push args - 355 50/push-EAX - 356 68/push Stderr/imm32 - 357 # . . call - 358 e8/call write-byte-buffered/disp32 - 359 # . . discard args - 360 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 361 # . write-buffered(Stderr, "' only permitted within '*(...)' in '") - 362 # . . push args - 363 68/push "' only permitted within '*(...)' in '"/imm32 - 364 68/push Stderr/imm32 - 365 # . . call - 366 e8/call write-buffered/disp32 - 367 # . . discard args - 368 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 369 # . write-stream-data(Stderr, line) - 370 # . . push args - 371 51/push-ECX - 372 68/push Stderr/imm32 - 373 # . . call - 374 e8/call write-stream-data/disp32 - 375 # . . discard args - 376 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 377 # . write-buffered(Stderr, "'") - 378 # . . push args - 379 68/push "'"/imm32 - 380 68/push Stderr/imm32 - 381 # . . call - 382 e8/call write-buffered/disp32 - 383 # . . discard args - 384 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 385 # . flush(Stderr) - 386 # . . push args - 387 68/push Stderr/imm32 - 388 # . . call - 389 e8/call flush/disp32 - 390 # . . discard args - 391 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 392 # . syscall(exit, 1) - 393 bb/copy-to-EBX 1/imm32 - 394 b8/copy-to-EAX 1/imm32/exit - 395 cd/syscall 0x80/imm8 - 396 # never gets here - 397 - 398 test-convert-passes-most-words-through: - 399 # . prolog - 400 55/push-EBP - 401 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 402 # setup - 403 # . clear-stream(_test-input-stream) - 404 # . . push args - 405 68/push _test-input-stream/imm32 - 406 # . . call - 407 e8/call clear-stream/disp32 - 408 # . . discard args - 409 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 410 # . clear-stream(_test-input-buffered-file+4) - 411 # . . push args - 412 b8/copy-to-EAX _test-input-buffered-file/imm32 - 413 05/add-to-EAX 4/imm32 - 414 50/push-EAX - 415 # . . call - 416 e8/call clear-stream/disp32 - 417 # . . discard args - 418 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 419 # . clear-stream(_test-output-stream) - 420 # . . push args - 421 68/push _test-output-stream/imm32 - 422 # . . call - 423 e8/call clear-stream/disp32 - 424 # . . discard args - 425 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 426 # . clear-stream(_test-output-buffered-file+4) - 427 # . . push args - 428 b8/copy-to-EAX _test-output-buffered-file/imm32 - 429 05/add-to-EAX 4/imm32 - 430 50/push-EAX - 431 # . . call - 432 e8/call clear-stream/disp32 - 433 # . . discard args - 434 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 435 # initialize input - 436 # . write(_test-input-stream, "== abcd 0x1") - 437 # . . push args - 438 68/push "== abcd 0x1"/imm32 - 439 68/push _test-input-stream/imm32 - 440 # . . call - 441 e8/call write/disp32 - 442 # . . discard args - 443 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 444 # convert(_test-input-buffered-file, _test-output-buffered-file) - 445 # . . push args - 446 68/push _test-output-buffered-file/imm32 - 447 68/push _test-input-buffered-file/imm32 - 448 # . . call - 449 e8/call convert/disp32 - 450 # . . discard args - 451 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 452 # check that the line just passed through - 453 # . flush(_test-output-buffered-file) - 454 # . . push args - 455 68/push _test-output-buffered-file/imm32 - 456 # . . call - 457 e8/call flush/disp32 - 458 # . . discard args - 459 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 460 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 486 # . check-stream-equal(_test-output-stream, "== abcd 0x1 \n", msg) - 487 # . . push args - 488 68/push "F - test-convert-passes-most-words-through"/imm32 - 489 68/push "== abcd 0x1 \n"/imm32 - 490 68/push _test-output-stream/imm32 - 491 # . . call - 492 e8/call check-stream-equal/disp32 - 493 # . . discard args - 494 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 495 # . epilog - 496 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 497 5d/pop-to-EBP - 498 c3/return - 499 - 500 test-convert-direct-mode: - 501 # . prolog - 502 55/push-EBP - 503 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 504 # setup - 505 # . clear-stream(_test-input-stream) - 506 # . . push args - 507 68/push _test-input-stream/imm32 - 508 # . . call - 509 e8/call clear-stream/disp32 - 510 # . . discard args - 511 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 512 # . clear-stream(_test-input-buffered-file+4) - 513 # . . push args - 514 b8/copy-to-EAX _test-input-buffered-file/imm32 - 515 05/add-to-EAX 4/imm32 - 516 50/push-EAX - 517 # . . call - 518 e8/call clear-stream/disp32 - 519 # . . discard args - 520 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 521 # . clear-stream(_test-output-stream) - 522 # . . push args - 523 68/push _test-output-stream/imm32 - 524 # . . call - 525 e8/call clear-stream/disp32 - 526 # . . discard args - 527 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 528 # . clear-stream(_test-output-buffered-file+4) - 529 # . . push args - 530 b8/copy-to-EAX _test-output-buffered-file/imm32 - 531 05/add-to-EAX 4/imm32 - 532 50/push-EAX - 533 # . . call - 534 e8/call clear-stream/disp32 - 535 # . . discard args - 536 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 537 # initialize input - 538 # . write(_test-input-stream, "ab %ecx") - 539 # . . push args - 540 68/push "ab %ecx"/imm32 - 541 68/push _test-input-stream/imm32 - 542 # . . call - 543 e8/call write/disp32 - 544 # . . discard args - 545 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 546 # convert(_test-input-buffered-file, _test-output-buffered-file) - 547 # . . push args - 548 68/push _test-output-buffered-file/imm32 - 549 68/push _test-input-buffered-file/imm32 - 550 # . . call - 551 e8/call convert/disp32 - 552 # . . discard args - 553 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 554 # check that the line just passed through - 555 # . flush(_test-output-buffered-file) - 556 # . . push args - 557 68/push _test-output-buffered-file/imm32 - 558 # . . call - 559 e8/call flush/disp32 - 560 # . . discard args - 561 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 562 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 588 # . check-stream-equal(_test-output-stream, "ab 3/mod/direct 0x00000001/rm32 \n", msg) - 589 # . . push args - 590 68/push "F - test-convert-direct-mode"/imm32 - 591 68/push "ab 3/mod/direct 0x00000001/rm32 \n"/imm32 - 592 68/push _test-output-stream/imm32 - 593 # . . call - 594 e8/call check-stream-equal/disp32 - 595 # . . discard args - 596 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 597 # . epilog - 598 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 599 5d/pop-to-EBP - 600 c3/return - 601 - 602 test-convert-register-indirect-mode: - 603 # . prolog - 604 55/push-EBP - 605 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 606 # setup - 607 # . clear-stream(_test-input-stream) - 608 # . . push args - 609 68/push _test-input-stream/imm32 - 610 # . . call - 611 e8/call clear-stream/disp32 - 612 # . . discard args - 613 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 614 # . clear-stream(_test-input-buffered-file+4) - 615 # . . push args - 616 b8/copy-to-EAX _test-input-buffered-file/imm32 - 617 05/add-to-EAX 4/imm32 - 618 50/push-EAX - 619 # . . call - 620 e8/call clear-stream/disp32 - 621 # . . discard args - 622 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 623 # . clear-stream(_test-output-stream) - 624 # . . push args - 625 68/push _test-output-stream/imm32 - 626 # . . call - 627 e8/call clear-stream/disp32 - 628 # . . discard args - 629 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 630 # . clear-stream(_test-output-buffered-file+4) - 631 # . . push args - 632 b8/copy-to-EAX _test-output-buffered-file/imm32 - 633 05/add-to-EAX 4/imm32 - 634 50/push-EAX - 635 # . . call - 636 e8/call clear-stream/disp32 - 637 # . . discard args - 638 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 639 # initialize input - 640 # . write(_test-input-stream, "ab *ecx") - 641 # . . push args - 642 68/push "ab *ecx"/imm32 - 643 68/push _test-input-stream/imm32 - 644 # . . call - 645 e8/call write/disp32 - 646 # . . discard args - 647 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 648 # convert(_test-input-buffered-file, _test-output-buffered-file) - 649 # . . push args - 650 68/push _test-output-buffered-file/imm32 - 651 68/push _test-input-buffered-file/imm32 - 652 # . . call - 653 e8/call convert/disp32 - 654 # . . discard args - 655 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 656 # check that the line just passed through - 657 # . flush(_test-output-buffered-file) - 658 # . . push args - 659 68/push _test-output-buffered-file/imm32 - 660 # . . call - 661 e8/call flush/disp32 - 662 # . . discard args - 663 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 664 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 690 # . check-stream-equal(_test-output-stream, "ab 0/mod/indirect 0x00000001/rm32 \n", msg) - 691 # . . push args - 692 68/push "F - test-convert-indirect-mode"/imm32 - 693 68/push "ab 0/mod/indirect 0x00000001/rm32 \n"/imm32 - 694 68/push _test-output-stream/imm32 - 695 # . . call - 696 e8/call check-stream-equal/disp32 - 697 # . . discard args - 698 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 699 # . epilog - 700 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 701 5d/pop-to-EBP - 702 c3/return - 703 - 704 test-convert-register-indirect-mode-without-displacement: - 705 # . prolog - 706 55/push-EBP - 707 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 708 # setup - 709 # . clear-stream(_test-input-stream) - 710 # . . push args - 711 68/push _test-input-stream/imm32 - 712 # . . call - 713 e8/call clear-stream/disp32 - 714 # . . discard args - 715 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 716 # . clear-stream(_test-input-buffered-file+4) - 717 # . . push args - 718 b8/copy-to-EAX _test-input-buffered-file/imm32 - 719 05/add-to-EAX 4/imm32 - 720 50/push-EAX - 721 # . . call - 722 e8/call clear-stream/disp32 - 723 # . . discard args - 724 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 725 # . clear-stream(_test-output-stream) - 726 # . . push args - 727 68/push _test-output-stream/imm32 - 728 # . . call - 729 e8/call clear-stream/disp32 - 730 # . . discard args - 731 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 732 # . clear-stream(_test-output-buffered-file+4) - 733 # . . push args - 734 b8/copy-to-EAX _test-output-buffered-file/imm32 - 735 05/add-to-EAX 4/imm32 - 736 50/push-EAX - 737 # . . call - 738 e8/call clear-stream/disp32 - 739 # . . discard args - 740 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 741 # initialize input - 742 # . write(_test-input-stream, "ab *(ecx)") - 743 # . . push args - 744 68/push "ab *(ecx)"/imm32 - 745 68/push _test-input-stream/imm32 - 746 # . . call - 747 e8/call write/disp32 - 748 # . . discard args - 749 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 750 # convert(_test-input-buffered-file, _test-output-buffered-file) - 751 # . . push args - 752 68/push _test-output-buffered-file/imm32 - 753 68/push _test-input-buffered-file/imm32 - 754 # . . call - 755 e8/call convert/disp32 - 756 # . . discard args - 757 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 758 # check that the line just passed through - 759 # . flush(_test-output-buffered-file) - 760 # . . push args - 761 68/push _test-output-buffered-file/imm32 - 762 # . . call - 763 e8/call flush/disp32 - 764 # . . discard args - 765 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 766 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 792 # . check-stream-equal(_test-output-stream, "ab 0/mod/indirect 1/rm32 \n", msg) - 793 # . . push args - 794 68/push "F - test-convert-indirect-mode-without-displacement"/imm32 - 795 68/push "ab 0/mod/indirect 0x00000001/rm32 \n"/imm32 - 796 68/push _test-output-stream/imm32 - 797 # . . call - 798 e8/call check-stream-equal/disp32 - 799 # . . discard args - 800 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 801 # . epilog - 802 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 803 5d/pop-to-EBP - 804 c3/return - 805 - 806 test-convert-register-indirect-mode-with-displacement: - 807 # . prolog - 808 55/push-EBP - 809 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 810 # setup - 811 # . clear-stream(_test-input-stream) - 812 # . . push args - 813 68/push _test-input-stream/imm32 - 814 # . . call - 815 e8/call clear-stream/disp32 - 816 # . . discard args - 817 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 818 # . clear-stream(_test-input-buffered-file+4) - 819 # . . push args - 820 b8/copy-to-EAX _test-input-buffered-file/imm32 - 821 05/add-to-EAX 4/imm32 - 822 50/push-EAX - 823 # . . call - 824 e8/call clear-stream/disp32 - 825 # . . discard args - 826 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 827 # . clear-stream(_test-output-stream) - 828 # . . push args - 829 68/push _test-output-stream/imm32 - 830 # . . call - 831 e8/call clear-stream/disp32 - 832 # . . discard args - 833 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 834 # . clear-stream(_test-output-buffered-file+4) - 835 # . . push args - 836 b8/copy-to-EAX _test-output-buffered-file/imm32 - 837 05/add-to-EAX 4/imm32 - 838 50/push-EAX - 839 # . . call - 840 e8/call clear-stream/disp32 - 841 # . . discard args - 842 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 843 # initialize input - 844 # . write(_test-input-stream, "ab *(ecx+4)") - 845 # . . push args - 846 68/push "ab *(ecx+4)"/imm32 - 847 68/push _test-input-stream/imm32 - 848 # . . call - 849 e8/call write/disp32 - 850 # . . discard args - 851 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 852 # convert(_test-input-buffered-file, _test-output-buffered-file) - 853 # . . push args - 854 68/push _test-output-buffered-file/imm32 - 855 68/push _test-input-buffered-file/imm32 - 856 # . . call - 857 e8/call convert/disp32 - 858 # . . discard args - 859 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 860 # check that the line just passed through - 861 # . flush(_test-output-buffered-file) - 862 # . . push args - 863 68/push _test-output-buffered-file/imm32 - 864 # . . call - 865 e8/call flush/disp32 - 866 # . . discard args - 867 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 868 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 894 # . check-stream-equal(_test-output-stream, "ab 2/mod/*+disp32 1/rm32 4/disp32 \n", msg) - 895 # . . push args - 896 68/push "F - test-convert-indirect-mode-with-displacement"/imm32 - 897 68/push "ab 2/mod/*+disp32 0x00000001/rm32 0x00000004/disp32 \n"/imm32 - 898 68/push _test-output-stream/imm32 - 899 # . . call - 900 e8/call check-stream-equal/disp32 - 901 # . . discard args - 902 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 903 # . epilog - 904 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 905 5d/pop-to-EBP - 906 c3/return - 907 - 908 # boss level - 909 test-convert-register-indirect-mode-with-sib-byte: - 910 # . prolog - 911 55/push-EBP - 912 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 913 # setup - 914 # . clear-stream(_test-input-stream) - 915 # . . push args - 916 68/push _test-input-stream/imm32 - 917 # . . call - 918 e8/call clear-stream/disp32 - 919 # . . discard args - 920 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 921 # . clear-stream(_test-input-buffered-file+4) - 922 # . . push args - 923 b8/copy-to-EAX _test-input-buffered-file/imm32 - 924 05/add-to-EAX 4/imm32 - 925 50/push-EAX - 926 # . . call - 927 e8/call clear-stream/disp32 - 928 # . . discard args - 929 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 930 # . clear-stream(_test-output-stream) - 931 # . . push args - 932 68/push _test-output-stream/imm32 - 933 # . . call - 934 e8/call clear-stream/disp32 - 935 # . . discard args - 936 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 937 # . clear-stream(_test-output-buffered-file+4) - 938 # . . push args - 939 b8/copy-to-EAX _test-output-buffered-file/imm32 - 940 05/add-to-EAX 4/imm32 - 941 50/push-EAX - 942 # . . call - 943 e8/call clear-stream/disp32 - 944 # . . discard args - 945 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 946 # initialize input - 947 # . write(_test-input-stream, "ab *(ecx + edx<<3 + 4)") - 948 # . . push args - 949 68/push "ab *(ecx + edx<<3 + 4)"/imm32 - 950 68/push _test-input-stream/imm32 - 951 # . . call - 952 e8/call write/disp32 - 953 # . . discard args - 954 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 955 # convert(_test-input-buffered-file, _test-output-buffered-file) - 956 # . . push args - 957 68/push _test-output-buffered-file/imm32 - 958 68/push _test-input-buffered-file/imm32 - 959 # . . call - 960 e8/call convert/disp32 - 961 # . . discard args - 962 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 963 # check that the line just passed through - 964 # . flush(_test-output-buffered-file) - 965 # . . push args - 966 68/push _test-output-buffered-file/imm32 - 967 # . . call - 968 e8/call flush/disp32 - 969 # . . discard args - 970 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 971 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- - 997 # . check-stream-equal(_test-output-stream, "ab 2/mod/*+disp32 4/rm32/sib 1/base 2/index 3/scale 4/disp32 \n", msg) - 998 # . . push args - 999 68/push "F - test-convert-indirect-mode-with-sib-byte"/imm32 -1000 68/push "ab 2/mod/*+disp32 4/rm32/sib 0x00000001/base 0x00000002/index 0x00000003/scale 0x00000004/disp32 \n"/imm32 -1001 68/push _test-output-stream/imm32 -1002 # . . call -1003 e8/call check-stream-equal/disp32 -1004 # . . discard args -1005 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1006 # . epilog -1007 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1008 5d/pop-to-EBP -1009 c3/return -1010 -1011 test-convert-register-indirect-mode-with-sib-byte-negative-displacement: -1012 # . prolog -1013 55/push-EBP -1014 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1015 # setup -1016 # . clear-stream(_test-input-stream) -1017 # . . push args -1018 68/push _test-input-stream/imm32 -1019 # . . call -1020 e8/call clear-stream/disp32 -1021 # . . discard args -1022 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1023 # . clear-stream(_test-input-buffered-file+4) -1024 # . . push args -1025 b8/copy-to-EAX _test-input-buffered-file/imm32 -1026 05/add-to-EAX 4/imm32 -1027 50/push-EAX -1028 # . . call -1029 e8/call clear-stream/disp32 -1030 # . . discard args -1031 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1032 # . clear-stream(_test-output-stream) -1033 # . . push args -1034 68/push _test-output-stream/imm32 -1035 # . . call -1036 e8/call clear-stream/disp32 -1037 # . . discard args -1038 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1039 # . clear-stream(_test-output-buffered-file+4) -1040 # . . push args -1041 b8/copy-to-EAX _test-output-buffered-file/imm32 -1042 05/add-to-EAX 4/imm32 -1043 50/push-EAX -1044 # . . call -1045 e8/call clear-stream/disp32 -1046 # . . discard args -1047 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1048 # initialize input -1049 # . write(_test-input-stream, "ab *(ecx + edx<<3 - 4)") -1050 # . . push args -1051 68/push "ab *(ecx + edx<<3 - 4)"/imm32 -1052 68/push _test-input-stream/imm32 -1053 # . . call -1054 e8/call write/disp32 -1055 # . . discard args -1056 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1057 # convert(_test-input-buffered-file, _test-output-buffered-file) -1058 # . . push args -1059 68/push _test-output-buffered-file/imm32 -1060 68/push _test-input-buffered-file/imm32 -1061 # . . call -1062 e8/call convert/disp32 -1063 # . . discard args -1064 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1065 # check that the line just passed through -1066 # . flush(_test-output-buffered-file) -1067 # . . push args -1068 68/push _test-output-buffered-file/imm32 -1069 # . . call -1070 e8/call flush/disp32 -1071 # . . discard args -1072 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1073 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- -1099 # . check-stream-equal(_test-output-stream, "ab 2/mod/*+disp32 4/rm32/sib 1/base 2/index 3/scale -4/disp32 \n", msg) -1100 # . . push args -1101 68/push "F - test-convert-indirect-mode-with-sib-byte-negative-displacement"/imm32 -1102 68/push "ab 2/mod/*+disp32 4/rm32/sib 0x00000001/base 0x00000002/index 0x00000003/scale 0xfffffffc/disp32 \n"/imm32 -1103 68/push _test-output-stream/imm32 -1104 # . . call -1105 e8/call check-stream-equal/disp32 -1106 # . . discard args -1107 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1108 # . epilog -1109 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1110 5d/pop-to-EBP -1111 c3/return -1112 -1113 # beware: modifies 'word' -1114 emit-direct-mode: # word : (address slice), out : (address buffered-file) -1115 # . prolog -1116 55/push-EBP -1117 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1118 # . save registers -1119 50/push-EAX -1120 # ++word->start -1121 # . EAX = word -1122 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 8/disp8 . # copy *(EBP+8) to EAX -1123 # . ++(*EAX) -1124 ff 0/subop/increment 0/mod/indirect 0/rm32/EAX . . . . . . # increment *EAX -1125 # reg-num/EAX = get-slice(Registers, word, row-size=8) -1126 # . . push args -1127 68/push "Registers"/imm32 -1128 68/push 8/imm32/row-size -1129 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -1130 68/push Registers/imm32 -1131 # . . call -1132 e8/call get-slice/disp32 -1133 # . . discard args -1134 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -1135 # write-buffered(out, "3/mod/direct ") -1136 # . . push args -1137 68/push "3/mod/direct "/imm32 -1138 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -1139 # . . call -1140 e8/call write-buffered/disp32 -1141 # . . discard args -1142 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1143 # print-int32-buffered(out, *EAX) -1144 # . . push args -1145 ff 6/subop/push 0/mod/indirect 0/rm32/EAX . . . . . . # push *EAX -1146 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -1147 # . . call -1148 e8/call print-int32-buffered/disp32 -1149 # . . discard args -1150 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1151 # write-buffered(out, "/rm32") -1152 # . . push args -1153 68/push "/rm32"/imm32 -1154 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -1155 # . . call -1156 e8/call write-buffered/disp32 -1157 # . . discard args -1158 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1159 $emit-direct-mode:end: -1160 # . restore registers -1161 58/pop-to-EAX -1162 # . epilog -1163 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1164 5d/pop-to-EBP -1165 c3/return -1166 -1167 test-emit-direct-mode: -1168 # . prolog -1169 55/push-EBP -1170 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1171 # setup -1172 # . clear-stream(_test-output-stream) -1173 # . . push args -1174 68/push _test-output-stream/imm32 -1175 # . . call -1176 e8/call clear-stream/disp32 -1177 # . . discard args -1178 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1179 # . clear-stream(_test-output-buffered-file+4) -1180 # . . push args -1181 b8/copy-to-EAX _test-output-buffered-file/imm32 -1182 05/add-to-EAX 4/imm32 -1183 50/push-EAX -1184 # . . call -1185 e8/call clear-stream/disp32 -1186 # . . discard args -1187 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1188 # var slice/ECX = "%eax" -1189 b8/copy-to-EAX "%eax"/imm32 -1190 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -1191 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 -1192 05/add-to-EAX 4/imm32 -1193 # . ECX = {EAX, ECX} -1194 51/push-ECX -1195 50/push-EAX -1196 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1197 # emit-direct-mode(str, _test-output-buffered-file) -1198 # . . push args -1199 68/push _test-output-buffered-file/imm32 -1200 51/push-ECX -1201 # . . call -1202 e8/call emit-direct-mode/disp32 -1203 # . . discard args -1204 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1205 # . flush(_test-output-buffered-file) -1206 # . . push args -1207 68/push _test-output-buffered-file/imm32 -1208 # . . call -1209 e8/call flush/disp32 -1210 # . . discard args -1211 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1212 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -1238 # check-stream-equal(_test-output-stream, "3/mod/direct 0/rm32", msg) -1239 # . . push args -1240 68/push "F - test-emit-direct-mode/0"/imm32 -1241 68/push "3/mod/direct 0x00000000/rm32"/imm32 -1242 68/push _test-output-stream/imm32 -1243 # . . call -1244 e8/call check-stream-equal/disp32 -1245 # . . discard args -1246 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1247 # . epilog -1248 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1249 5d/pop-to-EBP -1250 c3/return -1251 -1252 test-emit-direct-mode-2: -1253 # . prolog -1254 55/push-EBP -1255 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1256 # setup -1257 # . clear-stream(_test-output-stream) -1258 # . . push args -1259 68/push _test-output-stream/imm32 -1260 # . . call -1261 e8/call clear-stream/disp32 -1262 # . . discard args -1263 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1264 # . clear-stream(_test-output-buffered-file+4) -1265 # . . push args -1266 b8/copy-to-EAX _test-output-buffered-file/imm32 -1267 05/add-to-EAX 4/imm32 -1268 50/push-EAX -1269 # . . call -1270 e8/call clear-stream/disp32 -1271 # . . discard args -1272 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1273 # var slice/ECX = "%edi" -1274 b8/copy-to-EAX "%edi"/imm32 -1275 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -1276 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 -1277 05/add-to-EAX 4/imm32 -1278 # . ECX = {EAX, ECX} -1279 51/push-ECX -1280 50/push-EAX -1281 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1282 # emit-direct-mode(str/ECX, _test-output-buffered-file) -1283 # . . push args -1284 68/push _test-output-buffered-file/imm32 -1285 51/push-ECX -1286 # . . call -1287 e8/call emit-direct-mode/disp32 -1288 # . . discard args -1289 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1290 # . flush(_test-output-buffered-file) -1291 # . . push args -1292 68/push _test-output-buffered-file/imm32 -1293 # . . call -1294 e8/call flush/disp32 -1295 # . . discard args -1296 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1297 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -1323 # check-stream-equal(_test-output-stream, "3/mod/direct 7/rm32", msg) -1324 # . . push args -1325 68/push "F - test-emit-direct-mode/1"/imm32 -1326 68/push "3/mod/direct 0x00000007/rm32"/imm32 -1327 68/push _test-output-stream/imm32 -1328 # . . call -1329 e8/call check-stream-equal/disp32 -1330 # . . discard args -1331 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1332 # . epilog -1333 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1334 5d/pop-to-EBP -1335 c3/return -1336 -1337 # (re)compute the bounds of the next word or parenthetical expression in the line -1338 # return empty string on reaching end of file -1339 # -1340 # error messages considered: -1341 # * ... -> error: no space after '*' -1342 # *(... -> error: *(...) expression must be all on a single line -1343 next-word-or-expression: # line : (address stream byte), out : (address slice) -1344 # . prolog -1345 55/push-EBP -1346 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1347 # . save registers -1348 50/push-EAX -1349 51/push-ECX -1350 56/push-ESI -1351 57/push-EDI -1352 # ESI = line -1353 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI -1354 # EDI = out -1355 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI -1356 # skip-chars-matching(line, ' ') -1357 # . . push args -1358 68/push 0x20/imm32/space -1359 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -1360 # . . call -1361 e8/call skip-chars-matching/disp32 -1362 # . . discard args -1363 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1364 $next-word-or-expression:check0: -1365 # if (line->read >= line->write) clear out and return -1366 # . EAX = line->read -1367 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy *(ESI+4) to EAX -1368 # . if (EAX < line->write) goto next check -1369 3b/compare 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # compare EAX with *ESI -1370 7c/jump-if-lesser $next-word-or-expression:check-for-comment/disp8 -1371 # . return out = {0, 0} -1372 c7 0/subop/copy 0/mod/direct 7/rm32/EDI . . . . . 0/imm32 # copy to *EDI -1373 c7 0/subop/copy 1/mod/*+disp8 7/rm32/EDI . . . . 4/disp8 0/imm32 # copy to *(EDI+4) -1374 eb/jump $next-word-or-expression:end/disp8 -1375 $next-word-or-expression:check-for-comment: -1376 # out->start = &line->data[line->read] -1377 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX -1378 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 -1379 89/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to *EDI -1380 # if (line->data[line->read] != '#') goto next check -1381 # . EAX = line->data[line->read] -1382 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -1383 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 -1384 # . compare -1385 3d/compare-EAX-and 0x23/imm32/pound -1386 75/jump-if-not-equal $next-word-or-expression:check-for-paren/disp8 -1387 $next-word-or-expression:comment: -1388 # out->end = &line->data[line->write] -1389 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX -1390 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 -1391 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDI+4) -1392 # line->read = line->write # skip rest of line -1393 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX -1394 89/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(ESI+4) -1395 # return -1396 eb/jump $next-word-or-expression:end/disp8 -1397 $next-word-or-expression:check-for-paren: -1398 # if (line->data[line->read] != '*') goto next check -1399 # . EAX = line->data[line->read] -1400 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -1401 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 -1402 # . compare -1403 3d/compare-EAX-and 0x2a/imm32/asterisk -1404 75/jump-if-not-equal $next-word-or-expression:regular-word/disp8 -1405 # if (line->data[line->read] == ' ') goto error1 -1406 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 -1407 # . compare -1408 3d/compare-EAX-and 0x20/imm32/space -1409 74/jump-if-equal $next-word-or-expression:error1/disp8 -1410 # if (line->data[line->read] != '(') goto regular word -1411 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 -1412 # . compare -1413 3d/compare-EAX-and 0x28/imm32/open-paren -1414 75/jump-if-not-equal $next-word-or-expression:regular-word/disp8 -1415 $next-word-or-expression:paren: -1416 # skip-until-close-paren(line) -1417 # . . push args -1418 56/push-ESI -1419 # . . call -1420 e8/call skip-until-close-paren/disp32 -1421 # . . discard args -1422 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1423 # if (line->data[line->read] != ')') goto error2 -1424 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX -1425 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 -1426 # . compare -1427 3d/compare-EAX-and 0x29/imm32/close-paren -1428 75/jump-if-not-equal $next-word-or-expression:error2/disp8 -1429 # skip ')' -1430 ff 0/subop/increment 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # increment *(ESI+4) -1431 # fall through -1432 $next-word-or-expression:regular-word: -1433 # skip-chars-not-matching-whitespace(line) # including trailing newline -1434 # . . push args -1435 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -1436 # . . call -1437 e8/call skip-chars-not-matching-whitespace/disp32 -1438 # . . discard args -1439 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1440 # out->end = &line->data[line->read] -1441 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX -1442 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 -1443 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDI+4) -1444 $next-word-or-expression:end: -1445 # . restore registers -1446 5f/pop-to-EDI -1447 5e/pop-to-ESI -1448 59/pop-to-ECX -1449 58/pop-to-EAX -1450 # . epilog -1451 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1452 5d/pop-to-EBP -1453 c3/return -1454 -1455 $next-word-or-expression:error1: -1456 # print(stderr, "error: no space allowed after '*' in '" line "'") -1457 # . write-buffered(Stderr, "error: no space allowed after '*' in '") -1458 # . . push args -1459 68/push "error: no space allowed after '*' in '"/imm32 -1460 68/push Stderr/imm32 -1461 # . . call -1462 e8/call write-buffered/disp32 -1463 # . . discard args -1464 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1465 # . write-stream-data(Stderr, line) -1466 # . . push args -1467 56/push-ESI -1468 68/push Stderr/imm32 -1469 # . . call -1470 e8/call write-stream-data/disp32 -1471 # . . discard args -1472 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1473 # . write-buffered(Stderr, "'") -1474 # . . push args -1475 68/push "'"/imm32 -1476 68/push Stderr/imm32 -1477 # . . call -1478 e8/call write-buffered/disp32 -1479 # . . discard args -1480 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1481 # . flush(Stderr) -1482 # . . push args -1483 68/push Stderr/imm32 -1484 # . . call -1485 e8/call flush/disp32 -1486 # . . discard args -1487 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1488 # . syscall(exit, 1) -1489 bb/copy-to-EBX 1/imm32 -1490 b8/copy-to-EAX 1/imm32/exit -1491 cd/syscall 0x80/imm8 -1492 # never gets here -1493 -1494 $next-word-or-expression:error2: -1495 # print(stderr, "error: no space allowed after '*' in '" line "'") -1496 # . write-buffered(Stderr, "error: *(...) expression must be all on a single line in '") -1497 # . . push args -1498 68/push "error: *(...) expression must be all on a single line in '"/imm32 -1499 68/push Stderr/imm32 -1500 # . . call -1501 e8/call write-buffered/disp32 -1502 # . . discard args -1503 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1504 # . write-stream-data(Stderr, line) -1505 # . . push args -1506 56/push-ESI -1507 68/push Stderr/imm32 -1508 # . . call -1509 e8/call write-stream-data/disp32 -1510 # . . discard args -1511 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1512 # . write-buffered(Stderr, "'") -1513 # . . push args -1514 68/push "'"/imm32 -1515 68/push Stderr/imm32 -1516 # . . call -1517 e8/call write-buffered/disp32 -1518 # . . discard args -1519 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1520 # . flush(Stderr) -1521 # . . push args -1522 68/push Stderr/imm32 -1523 # . . call -1524 e8/call flush/disp32 -1525 # . . discard args -1526 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1527 # . syscall(exit, 1) -1528 bb/copy-to-EBX 1/imm32 -1529 b8/copy-to-EAX 1/imm32/exit -1530 cd/syscall 0x80/imm8 -1531 # never gets here -1532 -1533 test-next-word-or-expression: -1534 # . prolog -1535 55/push-EBP -1536 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1537 # setup -1538 # . clear-stream(_test-input-stream) -1539 # . . push args -1540 68/push _test-input-stream/imm32 -1541 # . . call -1542 e8/call clear-stream/disp32 -1543 # . . discard args -1544 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1545 # var slice/ECX = {0, 0} -1546 68/push 0/imm32/end -1547 68/push 0/imm32/start -1548 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1549 # write(_test-input-stream, " ab") -1550 # . . push args -1551 68/push " ab"/imm32 -1552 68/push _test-input-stream/imm32 -1553 # . . call -1554 e8/call write/disp32 -1555 # . . discard args -1556 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1557 # next-word-or-expression(_test-input-stream, slice) -1558 # . . push args -1559 51/push-ECX -1560 68/push _test-input-stream/imm32 -1561 # . . call -1562 e8/call next-word-or-expression/disp32 -1563 # . . discard args -1564 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1565 # check-ints-equal(_test-input-stream->read, 4, msg) -1566 # . . push args -1567 68/push "F - test-next-word-or-expression/updates-stream-read-correctly"/imm32 -1568 68/push 4/imm32 -1569 b8/copy-to-EAX _test-input-stream/imm32 -1570 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) -1571 # . . call -1572 e8/call check-ints-equal/disp32 -1573 # . . discard args -1574 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1575 # check-ints-equal(slice->start - _test-input-stream->data, 2, msg) -1576 # . check-ints-equal(slice->start - _test-input-stream, 14, msg) -1577 # . . push args -1578 68/push "F - test-next-word-or-expression: start"/imm32 -1579 68/push 0xe/imm32 -1580 # . . push slice->start - _test-input-stream -1581 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX -1582 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX -1583 50/push-EAX -1584 # . . call -1585 e8/call check-ints-equal/disp32 -1586 # . . discard args -1587 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1588 # check-ints-equal(slice->end - _test-input-stream->data, 4, msg) -1589 # . check-ints-equal(slice->end - _test-input-stream, 16, msg) -1590 # . . push args -1591 68/push "F - test-next-word-or-expression: end"/imm32 -1592 68/push 0x10/imm32 -1593 # . . push slice->end - _test-input-stream -1594 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX -1595 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX -1596 50/push-EAX -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 # . epilog -1602 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1603 5d/pop-to-EBP -1604 c3/return -1605 -1606 test-next-word-or-expression-returns-whole-comment: -1607 # . prolog -1608 55/push-EBP -1609 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1610 # setup -1611 # . clear-stream(_test-input-stream) -1612 # . . push args -1613 68/push _test-input-stream/imm32 -1614 # . . call -1615 e8/call clear-stream/disp32 -1616 # . . discard args -1617 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1618 # var slice/ECX = {0, 0} -1619 68/push 0/imm32/end -1620 68/push 0/imm32/start -1621 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1622 # write(_test-input-stream, " # a") -1623 # . . push args -1624 68/push " # a"/imm32 -1625 68/push _test-input-stream/imm32 -1626 # . . call -1627 e8/call write/disp32 -1628 # . . discard args -1629 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1630 # next-word-or-expression(_test-input-stream, slice) -1631 # . . push args -1632 51/push-ECX -1633 68/push _test-input-stream/imm32 -1634 # . . call -1635 e8/call next-word-or-expression/disp32 -1636 # . . discard args -1637 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1638 # check-ints-equal(_test-input-stream->read, 5, msg) -1639 # . . push args -1640 68/push "F - test-next-word-or-expression-returns-whole-comment/updates-stream-read-correctly"/imm32 -1641 68/push 5/imm32 -1642 b8/copy-to-EAX _test-input-stream/imm32 -1643 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) -1644 # . . call -1645 e8/call check-ints-equal/disp32 -1646 # . . discard args -1647 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1648 # check-ints-equal(slice->start - _test-input-stream->data, 2, msg) -1649 # . check-ints-equal(slice->start - _test-input-stream, 14, msg) -1650 # . . push args -1651 68/push "F - test-next-word-or-expression-returns-whole-comment: start"/imm32 -1652 68/push 0xe/imm32 -1653 # . . push slice->start - _test-input-stream -1654 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX -1655 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX -1656 50/push-EAX -1657 # . . call -1658 e8/call check-ints-equal/disp32 -1659 # . . discard args -1660 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1661 # check-ints-equal(slice->end - _test-input-stream->data, 5, msg) -1662 # . check-ints-equal(slice->end - _test-input-stream, 17, msg) -1663 # . . push args -1664 68/push "F - test-next-word-or-expression-returns-whole-comment: end"/imm32 -1665 68/push 0x11/imm32 -1666 # . . push slice->end - _test-input-stream -1667 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX -1668 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX -1669 50/push-EAX -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 # . epilog -1675 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1676 5d/pop-to-EBP -1677 c3/return -1678 -1679 test-next-word-or-expression-returns-empty-expression-on-eof: -1680 # . prolog -1681 55/push-EBP -1682 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1683 # setup -1684 # . clear-stream(_test-input-stream) -1685 # . . push args -1686 68/push _test-input-stream/imm32 -1687 # . . call -1688 e8/call clear-stream/disp32 -1689 # . . discard args -1690 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1691 # var slice/ECX = {0, 0} -1692 68/push 0/imm32/end -1693 68/push 0/imm32/start -1694 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1695 # write nothing to _test-input-stream -1696 # next-word-or-expression(_test-input-stream, slice) -1697 # . . push args -1698 51/push-ECX -1699 68/push _test-input-stream/imm32 -1700 # . . call -1701 e8/call next-word-or-expression/disp32 -1702 # . . discard args -1703 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1704 # check-ints-equal(slice->end - slice->start, 0, msg) -1705 # . . push args -1706 68/push "F - test-next-word-or-expression-returns-empty-expression-on-eof"/imm32 -1707 68/push 0/imm32 -1708 # . . push slice->end - slice->start -1709 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX -1710 2b/subtract 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # subtract *ECX from EAX -1711 50/push-EAX -1712 # . . call -1713 e8/call check-ints-equal/disp32 -1714 # . . discard args -1715 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1716 # . epilog -1717 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1718 5d/pop-to-EBP -1719 c3/return -1720 -1721 test-next-word-or-expression-returns-whole-expression: -1722 # . prolog -1723 55/push-EBP -1724 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1725 # setup -1726 # . clear-stream(_test-input-stream) -1727 # . . push args -1728 68/push _test-input-stream/imm32 -1729 # . . call -1730 e8/call clear-stream/disp32 -1731 # . . discard args -1732 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1733 # var slice/ECX = {0, 0} -1734 68/push 0/imm32/end -1735 68/push 0/imm32/start -1736 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1737 # write(_test-input-stream, " *(a b)/imm32 ") -1738 # . . push args -1739 68/push " *(a b)/imm32 "/imm32 -1740 68/push _test-input-stream/imm32 -1741 # . . call -1742 e8/call write/disp32 -1743 # . . discard args -1744 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1745 # next-word-or-expression(_test-input-stream, slice) -1746 # . . push args -1747 51/push-ECX -1748 68/push _test-input-stream/imm32 -1749 # . . call -1750 e8/call next-word-or-expression/disp32 -1751 # . . discard args -1752 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1753 # check-ints-equal(slice->start - _test-input-stream->data, 1, msg) -1754 # . check-ints-equal(slice->start - _test-input-stream, 13, msg) -1755 # . . push args -1756 68/push "F - test-next-word-or-expression-returns-whole-expression: start"/imm32 -1757 68/push 0xd/imm32 -1758 # . . push slice->start - _test-input-stream -1759 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX -1760 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX -1761 50/push-EAX + 32 # Addition isn't commutative here. Template must always be (base+index<<scale+disp), + 33 # though some components are optional as described above. + 34 # + 35 # No metadata allowed inside '*(...)'. + 36 # Whitespace inside '*(...)' is ok. But not immediately after the '*' or '%'. + 37 + 38 == code + 39 # instruction effective address register displacement immediate + 40 # . op subop mod rm32 base index scale r32 + 41 # . 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 + 42 + 43 Entry: # run tests if necessary, convert stdin if not + 44 # initialize heap + 45 # . Heap = new-segment(Heap-size) + 46 # . . push args + 47 68/push Heap/imm32 + 48 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Heap-size/disp32 # push *Heap-size + 49 # . . call + 50 e8/call new-segment/disp32 + 51 # . . discard args + 52 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 53 + 54 # run tests if necessary, convert stdin if not + 55 # . prolog + 56 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 57 # - if argc > 1 and argv[1] == "test", then return run_tests() + 58 # . argc > 1 + 59 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP + 60 7e/jump-if-lesser-or-equal $run-main/disp8 + 61 # . argv[1] == "test" + 62 # . . push args + 63 68/push "test"/imm32 + 64 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 65 # . . call + 66 e8/call kernel-string-equal?/disp32 + 67 # . . discard args + 68 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 69 # . check result + 70 3d/compare-EAX-and 1/imm32 + 71 75/jump-if-not-equal $run-main/disp8 + 72 # . run-tests() + 73 e8/call run-tests/disp32 + 74 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX + 75 eb/jump $main:end/disp8 + 76 $run-main: + 77 # - otherwise convert stdin + 78 # convert(Stdin, Stdout) + 79 # . . push args + 80 68/push Stdout/imm32 + 81 68/push Stdin/imm32 + 82 # . . call + 83 e8/call convert/disp32 + 84 # . . discard args + 85 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x8/imm32 # add to ESP + 86 # . syscall(exit, 0) + 87 bb/copy-to-EBX 0/imm32 + 88 $main:end: + 89 b8/copy-to-EAX 1/imm32/exit + 90 cd/syscall 0x80/imm8 + 91 + 92 # error messages considered: + 93 # *x + 34 -> error: base+disp addressing must be within '()' + 94 convert: # in : (address buffered-file), out : (address buffered-file) -> <void> + 95 # pseudocode: + 96 # var line = new-stream(512, 1) + 97 # while true + 98 # clear-stream(line) + 99 # read-line-buffered(in, line) + 100 # if (line->write == 0) break # end of file + 101 # while true + 102 # var word-slice = next-word-or-expression(line) + 103 # if slice-empty?(word-slice) # end of line + 104 # break + 105 # if slice-starts-with?(word-slice, "#") # comment + 106 # continue + 107 # if slice-starts-with?(word-slice, '%') # direct mode + 108 # emit-direct-mode(word-slice, out) + 109 # else if slice-starts-with?(word-slice, '*') # indirect mode + 110 # base, index, scale, disp = parse-effective-address(word-slice) + 111 # emit-indirect-mode(out, base, index, scale, disp) + 112 # else if slice-starts-with?(word-slice, '+') + 113 # abort("'+' only permitted within '*(...)'") + 114 # else + 115 # write-slice-buffered(out, word-slice) + 116 # write(out, " ") + 117 # write(out, "\n") + 118 # flush(out) + 119 # + 120 # . prolog + 121 55/push-EBP + 122 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 123 # . save registers + 124 50/push-EAX + 125 51/push-ECX + 126 52/push-EDX + 127 53/push-EBX + 128 # var line/ECX : (address stream byte) = stream(512) + 129 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0x200/imm32 # subtract from ESP + 130 68/push 0x200/imm32/length + 131 68/push 0/imm32/read + 132 68/push 0/imm32/write + 133 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 134 # var word-slice/EDX = {0, 0} + 135 68/push 0/imm32/end + 136 68/push 0/imm32/start + 137 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX + 138 $convert:line-loop: + 139 # clear-stream(line) + 140 # . . push args + 141 51/push-ECX + 142 # . . call + 143 e8/call clear-stream/disp32 + 144 # . . discard args + 145 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 146 # read-line-buffered(in, line) + 147 # . . push args + 148 51/push-ECX + 149 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 150 # . . call + 151 e8/call read-line-buffered/disp32 + 152 # . . discard args + 153 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 154 $convert:check0: + 155 # if (line->write == 0) break + 156 81 7/subop/compare 0/mod/indirect 1/rm32/ECX . . . . . 0/imm32 # compare *ECX + 157 0f 84/jump-if-equal $convert:break/disp32 + 158 $convert:word-loop: + 159 # next-word-or-expression(line, word-slice) + 160 # . . push args + 161 52/push-EDX + 162 51/push-ECX + 163 # . . call + 164 e8/call next-word-or-expression/disp32 + 165 # . . discard args + 166 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 167 $convert:check1: + 168 # if (slice-empty?(word-slice)) break + 169 # . EAX = slice-empty?(word-slice) + 170 # . . push args + 171 52/push-EDX + 172 # . . call + 173 e8/call slice-empty?/disp32 + 174 # . . discard args + 175 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 176 # . if (EAX != 0) break + 177 3d/compare-EAX-and 0/imm32 + 178 0f 85/jump-if-not-equal $convert:next-line/disp32 + 179 $convert:check-for-comment: + 180 # if (slice-starts-with?(word-slice, "#")) continue + 181 # . start/EBX = word-slice->start + 182 8b/copy 0/mod/indirect 2/rm32/EDX . . . 3/r32/EBX . . # copy *EDX to EBX + 183 # . c/EAX = *start + 184 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX + 185 8a/copy-byte 0/mod/indirect 3/rm32/EBX . . . 0/r32/AL . . # copy byte at *EBX to AL + 186 # . if (EAX == '#') continue + 187 3d/compare-EAX-and 0x23/imm32/hash + 188 74/jump-if-equal $convert:word-loop/disp8 + 189 $convert:check-for-direct-mode: + 190 # if (!slice-starts-with?(word-slice, "%")) goto next check + 191 3d/compare-EAX-and 0x25/imm32/percent + 192 75/jump-if-not-equal $convert:check-for-indirect-mode/disp8 + 193 $convert:direct-mode: + 194 +-- 46 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- + 240 # emit-direct-mode(word-slice, out) + 241 # . . push args + 242 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 243 52/push-EDX + 244 # . . call + 245 e8/call emit-direct-mode/disp32 + 246 # . . discard args + 247 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 248 # continue + 249 e9/jump $convert:next-word/disp32 + 250 $convert:check-for-indirect-mode: + 251 # if (!slice-starts-with?(word-slice, "*")) goto next check + 252 3d/compare-EAX-and 0x2a/imm32/asterisk + 253 75/jump-if-not-equal $convert:check-for-invalid-addition/disp8 + 254 $convert:indirect-mode: + 255 # spill registers + 256 50/push-EAX + 257 51/push-ECX + 258 52/push-EDX + 259 53/push-EBX + 260 # base/EAX, index/ECX, scale/EDX, disp/EBX = parse-effective-address(word-slice) + 261 # . . push args + 262 52/push-EDX + 263 # . . call + 264 e8/call parse-effective-address/disp32 + 265 # . . discard args + 266 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 267 # emit-indirect-mode(out, base, index, scale, disp) + 268 # . . push args + 269 53/push-EBX + 270 52/push-EDX + 271 51/push-ECX + 272 50/push-EAX + 273 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 274 # . . call + 275 e8/call emit-indirect-mode/disp32 + 276 # . . discard args + 277 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP + 278 # restore registers + 279 5b/pop-to-EBX + 280 5a/pop-to-EDX + 281 59/pop-to-ECX + 282 58/pop-to-EAX + 283 # continue + 284 e9/jump $convert:next-word/disp32 + 285 $convert:check-for-invalid-addition: + 286 # if (slice-starts-with?(word-slice, "+")) goto error1 + 287 3d/compare-EAX-and 0x2b/imm32/plus + 288 74/jump-if-equal $convert:error1/disp8 + 289 $convert:check-for-invalid-left-shift: + 290 # if (slice-starts-with?(word-slice, "<")) goto error1 + 291 3d/compare-EAX-and 0x3c/imm32/less-than + 292 74/jump-if-equal $convert:error1/disp8 + 293 $convert:regular-word: + 294 # write-slice-buffered(out, word-slice) + 295 # . . push args + 296 52/push-EDX + 297 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 298 # . . call + 299 e8/call write-slice-buffered/disp32 + 300 # . . discard args + 301 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 302 # fall through + 303 $convert:next-word: + 304 # write-buffered(out, " ") + 305 # . . push args + 306 68/push " "/imm32 + 307 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 308 # . . call + 309 e8/call write-buffered/disp32 + 310 # . . discard args + 311 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 312 # loop + 313 e9/jump $convert:word-loop/disp32 + 314 $convert:next-line: + 315 # write-buffered(out, "\n") + 316 # . . push args + 317 68/push Newline/imm32 + 318 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 319 # . . call + 320 e8/call write-buffered/disp32 + 321 # . . discard args + 322 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 323 # loop + 324 e9/jump $convert:line-loop/disp32 + 325 $convert:break: + 326 # flush(out) + 327 # . . push args + 328 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 329 # . . call + 330 e8/call flush/disp32 + 331 # . . discard args + 332 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 333 $convert:end: + 334 # . reclaim locals + 335 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x214/imm32 # add to ESP + 336 # . restore registers + 337 5b/pop-to-EBX + 338 5a/pop-to-EDX + 339 59/pop-to-ECX + 340 58/pop-to-EAX + 341 # . epilog + 342 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 343 5d/pop-to-EBP + 344 c3/return + 345 + 346 $convert:error1: + 347 # print(stderr, "error: '" EAX "' only permitted within '*(...)' in '" line "'") + 348 # . write-buffered(Stderr, "error: '") + 349 # . . push args + 350 68/push "error: '"/imm32 + 351 68/push Stderr/imm32 + 352 # . . call + 353 e8/call write-buffered/disp32 + 354 # . . discard args + 355 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 356 # . write-byte-buffered(Stderr, EAX) + 357 # . . push args + 358 50/push-EAX + 359 68/push Stderr/imm32 + 360 # . . call + 361 e8/call write-byte-buffered/disp32 + 362 # . . discard args + 363 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 364 # . write-buffered(Stderr, "' only permitted within '*(...)' in '") + 365 # . . push args + 366 68/push "' only permitted within '*(...)' in '"/imm32 + 367 68/push Stderr/imm32 + 368 # . . call + 369 e8/call write-buffered/disp32 + 370 # . . discard args + 371 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 372 # . write-stream-data(Stderr, line) + 373 # . . push args + 374 51/push-ECX + 375 68/push Stderr/imm32 + 376 # . . call + 377 e8/call write-stream-data/disp32 + 378 # . . discard args + 379 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 380 # . write-buffered(Stderr, "'") + 381 # . . push args + 382 68/push "'"/imm32 + 383 68/push Stderr/imm32 + 384 # . . call + 385 e8/call write-buffered/disp32 + 386 # . . discard args + 387 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 388 # . flush(Stderr) + 389 # . . push args + 390 68/push Stderr/imm32 + 391 # . . call + 392 e8/call flush/disp32 + 393 # . . discard args + 394 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 395 # . syscall(exit, 1) + 396 bb/copy-to-EBX 1/imm32 + 397 b8/copy-to-EAX 1/imm32/exit + 398 cd/syscall 0x80/imm8 + 399 # never gets here + 400 + 401 test-convert-passes-most-words-through: + 402 # . prolog + 403 55/push-EBP + 404 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 405 # setup + 406 # . clear-stream(_test-input-stream) + 407 # . . push args + 408 68/push _test-input-stream/imm32 + 409 # . . call + 410 e8/call clear-stream/disp32 + 411 # . . discard args + 412 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 413 # . clear-stream(_test-input-buffered-file+4) + 414 # . . push args + 415 b8/copy-to-EAX _test-input-buffered-file/imm32 + 416 05/add-to-EAX 4/imm32 + 417 50/push-EAX + 418 # . . call + 419 e8/call clear-stream/disp32 + 420 # . . discard args + 421 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 422 # . clear-stream(_test-output-stream) + 423 # . . push args + 424 68/push _test-output-stream/imm32 + 425 # . . call + 426 e8/call clear-stream/disp32 + 427 # . . discard args + 428 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 429 # . clear-stream(_test-output-buffered-file+4) + 430 # . . push args + 431 b8/copy-to-EAX _test-output-buffered-file/imm32 + 432 05/add-to-EAX 4/imm32 + 433 50/push-EAX + 434 # . . call + 435 e8/call clear-stream/disp32 + 436 # . . discard args + 437 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 438 # initialize input + 439 # . write(_test-input-stream, "== abcd 0x1") + 440 # . . push args + 441 68/push "== abcd 0x1"/imm32 + 442 68/push _test-input-stream/imm32 + 443 # . . call + 444 e8/call write/disp32 + 445 # . . discard args + 446 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 447 # convert(_test-input-buffered-file, _test-output-buffered-file) + 448 # . . push args + 449 68/push _test-output-buffered-file/imm32 + 450 68/push _test-input-buffered-file/imm32 + 451 # . . call + 452 e8/call convert/disp32 + 453 # . . discard args + 454 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 455 # check that the line just passed through + 456 # . flush(_test-output-buffered-file) + 457 # . . push args + 458 68/push _test-output-buffered-file/imm32 + 459 # . . call + 460 e8/call flush/disp32 + 461 # . . discard args + 462 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 463 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 489 # . check-stream-equal(_test-output-stream, "== abcd 0x1 \n", msg) + 490 # . . push args + 491 68/push "F - test-convert-passes-most-words-through"/imm32 + 492 68/push "== abcd 0x1 \n"/imm32 + 493 68/push _test-output-stream/imm32 + 494 # . . call + 495 e8/call check-stream-equal/disp32 + 496 # . . discard args + 497 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 498 # . epilog + 499 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 500 5d/pop-to-EBP + 501 c3/return + 502 + 503 test-convert-direct-mode: + 504 # . prolog + 505 55/push-EBP + 506 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 507 # setup + 508 # . clear-stream(_test-input-stream) + 509 # . . push args + 510 68/push _test-input-stream/imm32 + 511 # . . call + 512 e8/call clear-stream/disp32 + 513 # . . discard args + 514 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 515 # . clear-stream(_test-input-buffered-file+4) + 516 # . . push args + 517 b8/copy-to-EAX _test-input-buffered-file/imm32 + 518 05/add-to-EAX 4/imm32 + 519 50/push-EAX + 520 # . . call + 521 e8/call clear-stream/disp32 + 522 # . . discard args + 523 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 524 # . clear-stream(_test-output-stream) + 525 # . . push args + 526 68/push _test-output-stream/imm32 + 527 # . . call + 528 e8/call clear-stream/disp32 + 529 # . . discard args + 530 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 531 # . clear-stream(_test-output-buffered-file+4) + 532 # . . push args + 533 b8/copy-to-EAX _test-output-buffered-file/imm32 + 534 05/add-to-EAX 4/imm32 + 535 50/push-EAX + 536 # . . call + 537 e8/call clear-stream/disp32 + 538 # . . discard args + 539 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 540 # initialize input + 541 # . write(_test-input-stream, "ab %ecx") + 542 # . . push args + 543 68/push "ab %ecx"/imm32 + 544 68/push _test-input-stream/imm32 + 545 # . . call + 546 e8/call write/disp32 + 547 # . . discard args + 548 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 549 # convert(_test-input-buffered-file, _test-output-buffered-file) + 550 # . . push args + 551 68/push _test-output-buffered-file/imm32 + 552 68/push _test-input-buffered-file/imm32 + 553 # . . call + 554 e8/call convert/disp32 + 555 # . . discard args + 556 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 557 # check that the line just passed through + 558 # . flush(_test-output-buffered-file) + 559 # . . push args + 560 68/push _test-output-buffered-file/imm32 + 561 # . . call + 562 e8/call flush/disp32 + 563 # . . discard args + 564 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 565 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 591 # . check-stream-equal(_test-output-stream, "ab 3/mod/direct 0x00000001/rm32 \n", msg) + 592 # . . push args + 593 68/push "F - test-convert-direct-mode"/imm32 + 594 68/push "ab 3/mod/direct 0x00000001/rm32 \n"/imm32 + 595 68/push _test-output-stream/imm32 + 596 # . . call + 597 e8/call check-stream-equal/disp32 + 598 # . . discard args + 599 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 600 # . epilog + 601 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 602 5d/pop-to-EBP + 603 c3/return + 604 + 605 test-convert-register-indirect-mode: + 606 # . prolog + 607 55/push-EBP + 608 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 609 # setup + 610 # . clear-stream(_test-input-stream) + 611 # . . push args + 612 68/push _test-input-stream/imm32 + 613 # . . call + 614 e8/call clear-stream/disp32 + 615 # . . discard args + 616 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 617 # . clear-stream(_test-input-buffered-file+4) + 618 # . . push args + 619 b8/copy-to-EAX _test-input-buffered-file/imm32 + 620 05/add-to-EAX 4/imm32 + 621 50/push-EAX + 622 # . . call + 623 e8/call clear-stream/disp32 + 624 # . . discard args + 625 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 626 # . clear-stream(_test-output-stream) + 627 # . . push args + 628 68/push _test-output-stream/imm32 + 629 # . . call + 630 e8/call clear-stream/disp32 + 631 # . . discard args + 632 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 633 # . clear-stream(_test-output-buffered-file+4) + 634 # . . push args + 635 b8/copy-to-EAX _test-output-buffered-file/imm32 + 636 05/add-to-EAX 4/imm32 + 637 50/push-EAX + 638 # . . call + 639 e8/call clear-stream/disp32 + 640 # . . discard args + 641 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 642 # initialize input + 643 # . write(_test-input-stream, "ab *ecx") + 644 # . . push args + 645 68/push "ab *ecx"/imm32 + 646 68/push _test-input-stream/imm32 + 647 # . . call + 648 e8/call write/disp32 + 649 # . . discard args + 650 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 651 # convert(_test-input-buffered-file, _test-output-buffered-file) + 652 # . . push args + 653 68/push _test-output-buffered-file/imm32 + 654 68/push _test-input-buffered-file/imm32 + 655 # . . call + 656 e8/call convert/disp32 + 657 # . . discard args + 658 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 659 # check that the line just passed through + 660 # . flush(_test-output-buffered-file) + 661 # . . push args + 662 68/push _test-output-buffered-file/imm32 + 663 # . . call + 664 e8/call flush/disp32 + 665 # . . discard args + 666 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 667 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 693 # . check-stream-equal(_test-output-stream, "ab 0/mod/indirect 0x00000001/rm32 \n", msg) + 694 # . . push args + 695 68/push "F - test-convert-indirect-mode"/imm32 + 696 68/push "ab 0/mod/indirect 0x00000001/rm32 \n"/imm32 + 697 68/push _test-output-stream/imm32 + 698 # . . call + 699 e8/call check-stream-equal/disp32 + 700 # . . discard args + 701 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 702 # . epilog + 703 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 704 5d/pop-to-EBP + 705 c3/return + 706 + 707 test-convert-register-indirect-mode-without-displacement: + 708 # . prolog + 709 55/push-EBP + 710 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 711 # setup + 712 # . clear-stream(_test-input-stream) + 713 # . . push args + 714 68/push _test-input-stream/imm32 + 715 # . . call + 716 e8/call clear-stream/disp32 + 717 # . . discard args + 718 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 719 # . clear-stream(_test-input-buffered-file+4) + 720 # . . push args + 721 b8/copy-to-EAX _test-input-buffered-file/imm32 + 722 05/add-to-EAX 4/imm32 + 723 50/push-EAX + 724 # . . call + 725 e8/call clear-stream/disp32 + 726 # . . discard args + 727 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 728 # . clear-stream(_test-output-stream) + 729 # . . push args + 730 68/push _test-output-stream/imm32 + 731 # . . call + 732 e8/call clear-stream/disp32 + 733 # . . discard args + 734 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 735 # . clear-stream(_test-output-buffered-file+4) + 736 # . . push args + 737 b8/copy-to-EAX _test-output-buffered-file/imm32 + 738 05/add-to-EAX 4/imm32 + 739 50/push-EAX + 740 # . . call + 741 e8/call clear-stream/disp32 + 742 # . . discard args + 743 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 744 # initialize input + 745 # . write(_test-input-stream, "ab *(ecx)") + 746 # . . push args + 747 68/push "ab *(ecx)"/imm32 + 748 68/push _test-input-stream/imm32 + 749 # . . call + 750 e8/call write/disp32 + 751 # . . discard args + 752 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 753 # convert(_test-input-buffered-file, _test-output-buffered-file) + 754 # . . push args + 755 68/push _test-output-buffered-file/imm32 + 756 68/push _test-input-buffered-file/imm32 + 757 # . . call + 758 e8/call convert/disp32 + 759 # . . discard args + 760 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 761 # check that the line just passed through + 762 # . flush(_test-output-buffered-file) + 763 # . . push args + 764 68/push _test-output-buffered-file/imm32 + 765 # . . call + 766 e8/call flush/disp32 + 767 # . . discard args + 768 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 769 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 795 # . check-stream-equal(_test-output-stream, "ab 0/mod/indirect 1/rm32 \n", msg) + 796 # . . push args + 797 68/push "F - test-convert-indirect-mode-without-displacement"/imm32 + 798 68/push "ab 0/mod/indirect 0x00000001/rm32 \n"/imm32 + 799 68/push _test-output-stream/imm32 + 800 # . . call + 801 e8/call check-stream-equal/disp32 + 802 # . . discard args + 803 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 804 # . epilog + 805 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 806 5d/pop-to-EBP + 807 c3/return + 808 + 809 test-convert-register-indirect-mode-with-displacement: + 810 # . prolog + 811 55/push-EBP + 812 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 813 # setup + 814 # . clear-stream(_test-input-stream) + 815 # . . push args + 816 68/push _test-input-stream/imm32 + 817 # . . call + 818 e8/call clear-stream/disp32 + 819 # . . discard args + 820 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 821 # . clear-stream(_test-input-buffered-file+4) + 822 # . . push args + 823 b8/copy-to-EAX _test-input-buffered-file/imm32 + 824 05/add-to-EAX 4/imm32 + 825 50/push-EAX + 826 # . . call + 827 e8/call clear-stream/disp32 + 828 # . . discard args + 829 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 830 # . clear-stream(_test-output-stream) + 831 # . . push args + 832 68/push _test-output-stream/imm32 + 833 # . . call + 834 e8/call clear-stream/disp32 + 835 # . . discard args + 836 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 837 # . clear-stream(_test-output-buffered-file+4) + 838 # . . push args + 839 b8/copy-to-EAX _test-output-buffered-file/imm32 + 840 05/add-to-EAX 4/imm32 + 841 50/push-EAX + 842 # . . call + 843 e8/call clear-stream/disp32 + 844 # . . discard args + 845 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 846 # initialize input + 847 # . write(_test-input-stream, "ab *(ecx+4)") + 848 # . . push args + 849 68/push "ab *(ecx+4)"/imm32 + 850 68/push _test-input-stream/imm32 + 851 # . . call + 852 e8/call write/disp32 + 853 # . . discard args + 854 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 855 # convert(_test-input-buffered-file, _test-output-buffered-file) + 856 # . . push args + 857 68/push _test-output-buffered-file/imm32 + 858 68/push _test-input-buffered-file/imm32 + 859 # . . call + 860 e8/call convert/disp32 + 861 # . . discard args + 862 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 863 # check that the line just passed through + 864 # . flush(_test-output-buffered-file) + 865 # . . push args + 866 68/push _test-output-buffered-file/imm32 + 867 # . . call + 868 e8/call flush/disp32 + 869 # . . discard args + 870 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 871 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- + 897 # . check-stream-equal(_test-output-stream, "ab 2/mod/*+disp32 1/rm32 4/disp32 \n", msg) + 898 # . . push args + 899 68/push "F - test-convert-indirect-mode-with-displacement"/imm32 + 900 68/push "ab 2/mod/*+disp32 0x00000001/rm32 0x00000004/disp32 \n"/imm32 + 901 68/push _test-output-stream/imm32 + 902 # . . call + 903 e8/call check-stream-equal/disp32 + 904 # . . discard args + 905 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 906 # . epilog + 907 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 908 5d/pop-to-EBP + 909 c3/return + 910 + 911 # boss level + 912 test-convert-register-indirect-mode-with-sib-byte: + 913 # . prolog + 914 55/push-EBP + 915 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 916 # setup + 917 # . clear-stream(_test-input-stream) + 918 # . . push args + 919 68/push _test-input-stream/imm32 + 920 # . . call + 921 e8/call clear-stream/disp32 + 922 # . . discard args + 923 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 924 # . clear-stream(_test-input-buffered-file+4) + 925 # . . push args + 926 b8/copy-to-EAX _test-input-buffered-file/imm32 + 927 05/add-to-EAX 4/imm32 + 928 50/push-EAX + 929 # . . call + 930 e8/call clear-stream/disp32 + 931 # . . discard args + 932 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 933 # . clear-stream(_test-output-stream) + 934 # . . push args + 935 68/push _test-output-stream/imm32 + 936 # . . call + 937 e8/call clear-stream/disp32 + 938 # . . discard args + 939 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 940 # . clear-stream(_test-output-buffered-file+4) + 941 # . . push args + 942 b8/copy-to-EAX _test-output-buffered-file/imm32 + 943 05/add-to-EAX 4/imm32 + 944 50/push-EAX + 945 # . . call + 946 e8/call clear-stream/disp32 + 947 # . . discard args + 948 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 949 # initialize input + 950 # . write(_test-input-stream, "ab *(ecx + edx<<3 + 4)") + 951 # . . push args + 952 68/push "ab *(ecx + edx<<3 + 4)"/imm32 + 953 68/push _test-input-stream/imm32 + 954 # . . call + 955 e8/call write/disp32 + 956 # . . discard args + 957 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 958 # convert(_test-input-buffered-file, _test-output-buffered-file) + 959 # . . push args + 960 68/push _test-output-buffered-file/imm32 + 961 68/push _test-input-buffered-file/imm32 + 962 # . . call + 963 e8/call convert/disp32 + 964 # . . discard args + 965 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 966 # check that the line just passed through + 967 # . flush(_test-output-buffered-file) + 968 # . . push args + 969 68/push _test-output-buffered-file/imm32 + 970 # . . call + 971 e8/call flush/disp32 + 972 # . . discard args + 973 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 974 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1000 # . check-stream-equal(_test-output-stream, "ab 2/mod/*+disp32 4/rm32/sib 1/base 2/index 3/scale 4/disp32 \n", msg) +1001 # . . push args +1002 68/push "F - test-convert-indirect-mode-with-sib-byte"/imm32 +1003 68/push "ab 2/mod/*+disp32 4/rm32/sib 0x00000001/base 0x00000002/index 0x00000003/scale 0x00000004/disp32 \n"/imm32 +1004 68/push _test-output-stream/imm32 +1005 # . . call +1006 e8/call check-stream-equal/disp32 +1007 # . . discard args +1008 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1009 # . epilog +1010 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1011 5d/pop-to-EBP +1012 c3/return +1013 +1014 test-convert-register-indirect-mode-with-sib-byte-negative-displacement: +1015 # . prolog +1016 55/push-EBP +1017 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1018 # setup +1019 # . clear-stream(_test-input-stream) +1020 # . . push args +1021 68/push _test-input-stream/imm32 +1022 # . . call +1023 e8/call clear-stream/disp32 +1024 # . . discard args +1025 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1026 # . clear-stream(_test-input-buffered-file+4) +1027 # . . push args +1028 b8/copy-to-EAX _test-input-buffered-file/imm32 +1029 05/add-to-EAX 4/imm32 +1030 50/push-EAX +1031 # . . call +1032 e8/call clear-stream/disp32 +1033 # . . discard args +1034 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1035 # . clear-stream(_test-output-stream) +1036 # . . push args +1037 68/push _test-output-stream/imm32 +1038 # . . call +1039 e8/call clear-stream/disp32 +1040 # . . discard args +1041 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1042 # . clear-stream(_test-output-buffered-file+4) +1043 # . . push args +1044 b8/copy-to-EAX _test-output-buffered-file/imm32 +1045 05/add-to-EAX 4/imm32 +1046 50/push-EAX +1047 # . . call +1048 e8/call clear-stream/disp32 +1049 # . . discard args +1050 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1051 # initialize input +1052 # . write(_test-input-stream, "ab *(ecx + edx<<3 - 4)") +1053 # . . push args +1054 68/push "ab *(ecx + edx<<3 - 4)"/imm32 +1055 68/push _test-input-stream/imm32 +1056 # . . call +1057 e8/call write/disp32 +1058 # . . discard args +1059 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1060 # convert(_test-input-buffered-file, _test-output-buffered-file) +1061 # . . push args +1062 68/push _test-output-buffered-file/imm32 +1063 68/push _test-input-buffered-file/imm32 +1064 # . . call +1065 e8/call convert/disp32 +1066 # . . discard args +1067 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1068 # check that the line just passed through +1069 # . flush(_test-output-buffered-file) +1070 # . . push args +1071 68/push _test-output-buffered-file/imm32 +1072 # . . call +1073 e8/call flush/disp32 +1074 # . . discard args +1075 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1076 +-- 26 lines: #? # dump _test-output-stream -------------------------------------------------------------------------------------------------------------- +1102 # . check-stream-equal(_test-output-stream, "ab 2/mod/*+disp32 4/rm32/sib 1/base 2/index 3/scale -4/disp32 \n", msg) +1103 # . . push args +1104 68/push "F - test-convert-indirect-mode-with-sib-byte-negative-displacement"/imm32 +1105 68/push "ab 2/mod/*+disp32 4/rm32/sib 0x00000001/base 0x00000002/index 0x00000003/scale 0xfffffffc/disp32 \n"/imm32 +1106 68/push _test-output-stream/imm32 +1107 # . . call +1108 e8/call check-stream-equal/disp32 +1109 # . . discard args +1110 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1111 # . epilog +1112 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1113 5d/pop-to-EBP +1114 c3/return +1115 +1116 # beware: modifies 'word' +1117 emit-direct-mode: # word : (address slice), out : (address buffered-file) +1118 # . prolog +1119 55/push-EBP +1120 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1121 # . save registers +1122 50/push-EAX +1123 # ++word->start +1124 # . EAX = word +1125 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 0/r32/EAX 8/disp8 . # copy *(EBP+8) to EAX +1126 # . ++(*EAX) +1127 ff 0/subop/increment 0/mod/indirect 0/rm32/EAX . . . . . . # increment *EAX +1128 # reg-num/EAX = get-slice(Registers, word, row-size=8) +1129 # . . push args +1130 68/push "Registers"/imm32 +1131 68/push 8/imm32/row-size +1132 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1133 68/push Registers/imm32 +1134 # . . call +1135 e8/call get-slice/disp32 +1136 # . . discard args +1137 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +1138 # write-buffered(out, "3/mod/direct ") +1139 # . . push args +1140 68/push "3/mod/direct "/imm32 +1141 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +1142 # . . call +1143 e8/call write-buffered/disp32 +1144 # . . discard args +1145 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1146 # print-int32-buffered(out, *EAX) +1147 # . . push args +1148 ff 6/subop/push 0/mod/indirect 0/rm32/EAX . . . . . . # push *EAX +1149 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +1150 # . . call +1151 e8/call print-int32-buffered/disp32 +1152 # . . discard args +1153 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1154 # write-buffered(out, "/rm32") +1155 # . . push args +1156 68/push "/rm32"/imm32 +1157 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +1158 # . . call +1159 e8/call write-buffered/disp32 +1160 # . . discard args +1161 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1162 $emit-direct-mode:end: +1163 # . restore registers +1164 58/pop-to-EAX +1165 # . epilog +1166 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1167 5d/pop-to-EBP +1168 c3/return +1169 +1170 test-emit-direct-mode: +1171 # . prolog +1172 55/push-EBP +1173 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1174 # setup +1175 # . clear-stream(_test-output-stream) +1176 # . . push args +1177 68/push _test-output-stream/imm32 +1178 # . . call +1179 e8/call clear-stream/disp32 +1180 # . . discard args +1181 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1182 # . clear-stream(_test-output-buffered-file+4) +1183 # . . push args +1184 b8/copy-to-EAX _test-output-buffered-file/imm32 +1185 05/add-to-EAX 4/imm32 +1186 50/push-EAX +1187 # . . call +1188 e8/call clear-stream/disp32 +1189 # . . discard args +1190 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1191 # var slice/ECX = "%eax" +1192 b8/copy-to-EAX "%eax"/imm32 +1193 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +1194 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 +1195 05/add-to-EAX 4/imm32 +1196 # . ECX = {EAX, ECX} +1197 51/push-ECX +1198 50/push-EAX +1199 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1200 # emit-direct-mode(str, _test-output-buffered-file) +1201 # . . push args +1202 68/push _test-output-buffered-file/imm32 +1203 51/push-ECX +1204 # . . call +1205 e8/call emit-direct-mode/disp32 +1206 # . . discard args +1207 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1208 # . flush(_test-output-buffered-file) +1209 # . . push args +1210 68/push _test-output-buffered-file/imm32 +1211 # . . call +1212 e8/call flush/disp32 +1213 # . . discard args +1214 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1215 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +1241 # check-stream-equal(_test-output-stream, "3/mod/direct 0/rm32", msg) +1242 # . . push args +1243 68/push "F - test-emit-direct-mode/0"/imm32 +1244 68/push "3/mod/direct 0x00000000/rm32"/imm32 +1245 68/push _test-output-stream/imm32 +1246 # . . call +1247 e8/call check-stream-equal/disp32 +1248 # . . discard args +1249 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1250 # . epilog +1251 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1252 5d/pop-to-EBP +1253 c3/return +1254 +1255 test-emit-direct-mode-2: +1256 # . prolog +1257 55/push-EBP +1258 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1259 # setup +1260 # . clear-stream(_test-output-stream) +1261 # . . push args +1262 68/push _test-output-stream/imm32 +1263 # . . call +1264 e8/call clear-stream/disp32 +1265 # . . discard args +1266 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1267 # . clear-stream(_test-output-buffered-file+4) +1268 # . . push args +1269 b8/copy-to-EAX _test-output-buffered-file/imm32 +1270 05/add-to-EAX 4/imm32 +1271 50/push-EAX +1272 # . . call +1273 e8/call clear-stream/disp32 +1274 # . . discard args +1275 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1276 # var slice/ECX = "%edi" +1277 b8/copy-to-EAX "%edi"/imm32 +1278 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +1279 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 +1280 05/add-to-EAX 4/imm32 +1281 # . ECX = {EAX, ECX} +1282 51/push-ECX +1283 50/push-EAX +1284 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1285 # emit-direct-mode(str/ECX, _test-output-buffered-file) +1286 # . . push args +1287 68/push _test-output-buffered-file/imm32 +1288 51/push-ECX +1289 # . . call +1290 e8/call emit-direct-mode/disp32 +1291 # . . discard args +1292 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1293 # . flush(_test-output-buffered-file) +1294 # . . push args +1295 68/push _test-output-buffered-file/imm32 +1296 # . . call +1297 e8/call flush/disp32 +1298 # . . discard args +1299 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1300 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +1326 # check-stream-equal(_test-output-stream, "3/mod/direct 7/rm32", msg) +1327 # . . push args +1328 68/push "F - test-emit-direct-mode/1"/imm32 +1329 68/push "3/mod/direct 0x00000007/rm32"/imm32 +1330 68/push _test-output-stream/imm32 +1331 # . . call +1332 e8/call check-stream-equal/disp32 +1333 # . . discard args +1334 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1335 # . epilog +1336 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1337 5d/pop-to-EBP +1338 c3/return +1339 +1340 # (re)compute the bounds of the next word or parenthetical expression in the line +1341 # return empty string on reaching end of file +1342 # +1343 # error messages considered: +1344 # * ... -> error: no space after '*' +1345 # *(... -> error: *(...) expression must be all on a single line +1346 next-word-or-expression: # line : (address stream byte), out : (address slice) +1347 # . prolog +1348 55/push-EBP +1349 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1350 # . save registers +1351 50/push-EAX +1352 51/push-ECX +1353 56/push-ESI +1354 57/push-EDI +1355 # ESI = line +1356 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +1357 # EDI = out +1358 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI +1359 # skip-chars-matching(line, ' ') +1360 # . . push args +1361 68/push 0x20/imm32/space +1362 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1363 # . . call +1364 e8/call skip-chars-matching/disp32 +1365 # . . discard args +1366 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1367 $next-word-or-expression:check0: +1368 # if (line->read >= line->write) clear out and return +1369 # . EAX = line->read +1370 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy *(ESI+4) to EAX +1371 # . if (EAX < line->write) goto next check +1372 3b/compare 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # compare EAX with *ESI +1373 7c/jump-if-lesser $next-word-or-expression:check-for-comment/disp8 +1374 # . return out = {0, 0} +1375 c7 0/subop/copy 0/mod/direct 7/rm32/EDI . . . . . 0/imm32 # copy to *EDI +1376 c7 0/subop/copy 1/mod/*+disp8 7/rm32/EDI . . . . 4/disp8 0/imm32 # copy to *(EDI+4) +1377 e9/jump $next-word-or-expression:end/disp32 +1378 $next-word-or-expression:check-for-comment: +1379 # out->start = &line->data[line->read] +1380 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX +1381 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 +1382 89/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to *EDI +1383 # if (line->data[line->read] != '#') goto next check +1384 # . EAX = line->data[line->read] +1385 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +1386 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 +1387 # . compare +1388 3d/compare-EAX-and 0x23/imm32/pound +1389 75/jump-if-not-equal $next-word-or-expression:check-for-string-literal/disp8 +1390 $next-word-or-expression:comment: +1391 # out->end = &line->data[line->write] +1392 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX +1393 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 +1394 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDI+4) +1395 # line->read = line->write # skip rest of line +1396 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX +1397 89/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(ESI+4) +1398 # return +1399 eb/jump $next-word-or-expression:end/disp8 +1400 $next-word-or-expression:check-for-string-literal: +1401 # if (line->data[line->read] != '"') goto next check +1402 # . EAX = line->data[line->read] +1403 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +1404 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 +1405 # . compare +1406 3d/compare-EAX-and 0x22/imm32/dquote +1407 75/jump-if-not-equal $next-word-or-expression:check-for-paren/disp8 +1408 $next-word-or-expression:string-literal: +1409 # skip-string(line) +1410 # . . push args +1411 56/push-ESI +1412 # . . call +1413 e8/call skip-string/disp32 +1414 # . . discard args +1415 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1416 # skip rest of word +1417 eb/jump $next-word-or-expression:regular-word/disp8 +1418 $next-word-or-expression:check-for-paren: +1419 # if (line->data[line->read] != '*') goto next check +1420 # . EAX = line->data[line->read] +1421 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +1422 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 +1423 # . compare +1424 3d/compare-EAX-and 0x2a/imm32/asterisk +1425 75/jump-if-not-equal $next-word-or-expression:regular-word/disp8 +1426 # if (line->data[line->read] == ' ') goto error1 +1427 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 +1428 # . compare +1429 3d/compare-EAX-and 0x20/imm32/space +1430 74/jump-if-equal $next-word-or-expression:error1/disp8 +1431 # if (line->data[line->read] != '(') goto regular word +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 0x28/imm32/open-paren +1435 75/jump-if-not-equal $next-word-or-expression:regular-word/disp8 +1436 $next-word-or-expression:paren: +1437 # skip-until-close-paren(line) +1438 # . . push args +1439 56/push-ESI +1440 # . . call +1441 e8/call skip-until-close-paren/disp32 +1442 # . . discard args +1443 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1444 # if (line->data[line->read] != ')') goto error2 +1445 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX +1446 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 +1447 # . compare +1448 3d/compare-EAX-and 0x29/imm32/close-paren +1449 75/jump-if-not-equal $next-word-or-expression:error2/disp8 +1450 # skip ')' +1451 ff 0/subop/increment 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # increment *(ESI+4) +1452 # fall through +1453 $next-word-or-expression:regular-word: +1454 # skip-chars-not-matching-whitespace(line) # including trailing newline +1455 # . . push args +1456 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1457 # . . call +1458 e8/call skip-chars-not-matching-whitespace/disp32 +1459 # . . discard args +1460 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1461 # out->end = &line->data[line->read] +1462 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX +1463 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 +1464 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDI+4) +1465 $next-word-or-expression:end: +1466 # . restore registers +1467 5f/pop-to-EDI +1468 5e/pop-to-ESI +1469 59/pop-to-ECX +1470 58/pop-to-EAX +1471 # . epilog +1472 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1473 5d/pop-to-EBP +1474 c3/return +1475 +1476 $next-word-or-expression:error1: +1477 # print(stderr, "error: no space allowed after '*' in '" line "'") +1478 # . write-buffered(Stderr, "error: no space allowed after '*' in '") +1479 # . . push args +1480 68/push "error: no space allowed after '*' in '"/imm32 +1481 68/push Stderr/imm32 +1482 # . . call +1483 e8/call write-buffered/disp32 +1484 # . . discard args +1485 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1486 # . write-stream-data(Stderr, line) +1487 # . . push args +1488 56/push-ESI +1489 68/push Stderr/imm32 +1490 # . . call +1491 e8/call write-stream-data/disp32 +1492 # . . discard args +1493 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1494 # . write-buffered(Stderr, "'") +1495 # . . push args +1496 68/push "'"/imm32 +1497 68/push Stderr/imm32 +1498 # . . call +1499 e8/call write-buffered/disp32 +1500 # . . discard args +1501 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1502 # . flush(Stderr) +1503 # . . push args +1504 68/push Stderr/imm32 +1505 # . . call +1506 e8/call flush/disp32 +1507 # . . discard args +1508 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1509 # . syscall(exit, 1) +1510 bb/copy-to-EBX 1/imm32 +1511 b8/copy-to-EAX 1/imm32/exit +1512 cd/syscall 0x80/imm8 +1513 # never gets here +1514 +1515 $next-word-or-expression:error2: +1516 # print(stderr, "error: no space allowed after '*' in '" line "'") +1517 # . write-buffered(Stderr, "error: *(...) expression must be all on a single line in '") +1518 # . . push args +1519 68/push "error: *(...) expression must be all on a single line in '"/imm32 +1520 68/push Stderr/imm32 +1521 # . . call +1522 e8/call write-buffered/disp32 +1523 # . . discard args +1524 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1525 # . write-stream-data(Stderr, line) +1526 # . . push args +1527 56/push-ESI +1528 68/push Stderr/imm32 +1529 # . . call +1530 e8/call write-stream-data/disp32 +1531 # . . discard args +1532 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1533 # . write-buffered(Stderr, "'") +1534 # . . push args +1535 68/push "'"/imm32 +1536 68/push Stderr/imm32 +1537 # . . call +1538 e8/call write-buffered/disp32 +1539 # . . discard args +1540 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1541 # . flush(Stderr) +1542 # . . push args +1543 68/push Stderr/imm32 +1544 # . . call +1545 e8/call flush/disp32 +1546 # . . discard args +1547 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1548 # . syscall(exit, 1) +1549 bb/copy-to-EBX 1/imm32 +1550 b8/copy-to-EAX 1/imm32/exit +1551 cd/syscall 0x80/imm8 +1552 # never gets here +1553 +1554 test-next-word-or-expression: +1555 # . prolog +1556 55/push-EBP +1557 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1558 # setup +1559 # . clear-stream(_test-input-stream) +1560 # . . push args +1561 68/push _test-input-stream/imm32 +1562 # . . call +1563 e8/call clear-stream/disp32 +1564 # . . discard args +1565 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1566 # var slice/ECX = {0, 0} +1567 68/push 0/imm32/end +1568 68/push 0/imm32/start +1569 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1570 # write(_test-input-stream, " ab") +1571 # . . push args +1572 68/push " ab"/imm32 +1573 68/push _test-input-stream/imm32 +1574 # . . call +1575 e8/call write/disp32 +1576 # . . discard args +1577 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1578 # next-word-or-expression(_test-input-stream, slice) +1579 # . . push args +1580 51/push-ECX +1581 68/push _test-input-stream/imm32 +1582 # . . call +1583 e8/call next-word-or-expression/disp32 +1584 # . . discard args +1585 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1586 # check-ints-equal(_test-input-stream->read, 4, msg) +1587 # . . push args +1588 68/push "F - test-next-word-or-expression/updates-stream-read-correctly"/imm32 +1589 68/push 4/imm32 +1590 b8/copy-to-EAX _test-input-stream/imm32 +1591 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +1592 # . . call +1593 e8/call check-ints-equal/disp32 +1594 # . . discard args +1595 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1596 # check-ints-equal(slice->start - _test-input-stream->data, 2, msg) +1597 # . check-ints-equal(slice->start - _test-input-stream, 14, msg) +1598 # . . push args +1599 68/push "F - test-next-word-or-expression: start"/imm32 +1600 68/push 0xe/imm32 +1601 # . . push slice->start - _test-input-stream +1602 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX +1603 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +1604 50/push-EAX +1605 # . . call +1606 e8/call check-ints-equal/disp32 +1607 # . . discard args +1608 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1609 # check-ints-equal(slice->end - _test-input-stream->data, 4, msg) +1610 # . check-ints-equal(slice->end - _test-input-stream, 16, msg) +1611 # . . push args +1612 68/push "F - test-next-word-or-expression: end"/imm32 +1613 68/push 0x10/imm32 +1614 # . . push slice->end - _test-input-stream +1615 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +1616 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +1617 50/push-EAX +1618 # . . call +1619 e8/call check-ints-equal/disp32 +1620 # . . discard args +1621 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1622 # . epilog +1623 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1624 5d/pop-to-EBP +1625 c3/return +1626 +1627 test-next-word-or-expression-returns-whole-comment: +1628 # . prolog +1629 55/push-EBP +1630 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1631 # setup +1632 # . clear-stream(_test-input-stream) +1633 # . . push args +1634 68/push _test-input-stream/imm32 +1635 # . . call +1636 e8/call clear-stream/disp32 +1637 # . . discard args +1638 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1639 # var slice/ECX = {0, 0} +1640 68/push 0/imm32/end +1641 68/push 0/imm32/start +1642 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1643 # write(_test-input-stream, " # a") +1644 # . . push args +1645 68/push " # a"/imm32 +1646 68/push _test-input-stream/imm32 +1647 # . . call +1648 e8/call write/disp32 +1649 # . . discard args +1650 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1651 # next-word-or-expression(_test-input-stream, slice) +1652 # . . push args +1653 51/push-ECX +1654 68/push _test-input-stream/imm32 +1655 # . . call +1656 e8/call next-word-or-expression/disp32 +1657 # . . discard args +1658 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1659 # check-ints-equal(_test-input-stream->read, 5, msg) +1660 # . . push args +1661 68/push "F - test-next-word-or-expression-returns-whole-comment/updates-stream-read-correctly"/imm32 +1662 68/push 5/imm32 +1663 b8/copy-to-EAX _test-input-stream/imm32 +1664 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +1665 # . . call +1666 e8/call check-ints-equal/disp32 +1667 # . . discard args +1668 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1669 # check-ints-equal(slice->start - _test-input-stream->data, 2, msg) +1670 # . check-ints-equal(slice->start - _test-input-stream, 14, msg) +1671 # . . push args +1672 68/push "F - test-next-word-or-expression-returns-whole-comment: start"/imm32 +1673 68/push 0xe/imm32 +1674 # . . push slice->start - _test-input-stream +1675 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX +1676 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +1677 50/push-EAX +1678 # . . call +1679 e8/call check-ints-equal/disp32 +1680 # . . discard args +1681 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1682 # check-ints-equal(slice->end - _test-input-stream->data, 5, msg) +1683 # . check-ints-equal(slice->end - _test-input-stream, 17, msg) +1684 # . . push args +1685 68/push "F - test-next-word-or-expression-returns-whole-comment: end"/imm32 +1686 68/push 0x11/imm32 +1687 # . . push slice->end - _test-input-stream +1688 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +1689 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +1690 50/push-EAX +1691 # . . call +1692 e8/call check-ints-equal/disp32 +1693 # . . discard args +1694 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1695 # . epilog +1696 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1697 5d/pop-to-EBP +1698 c3/return +1699 +1700 test-next-word-or-expression-returns-empty-slice-on-eof: +1701 # . prolog +1702 55/push-EBP +1703 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1704 # setup +1705 # . clear-stream(_test-input-stream) +1706 # . . push args +1707 68/push _test-input-stream/imm32 +1708 # . . call +1709 e8/call clear-stream/disp32 +1710 # . . discard args +1711 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1712 # var slice/ECX = {0, 0} +1713 68/push 0/imm32/end +1714 68/push 0/imm32/start +1715 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1716 # write nothing to _test-input-stream +1717 # next-word-or-expression(_test-input-stream, slice) +1718 # . . push args +1719 51/push-ECX +1720 68/push _test-input-stream/imm32 +1721 # . . call +1722 e8/call next-word-or-expression/disp32 +1723 # . . discard args +1724 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1725 # check-ints-equal(slice->end - slice->start, 0, msg) +1726 # . . push args +1727 68/push "F - test-next-word-or-expression-returns-empty-expression-on-eof"/imm32 +1728 68/push 0/imm32 +1729 # . . push slice->end - slice->start +1730 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +1731 2b/subtract 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # subtract *ECX from EAX +1732 50/push-EAX +1733 # . . call +1734 e8/call check-ints-equal/disp32 +1735 # . . discard args +1736 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1737 # . epilog +1738 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1739 5d/pop-to-EBP +1740 c3/return +1741 +1742 test-next-word-or-expression-returns-string-literal: +1743 # . prolog +1744 55/push-EBP +1745 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1746 # setup +1747 # . clear-stream(_test-input-stream) +1748 # . . push args +1749 68/push _test-input-stream/imm32 +1750 # . . call +1751 e8/call clear-stream/disp32 +1752 # . . discard args +1753 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1754 # var slice/ECX = {0, 0} +1755 68/push 0/imm32/end +1756 68/push 0/imm32/start +1757 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1758 # write(_test-input-stream, " \"a b\"/imm32 ") +1759 # . . push args +1760 68/push " \"a b\"/imm32 "/imm32 +1761 68/push _test-input-stream/imm32 1762 # . . call -1763 e8/call check-ints-equal/disp32 +1763 e8/call write/disp32 1764 # . . discard args -1765 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1766 # check-ints-equal(slice->end - _test-input-stream->data, 13, msg) -1767 # . check-ints-equal(slice->end - _test-input-stream, 25, msg) -1768 # . . push args -1769 68/push "F - test-next-word-or-expression-returns-whole-expression: end"/imm32 -1770 68/push 0x19/imm32 -1771 # . . push slice->end - _test-input-stream -1772 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX -1773 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX -1774 50/push-EAX -1775 # . . call -1776 e8/call check-ints-equal/disp32 -1777 # . . discard args -1778 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1779 # . epilog -1780 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1781 5d/pop-to-EBP -1782 c3/return -1783 -1784 # Grammar: -1785 # *reg -> 0/mod reg/rm32 -1786 # *(reg) -> 0/mod reg/rm32 -1787 # *(reg+disp) -> 2/mod reg/rm32 disp/disp32 -1788 # *(reg1+reg2<<s) -> 2/mod 4/rm32 reg1/base reg2/index s/scale 0/disp32 -1789 # *(reg1+reg2<<s+disp) -> 2/mod 4/rm32 reg1/base reg2/index s/scale disp/disp32 -1790 # Intermediate structure: base, index, scale, disp -1791 # Default values: base: 0, index: 4 (none), scale: 0, disp: 0 -1792 # beware: modifies 'word' -1793 parse-effective-address: # word : (address slice) -> base/EAX, index/ECX, scale/EDX, disp/EBX -1794 # pseudocode: -1795 # ++word->start to skip '*' -1796 # initialize defaults: base=0, index=4, scale=0, disp=0 -1797 # if (*word->start != '(') { -1798 # base = get-slice(Registers, word, row-size=8) -1799 # return -1800 # } -1801 # # compound expressions -1802 # skip whitespace -1803 # read register into base -1804 # skip whitespace -1805 # if (*word->start == ')') goto end -1806 # if (*word->start == '-') goto displacement -1807 # if (*word->start != '+') goto error1 -1808 # ++word->start to skip '+' -1809 # skip whitespace -1810 # if next 3 characters don't make a register, goto displacement -1811 # read register into index -1812 # skip whitespace -1813 # if (*word->start == ')') goto end -1814 # if (*word->start == '<') { -1815 # ++word->start to skip '<' -1816 # if (*word->start != '<') goto error2 -1817 # ++word->start to skip '<' -1818 # skip whitespace -1819 # read integer into scale -1820 # skip whitespace -1821 # if (*word->start == ')') goto end -1822 # } -1823 # if (*word->start not in '+' '-') goto error3 -1824 # displacement: -1825 # read integer into disp -1826 # skip whitespace -1827 # if (*word->start != ')') goto error4 -1828 # . prolog -1829 55/push-EBP -1830 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1831 # . save registers -1832 56/push-ESI -1833 57/push-EDI -1834 # ESI = word -1835 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI -1836 # ++word->start to skip '*' -1837 ff 0/subop/increment 0/mod/indirect 6/rm32/ESI . . . . . . # increment *ESI -1838 # initialize defaults -1839 # base is in EDI; we'll move it to EAX just before we return -1840 bf/copy-to-EDI 0/imm32 -1841 b9/copy-to-ECX 4/imm32/no-index -1842 ba/copy-to-EDX 0/imm32/.scale -1843 bb/copy-to-EBX 0/imm32/disp -1844 $parse-effective-address:check-for-simple-register: -1845 # if (*word->start == '(') goto compound expression -1846 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX -1847 8a/copy-byte 0/mod/indirect 0/rm32/EAX . . . 0/r32/AL . . # copy byte at *EAX to AL -1848 81 4/subop/and 3/mod/direct 0/rm32/EAX . . . . . 0xff/imm32 # bitwise and of EAX -1849 3d/compare-EAX-and 0x28/imm32/open-paren -1850 74/jump-if-equal $parse-effective-address:compound-expression/disp8 -1851 $parse-effective-address:simple-register: -1852 # base = get-slice(Registers, word, row-size=8) -1853 # . EAX = get-slice(Registers, word, row-size=8) -1854 # . . push args -1855 68/push "Registers"/imm32 -1856 68/push 8/imm32/row-size -1857 56/push-ESI -1858 68/push Registers/imm32 +1765 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1766 # next-word-or-expression(_test-input-stream, slice) +1767 # . . push args +1768 51/push-ECX +1769 68/push _test-input-stream/imm32 +1770 # . . call +1771 e8/call next-word-or-expression/disp32 +1772 # . . discard args +1773 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1774 # check-ints-equal(slice->start - _test-input-stream->data, 1, msg) +1775 # . check-ints-equal(slice->start - _test-input-stream, 13, msg) +1776 # . . push args +1777 68/push "F - test-next-word-or-expression-returns-string-literal: start"/imm32 +1778 68/push 0xd/imm32 +1779 # . . push slice->start - _test-input-stream +1780 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX +1781 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +1782 50/push-EAX +1783 # . . call +1784 e8/call check-ints-equal/disp32 +1785 # . . discard args +1786 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1787 # check-ints-equal(slice->end - _test-input-stream->data, 12, msg) +1788 # . check-ints-equal(slice->end - _test-input-stream, 24, msg) +1789 # . . push args +1790 68/push "F - test-next-word-or-expression-returns-string-literal: end"/imm32 +1791 68/push 0x18/imm32 +1792 # . . push slice->end - _test-input-stream +1793 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +1794 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +1795 50/push-EAX +1796 # . . call +1797 e8/call check-ints-equal/disp32 +1798 # . . discard args +1799 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1800 # . epilog +1801 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1802 5d/pop-to-EBP +1803 c3/return +1804 +1805 test-next-word-or-expression-returns-string-with-escapes: +1806 # . prolog +1807 55/push-EBP +1808 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1809 # setup +1810 # . clear-stream(_test-input-stream) +1811 # . . push args +1812 68/push _test-input-stream/imm32 +1813 # . . call +1814 e8/call clear-stream/disp32 +1815 # . . discard args +1816 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1817 # var slice/ECX = {0, 0} +1818 68/push 0/imm32/end +1819 68/push 0/imm32/start +1820 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1821 # write(_test-input-stream, " \"a\\\"b\"/x") +1822 # . . push args +1823 68/push " \"a\\\"b\"/x"/imm32 +1824 68/push _test-input-stream/imm32 +1825 # . . call +1826 e8/call write/disp32 +1827 # . . discard args +1828 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1829 # next-word-or-expression(_test-input-stream, slice) +1830 # . . push args +1831 51/push-ECX +1832 68/push _test-input-stream/imm32 +1833 # . . call +1834 e8/call next-word-or-expression/disp32 +1835 # . . discard args +1836 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1837 # check-ints-equal(slice->start - _test-input-stream->data, 1, msg) +1838 # . check-ints-equal(slice->start - _test-input-stream, 13, msg) +1839 # . . push args +1840 68/push "F - test-next-word-or-expression-returns-string-with-escapes: start"/imm32 +1841 68/push 0xd/imm32 +1842 # . . push slice->start - _test-input-stream +1843 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX +1844 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +1845 50/push-EAX +1846 # . . call +1847 e8/call check-ints-equal/disp32 +1848 # . . discard args +1849 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1850 # check-ints-equal(slice->end - _test-input-stream->data, 9, msg) +1851 # . check-ints-equal(slice->end - _test-input-stream, 21, msg) +1852 # . . push args +1853 68/push "F - test-next-word-or-expression-returns-string-with-escapes: end"/imm32 +1854 68/push 0x15/imm32 +1855 # . . push slice->end - _test-input-stream +1856 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +1857 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +1858 50/push-EAX 1859 # . . call -1860 e8/call get-slice/disp32 +1860 e8/call check-ints-equal/disp32 1861 # . . discard args -1862 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -1863 # . base = *EAX -1864 8b/copy 0/mod/indirect 0/rm32/EAX . . . 7/r32/EDI . . # copy *EAX to EDI -1865 # return -1866 e9/jump $parse-effective-address:end/disp32 -1867 $parse-effective-address:compound-expression: -1868 # ++word->start to skip '(' -1869 ff 0/subop/increment 0/mod/indirect 6/rm32/ESI . . . . . . # increment *ESI -1870 # skip whitespace -1871 # . EAX = skip-chars-matching-whitespace-in-slice(word->start, word->end) -1872 # . . push args -1873 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) -1874 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI -1875 # . . call -1876 e8/call skip-chars-matching-whitespace-in-slice/disp32 -1877 # . . discard args -1878 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1879 # . word->start = EAX -1880 89/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to *ESI -1881 # read register into base -1882 # . EAX = next-register(word) -1883 # . . push args -1884 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -1885 # . . call -1886 e8/call next-register/disp32 -1887 # . . discard args -1888 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1889 # . EDI = *EAX -1890 8b/copy 0/mod/indirect 0/rm32/EAX . . . 7/r32/EDI . . # copy *EAX to EDI -1891 # skip whitespace -1892 # . EAX = skip-chars-matching-whitespace-in-slice(word->start, word->end) +1862 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1863 # . epilog +1864 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1865 5d/pop-to-EBP +1866 c3/return +1867 +1868 test-next-word-or-expression-returns-whole-expression: +1869 # . prolog +1870 55/push-EBP +1871 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1872 # setup +1873 # . clear-stream(_test-input-stream) +1874 # . . push args +1875 68/push _test-input-stream/imm32 +1876 # . . call +1877 e8/call clear-stream/disp32 +1878 # . . discard args +1879 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1880 # var slice/ECX = {0, 0} +1881 68/push 0/imm32/end +1882 68/push 0/imm32/start +1883 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1884 # write(_test-input-stream, " *(a b)/imm32 ") +1885 # . . push args +1886 68/push " *(a b)/imm32 "/imm32 +1887 68/push _test-input-stream/imm32 +1888 # . . call +1889 e8/call write/disp32 +1890 # . . discard args +1891 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1892 # next-word-or-expression(_test-input-stream, slice) 1893 # . . push args -1894 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) -1895 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI +1894 51/push-ECX +1895 68/push _test-input-stream/imm32 1896 # . . call -1897 e8/call skip-chars-matching-whitespace-in-slice/disp32 +1897 e8/call next-word-or-expression/disp32 1898 # . . discard args 1899 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1900 # . word->start = EAX -1901 89/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to *ESI -1902 # if (*word->start == ')') goto end -1903 8a/copy-byte 0/mod/indirect 0/rm32/EAX . . . 0/r32/AL . . # copy byte at *EAX to AL -1904 81 4/subop/and 3/mod/direct 0/rm32/EAX . . . . . 0xff/imm32 # bitwise and of EAX -1905 3d/compare-EAX-and 0x29/imm32/close-paren -1906 0f 84/jump-if-equal $parse-effective-address:end/disp32 -1907 # if (*word->start == '-') goto displacement -1908 3d/compare-EAX-and 0x2d/imm32/minus -1909 0f 84/jump-if-equal $parse-effective-address:displacement/disp32 -1910 # if (*word->start != '+') goto error1 -1911 3d/compare-EAX-and 0x2b/imm32/plus -1912 0f 85/jump-if-not-equal $parse-effective-address:error1/disp32 -1913 $parse-effective-address:check-for-index: -1914 # ++word->start to skip '+' -1915 ff 0/subop/increment 0/mod/indirect 6/rm32/ESI . . . . . . # increment *ESI -1916 # skip whitespace -1917 # . EAX = skip-chars-matching-whitespace-in-slice(word->start, word->end) -1918 # . . push args -1919 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) -1920 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI -1921 # . . call -1922 e8/call skip-chars-matching-whitespace-in-slice/disp32 -1923 # . . discard args -1924 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1925 # . word->start = EAX -1926 89/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to *ESI -1927 $parse-effective-address:resolve-ambiguity: -1928 # if next 3 characters don't make a register, goto displacement -1929 # . spill ECX -1930 51/push-ECX -1931 # . var tmp/ECX = {word->start, word->start+3} -1932 # . . ECX = word->start -1933 89/copy 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # copy EAX to ECX -1934 # . . EAX = word->start+3 -1935 05/add-to-EAX 3/imm32 -1936 # . . push -1937 50/push-EAX -1938 51/push-ECX -1939 # . . copy ESP to ECX -1940 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1941 # . EAX = maybe-get-slice(Register, tmp, row-size=8) -1942 # . . push args -1943 68/push 8/imm32/row-size -1944 51/push-ECX -1945 68/push Registers/imm32 -1946 # . . call -1947 e8/call maybe-get-slice/disp32 -1948 # . . discard args -1949 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1950 # . reclaim tmp -1951 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1952 # . restore ECX -1953 59/pop-to-ECX -1954 # . if (EAX == 0) goto displacement -1955 3d/compare-EAX-and 0/imm32 -1956 0f 84/jump-if-equal $parse-effective-address:displacement/disp32 -1957 $parse-effective-address:index: -1958 # read register into index -1959 # . EAX = next-register(word) -1960 # . . push args -1961 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -1962 # . . call -1963 e8/call next-register/disp32 -1964 # . . discard args -1965 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1966 # . ECX = *EAX -1967 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -1968 # skip whitespace -1969 # . EAX = skip-chars-matching-whitespace-in-slice(word->start, word->end) -1970 # . . push args -1971 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) -1972 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI -1973 # . . call -1974 e8/call skip-chars-matching-whitespace-in-slice/disp32 -1975 # . . discard args -1976 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1977 # . word->start = EAX -1978 89/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to *ESI -1979 # if (*word->start == ')') goto end -1980 8a/copy-byte 0/mod/indirect 0/rm32/EAX . . . 0/r32/AL . . # copy byte at *EAX to AL -1981 81 4/subop/and 3/mod/direct 0/rm32/EAX . . . . . 0xff/imm32 # bitwise and of EAX -1982 3d/compare-EAX-and 0x29/imm32/close-paren -1983 0f 84/jump-if-equal $parse-effective-address:end/disp32 -1984 $parse-effective-address:check-for-scale: -1985 # if (*word->start != '<') goto next check -1986 3d/compare-EAX-and 0x3c/imm32/less-than -1987 75/jump-if-not-equal $parse-effective-address:check-for-displacement/disp8 -1988 # ++word->start to skip '<' -1989 ff 0/subop/increment 0/mod/indirect 6/rm32/ESI . . . . . . # increment *ESI -1990 # if (*word->start != '<') goto error2 -1991 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX -1992 8a/copy-byte 0/mod/indirect 0/rm32/EAX . . . 0/r32/AL . . # copy byte at *EAX to AL -1993 81 4/subop/and 3/mod/direct 0/rm32/EAX . . . . . 0xff/imm32 # bitwise and of EAX -1994 3d/compare-EAX-and 0x3c/imm32/less-than -1995 0f 85/jump-if-not-equal $parse-effective-address:error2/disp32 -1996 # ++word->start to skip '<' -1997 ff 0/subop/increment 0/mod/indirect 6/rm32/ESI . . . . . . # increment *ESI -1998 # skip whitespace -1999 # . EAX = skip-chars-matching-whitespace-in-slice(word->start, word->end) -2000 # . . push args -2001 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) -2002 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI -2003 # . . call -2004 e8/call skip-chars-matching-whitespace-in-slice/disp32 -2005 # . . discard args -2006 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2007 # . word->start = EAX -2008 89/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to *ESI -2009 $parse-effective-address:scale: -2010 # read positive integer into scale -2011 # . EAX = next-positive-hex-int(word) -2012 # . . push args -2013 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2014 # . . call -2015 e8/call next-positive-hex-int/disp32 -2016 # . . discard args -2017 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2018 # . EDX = EAX -2019 89/copy 3/mod/direct 2/rm32/EDX . . . 0/r32/EAX . . # copy EAX to EDX -2020 # skip whitespace -2021 # . EAX = skip-chars-matching-whitespace-in-slice(word->start, word->end) -2022 # . . push args -2023 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) -2024 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI -2025 # . . call -2026 e8/call skip-chars-matching-whitespace-in-slice/disp32 -2027 # . . discard args -2028 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2029 # . word->start = EAX -2030 89/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to *ESI -2031 # if (*word->start == ')') goto end -2032 8a/copy-byte 0/mod/indirect 0/rm32/EAX . . . 0/r32/AL . . # copy byte at *EAX to AL -2033 81 4/subop/and 3/mod/direct 0/rm32/EAX . . . . . 0xff/imm32 # bitwise and of EAX -2034 3d/compare-EAX-and 0x29/imm32/close-paren -2035 74/jump-if-equal $parse-effective-address:end/disp8 -2036 $parse-effective-address:check-for-displacement: -2037 # if (*word->start not in '+' '-') goto error3 -2038 3d/compare-EAX-and 0x2b/imm32/plus -2039 74/jump-if-equal $parse-effective-address:displacement/disp8 -2040 3d/compare-EAX-and 0x2d/imm32/minus -2041 74/jump-if-equal $parse-effective-address:displacement/disp8 -2042 e9/jump $parse-effective-address:error3/disp32 -2043 $parse-effective-address:displacement: -2044 # read integer into disp -2045 # . EAX = next-hex-int(word) -2046 # . . push args -2047 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2048 # . . call -2049 e8/call next-hex-int/disp32 -2050 # . . discard args -2051 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2052 # . EBX = EAX -2053 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX -2054 # skip whitespace -2055 # . EAX = skip-chars-matching-whitespace-in-slice(word->start, word->end) -2056 # . . push args -2057 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) -2058 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI -2059 # . . call -2060 e8/call skip-chars-matching-whitespace-in-slice/disp32 -2061 # . . discard args -2062 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2063 # . word->start = EAX -2064 89/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to *ESI -2065 # if (*word->start != ')') goto error4 -2066 8a/copy-byte 0/mod/indirect 0/rm32/EAX . . . 0/r32/AL . . # copy byte at *EAX to AL -2067 81 4/subop/and 3/mod/direct 0/rm32/EAX . . . . . 0xff/imm32 # bitwise and of EAX -2068 3d/compare-EAX-and 0x29/imm32/close-paren -2069 0f 85/jump-if-not-equal $parse-effective-address:error4/disp32 -2070 $parse-effective-address:end: -2071 # return base in EAX -2072 89/copy 3/mod/direct 0/rm32/EAX . . . 7/r32/EDI . . # copy EDI to EAX -2073 # . restore registers -2074 5f/pop-to-EDI -2075 5e/pop-to-ESI -2076 # . epilog -2077 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -2078 5d/pop-to-EBP -2079 c3/return -2080 -2081 $parse-effective-address:error1: -2082 # print(stderr, "error: unexpected character: " EAX "\n") -2083 # . write-buffered(Stderr, "error: unexpected character: ") -2084 # . . push args -2085 68/push "error: unexpected character: "/imm32 -2086 68/push Stderr/imm32 -2087 # . . call -2088 e8/call write-buffered/disp32 -2089 # . . discard args -2090 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2091 # . print-int32-buffered(out, EAX) -2092 # . . push args -2093 50/push-EAX -2094 68/push Stderr/imm32 -2095 # . . call -2096 e8/call print-int32-buffered/disp32 -2097 # . . discard args +1900 # check-ints-equal(slice->start - _test-input-stream->data, 1, msg) +1901 # . check-ints-equal(slice->start - _test-input-stream, 13, msg) +1902 # . . push args +1903 68/push "F - test-next-word-or-expression-returns-whole-expression: start"/imm32 +1904 68/push 0xd/imm32 +1905 # . . push slice->start - _test-input-stream +1906 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX +1907 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +1908 50/push-EAX +1909 # . . call +1910 e8/call check-ints-equal/disp32 +1911 # . . discard args +1912 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1913 # check-ints-equal(slice->end - _test-input-stream->data, 13, msg) +1914 # . check-ints-equal(slice->end - _test-input-stream, 25, msg) +1915 # . . push args +1916 68/push "F - test-next-word-or-expression-returns-whole-expression: end"/imm32 +1917 68/push 0x19/imm32 +1918 # . . push slice->end - _test-input-stream +1919 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +1920 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-input-stream/imm32 # subtract from EAX +1921 50/push-EAX +1922 # . . call +1923 e8/call check-ints-equal/disp32 +1924 # . . discard args +1925 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1926 # . epilog +1927 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1928 5d/pop-to-EBP +1929 c3/return +1930 +1931 # Grammar: +1932 # *reg -> 0/mod reg/rm32 +1933 # *(reg) -> 0/mod reg/rm32 +1934 # *(reg+disp) -> 2/mod reg/rm32 disp/disp32 +1935 # *(reg1+reg2<<s) -> 2/mod 4/rm32 reg1/base reg2/index s/scale 0/disp32 +1936 # *(reg1+reg2<<s+disp) -> 2/mod 4/rm32 reg1/base reg2/index s/scale disp/disp32 +1937 # Intermediate structure: base, index, scale, disp +1938 # Default values: base: 0, index: 4 (none), scale: 0, disp: 0 +1939 # beware: modifies 'word' +1940 parse-effective-address: # word : (address slice) -> base/EAX, index/ECX, scale/EDX, disp/EBX +1941 # pseudocode: +1942 # ++word->start to skip '*' +1943 # initialize defaults: base=0, index=4, scale=0, disp=0 +1944 # if (*word->start != '(') { +1945 # base = get-slice(Registers, word, row-size=8) +1946 # return +1947 # } +1948 # # compound expressions +1949 # skip whitespace +1950 # read register into base +1951 # skip whitespace +1952 # if (*word->start == ')') goto end +1953 # if (*word->start == '-') goto displacement +1954 # if (*word->start != '+') goto error1 +1955 # ++word->start to skip '+' +1956 # skip whitespace +1957 # if next 3 characters don't make a register, goto displacement +1958 # read register into index +1959 # skip whitespace +1960 # if (*word->start == ')') goto end +1961 # if (*word->start == '<') { +1962 # ++word->start to skip '<' +1963 # if (*word->start != '<') goto error2 +1964 # ++word->start to skip '<' +1965 # skip whitespace +1966 # read integer into scale +1967 # skip whitespace +1968 # if (*word->start == ')') goto end +1969 # } +1970 # if (*word->start not in '+' '-') goto error3 +1971 # displacement: +1972 # read integer into disp +1973 # skip whitespace +1974 # if (*word->start != ')') goto error4 +1975 # . prolog +1976 55/push-EBP +1977 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1978 # . save registers +1979 56/push-ESI +1980 57/push-EDI +1981 # ESI = word +1982 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +1983 # ++word->start to skip '*' +1984 ff 0/subop/increment 0/mod/indirect 6/rm32/ESI . . . . . . # increment *ESI +1985 # initialize defaults +1986 # base is in EDI; we'll move it to EAX just before we return +1987 bf/copy-to-EDI 0/imm32 +1988 b9/copy-to-ECX 4/imm32/no-index +1989 ba/copy-to-EDX 0/imm32/.scale +1990 bb/copy-to-EBX 0/imm32/disp +1991 $parse-effective-address:check-for-simple-register: +1992 # if (*word->start == '(') goto compound expression +1993 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX +1994 8a/copy-byte 0/mod/indirect 0/rm32/EAX . . . 0/r32/AL . . # copy byte at *EAX to AL +1995 81 4/subop/and 3/mod/direct 0/rm32/EAX . . . . . 0xff/imm32 # bitwise and of EAX +1996 3d/compare-EAX-and 0x28/imm32/open-paren +1997 74/jump-if-equal $parse-effective-address:compound-expression/disp8 +1998 $parse-effective-address:simple-register: +1999 # base = get-slice(Registers, word, row-size=8) +2000 # . EAX = get-slice(Registers, word, row-size=8) +2001 # . . push args +2002 68/push "Registers"/imm32 +2003 68/push 8/imm32/row-size +2004 56/push-ESI +2005 68/push Registers/imm32 +2006 # . . call +2007 e8/call get-slice/disp32 +2008 # . . discard args +2009 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +2010 # . base = *EAX +2011 8b/copy 0/mod/indirect 0/rm32/EAX . . . 7/r32/EDI . . # copy *EAX to EDI +2012 # return +2013 e9/jump $parse-effective-address:end/disp32 +2014 $parse-effective-address:compound-expression: +2015 # ++word->start to skip '(' +2016 ff 0/subop/increment 0/mod/indirect 6/rm32/ESI . . . . . . # increment *ESI +2017 # skip whitespace +2018 # . EAX = skip-chars-matching-whitespace-in-slice(word->start, word->end) +2019 # . . push args +2020 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) +2021 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI +2022 # . . call +2023 e8/call skip-chars-matching-whitespace-in-slice/disp32 +2024 # . . discard args +2025 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2026 # . word->start = EAX +2027 89/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to *ESI +2028 # read register into base +2029 # . EAX = next-register(word) +2030 # . . push args +2031 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2032 # . . call +2033 e8/call next-register/disp32 +2034 # . . discard args +2035 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2036 # . EDI = *EAX +2037 8b/copy 0/mod/indirect 0/rm32/EAX . . . 7/r32/EDI . . # copy *EAX to EDI +2038 # skip whitespace +2039 # . EAX = skip-chars-matching-whitespace-in-slice(word->start, word->end) +2040 # . . push args +2041 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) +2042 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI +2043 # . . call +2044 e8/call skip-chars-matching-whitespace-in-slice/disp32 +2045 # . . discard args +2046 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2047 # . word->start = EAX +2048 89/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to *ESI +2049 # if (*word->start == ')') goto end +2050 8a/copy-byte 0/mod/indirect 0/rm32/EAX . . . 0/r32/AL . . # copy byte at *EAX to AL +2051 81 4/subop/and 3/mod/direct 0/rm32/EAX . . . . . 0xff/imm32 # bitwise and of EAX +2052 3d/compare-EAX-and 0x29/imm32/close-paren +2053 0f 84/jump-if-equal $parse-effective-address:end/disp32 +2054 # if (*word->start == '-') goto displacement +2055 3d/compare-EAX-and 0x2d/imm32/minus +2056 0f 84/jump-if-equal $parse-effective-address:displacement/disp32 +2057 # if (*word->start != '+') goto error1 +2058 3d/compare-EAX-and 0x2b/imm32/plus +2059 0f 85/jump-if-not-equal $parse-effective-address:error1/disp32 +2060 $parse-effective-address:check-for-index: +2061 # ++word->start to skip '+' +2062 ff 0/subop/increment 0/mod/indirect 6/rm32/ESI . . . . . . # increment *ESI +2063 # skip whitespace +2064 # . EAX = skip-chars-matching-whitespace-in-slice(word->start, word->end) +2065 # . . push args +2066 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) +2067 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI +2068 # . . call +2069 e8/call skip-chars-matching-whitespace-in-slice/disp32 +2070 # . . discard args +2071 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2072 # . word->start = EAX +2073 89/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to *ESI +2074 $parse-effective-address:resolve-ambiguity: +2075 # if next 3 characters don't make a register, goto displacement +2076 # . spill ECX +2077 51/push-ECX +2078 # . var tmp/ECX = {word->start, word->start+3} +2079 # . . ECX = word->start +2080 89/copy 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # copy EAX to ECX +2081 # . . EAX = word->start+3 +2082 05/add-to-EAX 3/imm32 +2083 # . . push +2084 50/push-EAX +2085 51/push-ECX +2086 # . . copy ESP to ECX +2087 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2088 # . EAX = maybe-get-slice(Register, tmp, row-size=8) +2089 # . . push args +2090 68/push 8/imm32/row-size +2091 51/push-ECX +2092 68/push Registers/imm32 +2093 # . . call +2094 e8/call maybe-get-slice/disp32 +2095 # . . discard args +2096 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2097 # . reclaim tmp 2098 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2099 # . write-buffered(Stderr, "\n") -2100 # . . push args -2101 68/push "\n"/imm32 -2102 68/push Stderr/imm32 -2103 # . . call -2104 e8/call write-buffered/disp32 -2105 # . . discard args -2106 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2107 # . flush(Stderr) -2108 # . . push args -2109 68/push Stderr/imm32 -2110 # . . call -2111 e8/call flush/disp32 -2112 # . . discard args -2113 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2114 # . syscall(exit, 1) -2115 bb/copy-to-EBX 1/imm32 -2116 b8/copy-to-EAX 1/imm32/exit -2117 cd/syscall 0x80/imm8 -2118 # never gets here -2119 -2120 $parse-effective-address:error2: -2121 # print(stderr, "error: '<' can only be followed by '<' but got: " EAX "\n") -2122 # . write-buffered(Stderr, "error: '<' can only be followed by '<' but got: ") -2123 # . . push args -2124 68/push "error: '<' can only be followed by '<' but got: "/imm32 -2125 68/push Stderr/imm32 -2126 # . . call -2127 e8/call write-buffered/disp32 -2128 # . . discard args -2129 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2130 # . print-int32-buffered(out, EAX) -2131 # . . push args -2132 50/push-EAX -2133 68/push Stderr/imm32 -2134 # . . call -2135 e8/call print-int32-buffered/disp32 -2136 # . . discard args -2137 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2138 # . write-buffered(Stderr, "\n") -2139 # . . push args -2140 68/push "\n"/imm32 -2141 68/push Stderr/imm32 -2142 # . . call -2143 e8/call write-buffered/disp32 -2144 # . . discard args -2145 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2146 # . flush(Stderr) +2099 # . restore ECX +2100 59/pop-to-ECX +2101 # . if (EAX == 0) goto displacement +2102 3d/compare-EAX-and 0/imm32 +2103 0f 84/jump-if-equal $parse-effective-address:displacement/disp32 +2104 $parse-effective-address:index: +2105 # read register into index +2106 # . EAX = next-register(word) +2107 # . . push args +2108 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2109 # . . call +2110 e8/call next-register/disp32 +2111 # . . discard args +2112 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2113 # . ECX = *EAX +2114 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2115 # skip whitespace +2116 # . EAX = skip-chars-matching-whitespace-in-slice(word->start, word->end) +2117 # . . push args +2118 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) +2119 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI +2120 # . . call +2121 e8/call skip-chars-matching-whitespace-in-slice/disp32 +2122 # . . discard args +2123 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2124 # . word->start = EAX +2125 89/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to *ESI +2126 # if (*word->start == ')') goto end +2127 8a/copy-byte 0/mod/indirect 0/rm32/EAX . . . 0/r32/AL . . # copy byte at *EAX to AL +2128 81 4/subop/and 3/mod/direct 0/rm32/EAX . . . . . 0xff/imm32 # bitwise and of EAX +2129 3d/compare-EAX-and 0x29/imm32/close-paren +2130 0f 84/jump-if-equal $parse-effective-address:end/disp32 +2131 $parse-effective-address:check-for-scale: +2132 # if (*word->start != '<') goto next check +2133 3d/compare-EAX-and 0x3c/imm32/less-than +2134 75/jump-if-not-equal $parse-effective-address:check-for-displacement/disp8 +2135 # ++word->start to skip '<' +2136 ff 0/subop/increment 0/mod/indirect 6/rm32/ESI . . . . . . # increment *ESI +2137 # if (*word->start != '<') goto error2 +2138 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX +2139 8a/copy-byte 0/mod/indirect 0/rm32/EAX . . . 0/r32/AL . . # copy byte at *EAX to AL +2140 81 4/subop/and 3/mod/direct 0/rm32/EAX . . . . . 0xff/imm32 # bitwise and of EAX +2141 3d/compare-EAX-and 0x3c/imm32/less-than +2142 0f 85/jump-if-not-equal $parse-effective-address:error2/disp32 +2143 # ++word->start to skip '<' +2144 ff 0/subop/increment 0/mod/indirect 6/rm32/ESI . . . . . . # increment *ESI +2145 # skip whitespace +2146 # . EAX = skip-chars-matching-whitespace-in-slice(word->start, word->end) 2147 # . . push args -2148 68/push Stderr/imm32 -2149 # . . call -2150 e8/call flush/disp32 -2151 # . . discard args -2152 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2153 # . syscall(exit, 1) -2154 bb/copy-to-EBX 1/imm32 -2155 b8/copy-to-EAX 1/imm32/exit -2156 cd/syscall 0x80/imm8 -2157 # never gets here -2158 -2159 $parse-effective-address:error3: -2160 # print(stderr, "error: unexpected character before displacement: " EAX "\n") -2161 # . write-buffered(Stderr, "error: unexpected character before displacement: ") -2162 # . . push args -2163 68/push "error: unexpected character before displacement: "/imm32 -2164 68/push Stderr/imm32 -2165 # . . call -2166 e8/call write-buffered/disp32 -2167 # . . discard args -2168 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2169 # . print-int32-buffered(out, EAX) -2170 # . . push args -2171 50/push-EAX -2172 68/push Stderr/imm32 -2173 # . . call -2174 e8/call print-int32-buffered/disp32 -2175 # . . discard args -2176 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2177 # . write-buffered(Stderr, "\n") -2178 # . . push args -2179 68/push "\n"/imm32 -2180 68/push Stderr/imm32 -2181 # . . call -2182 e8/call write-buffered/disp32 -2183 # . . discard args -2184 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2185 # . flush(Stderr) -2186 # . . push args -2187 68/push Stderr/imm32 -2188 # . . call -2189 e8/call flush/disp32 -2190 # . . discard args -2191 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2192 # . syscall(exit, 1) -2193 bb/copy-to-EBX 1/imm32 -2194 b8/copy-to-EAX 1/imm32/exit -2195 cd/syscall 0x80/imm8 -2196 # never gets here -2197 -2198 $parse-effective-address:error4: -2199 # print(stderr, "error: unexpected character after displacement: " EAX "; expected ')' to wrap up\n") -2200 # . write-buffered(Stderr, "error: unexpected character after displacement: ") -2201 # . . push args -2202 68/push "error: unexpected character after displacement: "/imm32 -2203 68/push Stderr/imm32 -2204 # . . call -2205 e8/call write-buffered/disp32 -2206 # . . discard args -2207 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2208 # . print-int32-buffered(out, EAX) -2209 # . . push args -2210 50/push-EAX -2211 68/push Stderr/imm32 -2212 # . . call -2213 e8/call print-int32-buffered/disp32 -2214 # . . discard args -2215 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2216 # . write-buffered(Stderr, "; expected ')' to wrap up\n") -2217 # . . push args -2218 68/push "; expected ')' to wrap up\n"/imm32 -2219 68/push Stderr/imm32 -2220 # . . call -2221 e8/call write-buffered/disp32 -2222 # . . discard args -2223 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2224 # . flush(Stderr) -2225 # . . push args -2226 68/push Stderr/imm32 -2227 # . . call -2228 e8/call flush/disp32 -2229 # . . discard args -2230 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2231 # . syscall(exit, 1) -2232 bb/copy-to-EBX 1/imm32 -2233 b8/copy-to-EAX 1/imm32/exit -2234 cd/syscall 0x80/imm8 -2235 # never gets here -2236 -2237 # assumes 'in' starts with a register name, and returns pointer to its code -2238 # side-effect: modifies 'in' to scan past the initial register name -2239 next-register: # in : (address slice) -> reg/EAX : int -2240 # . prolog -2241 55/push-EBP -2242 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -2243 # . save registers -2244 51/push-ECX -2245 56/push-ESI -2246 # ESI = in -2247 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI -2248 # var reg-slice/ECX : (address slice) = {in->start, in->start + 3} -2249 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX -2250 05/add-to-EAX 3/imm32 -2251 50/push-EAX -2252 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI -2253 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -2254 # in->start += 3 -2255 81 0/subop/add 0/mod/indirect 6/rm32/ESI . . . . . 3/imm32 # add to *ESI -2256 # EAX = get-slice(Registers, word, row-size=8) -2257 # . . push args -2258 68/push "next-register"/imm32 -2259 68/push 8/imm32/row-size -2260 51/push-ECX -2261 68/push Registers/imm32 -2262 # . . call -2263 e8/call get-slice/disp32 -2264 # . . discard args -2265 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -2266 $next-register:end: -2267 # reclaim locals -2268 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2269 # . restore registers -2270 5e/pop-to-ESI -2271 59/pop-to-ECX -2272 # . epilog -2273 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -2274 5d/pop-to-EBP -2275 c3/return -2276 -2277 test-parse-effective-address-simple: -2278 # . prolog -2279 55/push-EBP -2280 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -2281 # var slice/ECX = "*esi" -2282 b8/copy-to-EAX "*esi"/imm32 -2283 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -2284 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 -2285 05/add-to-EAX 4/imm32 -2286 # . ECX = {EAX, ECX} -2287 51/push-ECX -2288 50/push-EAX -2289 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -2290 # EAX, ECX, EDX, EBX = parse-effective-address(slice) -2291 # . . push args -2292 51/push-ECX -2293 # . . call -2294 e8/call parse-effective-address/disp32 -2295 # . . discard args -2296 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2297 # slice clobbered beyond this point -2298 # check-ints-equal(EAX, 6, msg) -2299 # . . push args -2300 68/push "F - test-parse-effective-address-simple/base"/imm32 -2301 68/push 6/imm32/ESI -2302 50/push-EAX -2303 # . . call -2304 e8/call check-ints-equal/disp32 -2305 # . . discard args -2306 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2307 # check-ints-equal(ECX, 4, msg) -2308 # . . push args -2309 68/push "F - test-parse-effective-address-simple/index"/imm32 -2310 68/push 4/imm32/none -2311 51/push-ECX +2148 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) +2149 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI +2150 # . . call +2151 e8/call skip-chars-matching-whitespace-in-slice/disp32 +2152 # . . discard args +2153 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2154 # . word->start = EAX +2155 89/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to *ESI +2156 $parse-effective-address:scale: +2157 # read positive integer into scale +2158 # . EAX = next-positive-hex-int(word) +2159 # . . push args +2160 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2161 # . . call +2162 e8/call next-positive-hex-int/disp32 +2163 # . . discard args +2164 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2165 # . EDX = EAX +2166 89/copy 3/mod/direct 2/rm32/EDX . . . 0/r32/EAX . . # copy EAX to EDX +2167 # skip whitespace +2168 # . EAX = skip-chars-matching-whitespace-in-slice(word->start, word->end) +2169 # . . push args +2170 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) +2171 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI +2172 # . . call +2173 e8/call skip-chars-matching-whitespace-in-slice/disp32 +2174 # . . discard args +2175 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2176 # . word->start = EAX +2177 89/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to *ESI +2178 # if (*word->start == ')') goto end +2179 8a/copy-byte 0/mod/indirect 0/rm32/EAX . . . 0/r32/AL . . # copy byte at *EAX to AL +2180 81 4/subop/and 3/mod/direct 0/rm32/EAX . . . . . 0xff/imm32 # bitwise and of EAX +2181 3d/compare-EAX-and 0x29/imm32/close-paren +2182 74/jump-if-equal $parse-effective-address:end/disp8 +2183 $parse-effective-address:check-for-displacement: +2184 # if (*word->start not in '+' '-') goto error3 +2185 3d/compare-EAX-and 0x2b/imm32/plus +2186 74/jump-if-equal $parse-effective-address:displacement/disp8 +2187 3d/compare-EAX-and 0x2d/imm32/minus +2188 74/jump-if-equal $parse-effective-address:displacement/disp8 +2189 e9/jump $parse-effective-address:error3/disp32 +2190 $parse-effective-address:displacement: +2191 # read integer into disp +2192 # . EAX = next-hex-int(word) +2193 # . . push args +2194 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2195 # . . call +2196 e8/call next-hex-int/disp32 +2197 # . . discard args +2198 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2199 # . EBX = EAX +2200 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX +2201 # skip whitespace +2202 # . EAX = skip-chars-matching-whitespace-in-slice(word->start, word->end) +2203 # . . push args +2204 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) +2205 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI +2206 # . . call +2207 e8/call skip-chars-matching-whitespace-in-slice/disp32 +2208 # . . discard args +2209 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2210 # . word->start = EAX +2211 89/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to *ESI +2212 # if (*word->start != ')') goto error4 +2213 8a/copy-byte 0/mod/indirect 0/rm32/EAX . . . 0/r32/AL . . # copy byte at *EAX to AL +2214 81 4/subop/and 3/mod/direct 0/rm32/EAX . . . . . 0xff/imm32 # bitwise and of EAX +2215 3d/compare-EAX-and 0x29/imm32/close-paren +2216 0f 85/jump-if-not-equal $parse-effective-address:error4/disp32 +2217 $parse-effective-address:end: +2218 # return base in EAX +2219 89/copy 3/mod/direct 0/rm32/EAX . . . 7/r32/EDI . . # copy EDI to EAX +2220 # . restore registers +2221 5f/pop-to-EDI +2222 5e/pop-to-ESI +2223 # . epilog +2224 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2225 5d/pop-to-EBP +2226 c3/return +2227 +2228 $parse-effective-address:error1: +2229 # print(stderr, "error: unexpected character: " EAX "\n") +2230 # . write-buffered(Stderr, "error: unexpected character: ") +2231 # . . push args +2232 68/push "error: unexpected character: "/imm32 +2233 68/push Stderr/imm32 +2234 # . . call +2235 e8/call write-buffered/disp32 +2236 # . . discard args +2237 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2238 # . print-int32-buffered(out, EAX) +2239 # . . push args +2240 50/push-EAX +2241 68/push Stderr/imm32 +2242 # . . call +2243 e8/call print-int32-buffered/disp32 +2244 # . . discard args +2245 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2246 # . write-buffered(Stderr, "\n") +2247 # . . push args +2248 68/push "\n"/imm32 +2249 68/push Stderr/imm32 +2250 # . . call +2251 e8/call write-buffered/disp32 +2252 # . . discard args +2253 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2254 # . flush(Stderr) +2255 # . . push args +2256 68/push Stderr/imm32 +2257 # . . call +2258 e8/call flush/disp32 +2259 # . . discard args +2260 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2261 # . syscall(exit, 1) +2262 bb/copy-to-EBX 1/imm32 +2263 b8/copy-to-EAX 1/imm32/exit +2264 cd/syscall 0x80/imm8 +2265 # never gets here +2266 +2267 $parse-effective-address:error2: +2268 # print(stderr, "error: '<' can only be followed by '<' but got: " EAX "\n") +2269 # . write-buffered(Stderr, "error: '<' can only be followed by '<' but got: ") +2270 # . . push args +2271 68/push "error: '<' can only be followed by '<' but got: "/imm32 +2272 68/push Stderr/imm32 +2273 # . . call +2274 e8/call write-buffered/disp32 +2275 # . . discard args +2276 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2277 # . print-int32-buffered(out, EAX) +2278 # . . push args +2279 50/push-EAX +2280 68/push Stderr/imm32 +2281 # . . call +2282 e8/call print-int32-buffered/disp32 +2283 # . . discard args +2284 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2285 # . write-buffered(Stderr, "\n") +2286 # . . push args +2287 68/push "\n"/imm32 +2288 68/push Stderr/imm32 +2289 # . . call +2290 e8/call write-buffered/disp32 +2291 # . . discard args +2292 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2293 # . flush(Stderr) +2294 # . . push args +2295 68/push Stderr/imm32 +2296 # . . call +2297 e8/call flush/disp32 +2298 # . . discard args +2299 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2300 # . syscall(exit, 1) +2301 bb/copy-to-EBX 1/imm32 +2302 b8/copy-to-EAX 1/imm32/exit +2303 cd/syscall 0x80/imm8 +2304 # never gets here +2305 +2306 $parse-effective-address:error3: +2307 # print(stderr, "error: unexpected character before displacement: " EAX "\n") +2308 # . write-buffered(Stderr, "error: unexpected character before displacement: ") +2309 # . . push args +2310 68/push "error: unexpected character before displacement: "/imm32 +2311 68/push Stderr/imm32 2312 # . . call -2313 e8/call check-ints-equal/disp32 +2313 e8/call write-buffered/disp32 2314 # . . discard args -2315 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2316 # check-ints-equal(EDX, 0, msg) +2315 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2316 # . print-int32-buffered(out, EAX) 2317 # . . push args -2318 68/push "F - test-parse-effective-address-simple/scale"/imm32 -2319 68/push 0/imm32/none -2320 52/push-EDX -2321 # . . call -2322 e8/call check-ints-equal/disp32 -2323 # . . discard args -2324 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2325 # check-ints-equal(EBX, 0, msg) -2326 # . . push args -2327 68/push "F - test-parse-effective-address-simple/displacement"/imm32 -2328 68/push 0/imm32/none -2329 53/push-EBX -2330 # . . call -2331 e8/call check-ints-equal/disp32 -2332 # . . discard args -2333 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2334 # . epilog -2335 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -2336 5d/pop-to-EBP -2337 c3/return -2338 -2339 test-parse-effective-address-base: -2340 # . prolog -2341 55/push-EBP -2342 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -2343 # var slice/ECX = "*(esi )" -2344 b8/copy-to-EAX "*(esi )"/imm32 -2345 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -2346 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 -2347 05/add-to-EAX 4/imm32 -2348 # . ECX = {EAX, ECX} -2349 51/push-ECX -2350 50/push-EAX -2351 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -2352 # EAX, ECX, EDX, EBX = parse-effective-address(slice) -2353 # . . push args -2354 51/push-ECX -2355 # . . call -2356 e8/call parse-effective-address/disp32 -2357 # . . discard args -2358 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2359 # slice clobbered beyond this point -2360 # check-ints-equal(EAX, 6, msg) -2361 # . . push args -2362 68/push "F - test-parse-effective-address-base/base"/imm32 -2363 68/push 6/imm32/ESI -2364 50/push-EAX -2365 # . . call -2366 e8/call check-ints-equal/disp32 -2367 # . . discard args -2368 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2369 # check-ints-equal(ECX, 4, msg) -2370 # . . push args -2371 68/push "F - test-parse-effective-address-base/index"/imm32 -2372 68/push 4/imm32/none -2373 51/push-ECX +2318 50/push-EAX +2319 68/push Stderr/imm32 +2320 # . . call +2321 e8/call print-int32-buffered/disp32 +2322 # . . discard args +2323 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2324 # . write-buffered(Stderr, "\n") +2325 # . . push args +2326 68/push "\n"/imm32 +2327 68/push Stderr/imm32 +2328 # . . call +2329 e8/call write-buffered/disp32 +2330 # . . discard args +2331 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2332 # . flush(Stderr) +2333 # . . push args +2334 68/push Stderr/imm32 +2335 # . . call +2336 e8/call flush/disp32 +2337 # . . discard args +2338 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2339 # . syscall(exit, 1) +2340 bb/copy-to-EBX 1/imm32 +2341 b8/copy-to-EAX 1/imm32/exit +2342 cd/syscall 0x80/imm8 +2343 # never gets here +2344 +2345 $parse-effective-address:error4: +2346 # print(stderr, "error: unexpected character after displacement: " EAX "; expected ')' to wrap up\n") +2347 # . write-buffered(Stderr, "error: unexpected character after displacement: ") +2348 # . . push args +2349 68/push "error: unexpected character after displacement: "/imm32 +2350 68/push Stderr/imm32 +2351 # . . call +2352 e8/call write-buffered/disp32 +2353 # . . discard args +2354 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2355 # . print-int32-buffered(out, EAX) +2356 # . . push args +2357 50/push-EAX +2358 68/push Stderr/imm32 +2359 # . . call +2360 e8/call print-int32-buffered/disp32 +2361 # . . discard args +2362 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2363 # . write-buffered(Stderr, "; expected ')' to wrap up\n") +2364 # . . push args +2365 68/push "; expected ')' to wrap up\n"/imm32 +2366 68/push Stderr/imm32 +2367 # . . call +2368 e8/call write-buffered/disp32 +2369 # . . discard args +2370 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2371 # . flush(Stderr) +2372 # . . push args +2373 68/push Stderr/imm32 2374 # . . call -2375 e8/call check-ints-equal/disp32 +2375 e8/call flush/disp32 2376 # . . discard args -2377 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2378 # check-ints-equal(EDX, 0, msg) -2379 # . . push args -2380 68/push "F - test-parse-effective-address-base/scale"/imm32 -2381 68/push 0/imm32/none -2382 52/push-EDX -2383 # . . call -2384 e8/call check-ints-equal/disp32 -2385 # . . discard args -2386 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2387 # check-ints-equal(EBX, 0, msg) -2388 # . . push args -2389 68/push "F - test-parse-effective-address-base/displacement"/imm32 -2390 68/push 0/imm32/none -2391 53/push-EBX -2392 # . . call -2393 e8/call check-ints-equal/disp32 -2394 # . . discard args -2395 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2396 # . epilog -2397 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -2398 5d/pop-to-EBP -2399 c3/return -2400 -2401 test-parse-effective-address-base-displacement: -2402 # . prolog -2403 55/push-EBP -2404 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -2405 # var slice/ECX = "*(esi+3)" -2406 b8/copy-to-EAX "*(esi+3)"/imm32 -2407 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -2408 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 -2409 05/add-to-EAX 4/imm32 -2410 # . ECX = {EAX, ECX} -2411 51/push-ECX -2412 50/push-EAX -2413 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -2414 # EAX, ECX, EDX, EBX = parse-effective-address(slice) -2415 # . . push args -2416 51/push-ECX -2417 # . . call -2418 e8/call parse-effective-address/disp32 -2419 # . . discard args -2420 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2421 # slice clobbered beyond this point -2422 # check-ints-equal(EAX, 6, msg) -2423 # . . push args -2424 68/push "F - test-parse-effective-address-base-displacement/base"/imm32 -2425 68/push 6/imm32/ESI -2426 50/push-EAX -2427 # . . call -2428 e8/call check-ints-equal/disp32 -2429 # . . discard args -2430 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2431 # check-ints-equal(ECX, 4, msg) -2432 # . . push args -2433 68/push "F - test-parse-effective-address-base-displacement/index"/imm32 -2434 68/push 4/imm32/none -2435 51/push-ECX -2436 # . . call -2437 e8/call check-ints-equal/disp32 -2438 # . . discard args -2439 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2440 # check-ints-equal(EDX, 0, msg) -2441 # . . push args -2442 68/push "F - test-parse-effective-address-base-displacement/scale"/imm32 -2443 68/push 0/imm32/none -2444 52/push-EDX -2445 # . . call -2446 e8/call check-ints-equal/disp32 -2447 # . . discard args -2448 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2449 # check-ints-equal(EBX, 3, msg) -2450 # . . push args -2451 68/push "F - test-parse-effective-address-base-displacement/displacement"/imm32 -2452 68/push 3/imm32 -2453 53/push-EBX -2454 # . . call -2455 e8/call check-ints-equal/disp32 -2456 # . . discard args -2457 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2458 # . epilog -2459 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -2460 5d/pop-to-EBP -2461 c3/return -2462 -2463 test-parse-effective-address-base-negative-displacement: -2464 # . prolog -2465 55/push-EBP -2466 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -2467 # var slice/ECX = "*(esi-3)" -2468 b8/copy-to-EAX "*(esi-3)"/imm32 -2469 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -2470 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 -2471 05/add-to-EAX 4/imm32 -2472 # . ECX = {EAX, ECX} -2473 51/push-ECX -2474 50/push-EAX -2475 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -2476 # EAX, ECX, EDX, EBX = parse-effective-address(slice) -2477 # . . push args -2478 51/push-ECX -2479 # . . call -2480 e8/call parse-effective-address/disp32 -2481 # . . discard args -2482 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2483 # slice clobbered beyond this point -2484 # check-ints-equal(EAX, 6, msg) -2485 # . . push args -2486 68/push "F - test-parse-effective-address-base-negative-displacement/base"/imm32 -2487 68/push 6/imm32/ESI -2488 50/push-EAX -2489 # . . call -2490 e8/call check-ints-equal/disp32 -2491 # . . discard args -2492 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2493 # check-ints-equal(ECX, 4, msg) -2494 # . . push args -2495 68/push "F - test-parse-effective-address-base-negative-displacement/index"/imm32 -2496 68/push 4/imm32/none -2497 51/push-ECX -2498 # . . call -2499 e8/call check-ints-equal/disp32 -2500 # . . discard args -2501 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2502 # check-ints-equal(EDX, 0, msg) -2503 # . . push args -2504 68/push "F - test-parse-effective-address-base-negative-displacement/scale"/imm32 -2505 68/push 0/imm32/none -2506 52/push-EDX -2507 # . . call -2508 e8/call check-ints-equal/disp32 -2509 # . . discard args -2510 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2511 # check-ints-equal(EBX, -3, msg) -2512 # . . push args -2513 68/push "F - test-parse-effective-address-base-negative-displacement/displacement"/imm32 -2514 68/push -3/imm32 -2515 53/push-EBX -2516 # . . call -2517 e8/call check-ints-equal/disp32 -2518 # . . discard args -2519 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2520 # . epilog -2521 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -2522 5d/pop-to-EBP -2523 c3/return -2524 -2525 test-parse-effective-address-base-index: -2526 # . prolog -2527 55/push-EBP -2528 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -2529 # var slice/ECX = "*(esi+ecx)" -2530 b8/copy-to-EAX "*(esi+ecx)"/imm32 -2531 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -2532 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 -2533 05/add-to-EAX 4/imm32 -2534 # . ECX = {EAX, ECX} -2535 51/push-ECX -2536 50/push-EAX -2537 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -2538 # EAX, ECX, EDX, EBX = parse-effective-address(slice) -2539 # . . push args -2540 51/push-ECX -2541 # . . call -2542 e8/call parse-effective-address/disp32 -2543 # . . discard args -2544 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2545 # slice clobbered beyond this point -2546 # check-ints-equal(EAX, 6, msg) -2547 # . . push args -2548 68/push "F - test-parse-effective-address-base-index/base"/imm32 -2549 68/push 6/imm32/ESI -2550 50/push-EAX -2551 # . . call -2552 e8/call check-ints-equal/disp32 -2553 # . . discard args -2554 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2555 # check-ints-equal(ECX, 1, msg) -2556 # . . push args -2557 68/push "F - test-parse-effective-address-base-index/index"/imm32 -2558 68/push 1/imm32/none -2559 51/push-ECX -2560 # . . call -2561 e8/call check-ints-equal/disp32 -2562 # . . discard args -2563 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2564 # check-ints-equal(EDX, 0, msg) -2565 # . . push args -2566 68/push "F - test-parse-effective-address-base-index/scale"/imm32 -2567 68/push 0/imm32/none -2568 52/push-EDX -2569 # . . call -2570 e8/call check-ints-equal/disp32 -2571 # . . discard args -2572 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2573 # check-ints-equal(EBX, 0, msg) -2574 # . . push args -2575 68/push "F - test-parse-effective-address-base-index/displacement"/imm32 -2576 68/push 0/imm32 -2577 53/push-EBX -2578 # . . call -2579 e8/call check-ints-equal/disp32 -2580 # . . discard args -2581 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2582 # . epilog -2583 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -2584 5d/pop-to-EBP -2585 c3/return -2586 -2587 test-parse-effective-address-base-index-scale: -2588 # . prolog -2589 55/push-EBP -2590 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -2591 # var slice/ECX = "*(esi+ecx<<2)" -2592 b8/copy-to-EAX "*(esi+ecx<<2)"/imm32 -2593 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -2594 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 -2595 05/add-to-EAX 4/imm32 -2596 # . ECX = {EAX, ECX} -2597 51/push-ECX -2598 50/push-EAX -2599 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -2600 # EAX, ECX, EDX, EBX = parse-effective-address(slice) -2601 # . . push args -2602 51/push-ECX -2603 # . . call -2604 e8/call parse-effective-address/disp32 -2605 # . . discard args -2606 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2607 # slice clobbered beyond this point -2608 # check-ints-equal(EAX, 6, msg) -2609 # . . push args -2610 68/push "F - test-parse-effective-address-base-index-scale/base"/imm32 -2611 68/push 6/imm32/ESI -2612 50/push-EAX -2613 # . . call -2614 e8/call check-ints-equal/disp32 -2615 # . . discard args -2616 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2617 # check-ints-equal(ECX, 1, msg) -2618 # . . push args -2619 68/push "F - test-parse-effective-address-base-index-scale/index"/imm32 -2620 68/push 1/imm32/none -2621 51/push-ECX -2622 # . . call -2623 e8/call check-ints-equal/disp32 -2624 # . . discard args -2625 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2626 # check-ints-equal(EDX, 2, msg) -2627 # . . push args -2628 68/push "F - test-parse-effective-address-base-index-scale/scale"/imm32 -2629 68/push 2/imm32 -2630 52/push-EDX -2631 # . . call -2632 e8/call check-ints-equal/disp32 -2633 # . . discard args -2634 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2635 # check-ints-equal(EBX, 0, msg) -2636 # . . push args -2637 68/push "F - test-parse-effective-address-base-index-scale/displacement"/imm32 -2638 68/push 0/imm32 -2639 53/push-EBX -2640 # . . call -2641 e8/call check-ints-equal/disp32 -2642 # . . discard args -2643 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2644 # . epilog -2645 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -2646 5d/pop-to-EBP -2647 c3/return -2648 -2649 test-parse-effective-address-base-index-scale-displacement: -2650 # . prolog -2651 55/push-EBP -2652 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -2653 # var slice/ECX = "*(esi + ecx<<2 - 0x34)" -2654 b8/copy-to-EAX "*(esi + ecx<<2 - 0x34)"/imm32 -2655 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -2656 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 -2657 05/add-to-EAX 4/imm32 -2658 # . ECX = {EAX, ECX} -2659 51/push-ECX -2660 50/push-EAX -2661 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -2662 # EAX, ECX, EDX, EBX = parse-effective-address(slice) -2663 # . . push args -2664 51/push-ECX -2665 # . . call -2666 e8/call parse-effective-address/disp32 -2667 # . . discard args -2668 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2669 # slice clobbered beyond this point -2670 # check-ints-equal(EAX, 6, msg) -2671 # . . push args -2672 68/push "F - test-parse-effective-address-base-index-scale/base"/imm32 -2673 68/push 6/imm32/ESI -2674 50/push-EAX -2675 # . . call -2676 e8/call check-ints-equal/disp32 -2677 # . . discard args -2678 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2679 # check-ints-equal(ECX, 1, msg) -2680 # . . push args -2681 68/push "F - test-parse-effective-address-base-index-scale/index"/imm32 -2682 68/push 1/imm32/none -2683 51/push-ECX -2684 # . . call -2685 e8/call check-ints-equal/disp32 -2686 # . . discard args -2687 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2688 # check-ints-equal(EDX, 2, msg) -2689 # . . push args -2690 68/push "F - test-parse-effective-address-base-index-scale/scale"/imm32 -2691 68/push 2/imm32 -2692 52/push-EDX -2693 # . . call -2694 e8/call check-ints-equal/disp32 -2695 # . . discard args -2696 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2697 # check-ints-equal(EBX, -0x34, msg) -2698 # . . push args -2699 68/push "F - test-parse-effective-address-base-index-scale/displacement"/imm32 -2700 68/push -0x34/imm32 -2701 53/push-EBX -2702 # . . call -2703 e8/call check-ints-equal/disp32 -2704 # . . discard args -2705 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2706 # . epilog -2707 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -2708 5d/pop-to-EBP -2709 c3/return -2710 -2711 # Code generation: -2712 # if index is none and disp is 0, then mod = 0 and rm32 = base -2713 # if index is none, then mod = 2 and rm32 = base and disp32 = disp -2714 # if index is not none, then mod = 2 and rm32 = 4 and base = base and index = index and disp32 = disp -2715 emit-indirect-mode: # out : (address buffered-file), base : int, index : int, scale : int, disp : int -2716 # . prolog -2717 55/push-EBP -2718 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -2719 $emit-indirect-mode:check-for-sib: -2720 # if (index == 4/none) goto next check -2721 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 4/imm32 # compare *(EBP+16) -2722 0f 84/jump-if-equal $emit-indirect-mode:check-for-disp/disp32 -2723 $emit-indirect-mode:emit-sib: -2724 # emit(out, "2/mod/indirect 4/rm32/sib " base "/base " index "/index " scale "/scale " disp "/disp32") -2725 # . write-buffered(out, "2/mod/*+disp32 4/rm32/sib ") -2726 # . . push args -2727 68/push "2/mod/*+disp32 4/rm32/sib "/imm32 -2728 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2729 # . . call -2730 e8/call write-buffered/disp32 -2731 # . . discard args -2732 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2733 # . print-int32-buffered(out, base) -2734 # . . push args -2735 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -2736 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2737 # . . call -2738 e8/call print-int32-buffered/disp32 -2739 # . . discard args -2740 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2741 # . write-buffered(out, "/base ") -2742 # . . push args -2743 68/push "/base "/imm32 -2744 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2745 # . . call -2746 e8/call write-buffered/disp32 -2747 # . . discard args -2748 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2749 # . print-int32-buffered(out, index) -2750 # . . push args -2751 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) -2752 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2753 # . . call -2754 e8/call print-int32-buffered/disp32 -2755 # . . discard args -2756 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2757 # . write-buffered(out, "/index ") -2758 # . . push args -2759 68/push "/index "/imm32 -2760 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2761 # . . call -2762 e8/call write-buffered/disp32 -2763 # . . discard args -2764 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2765 # . print-int32-buffered(out, scale) -2766 # . . push args -2767 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x14/disp8 . # push *(EBP+20) -2768 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2377 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2378 # . syscall(exit, 1) +2379 bb/copy-to-EBX 1/imm32 +2380 b8/copy-to-EAX 1/imm32/exit +2381 cd/syscall 0x80/imm8 +2382 # never gets here +2383 +2384 # assumes 'in' starts with a register name, and returns pointer to its code +2385 # side-effect: modifies 'in' to scan past the initial register name +2386 next-register: # in : (address slice) -> reg/EAX : int +2387 # . prolog +2388 55/push-EBP +2389 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2390 # . save registers +2391 51/push-ECX +2392 56/push-ESI +2393 # ESI = in +2394 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +2395 # var reg-slice/ECX : (address slice) = {in->start, in->start + 3} +2396 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX +2397 05/add-to-EAX 3/imm32 +2398 50/push-EAX +2399 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI +2400 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2401 # in->start += 3 +2402 81 0/subop/add 0/mod/indirect 6/rm32/ESI . . . . . 3/imm32 # add to *ESI +2403 # EAX = get-slice(Registers, word, row-size=8) +2404 # . . push args +2405 68/push "next-register"/imm32 +2406 68/push 8/imm32/row-size +2407 51/push-ECX +2408 68/push Registers/imm32 +2409 # . . call +2410 e8/call get-slice/disp32 +2411 # . . discard args +2412 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +2413 $next-register:end: +2414 # reclaim locals +2415 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2416 # . restore registers +2417 5e/pop-to-ESI +2418 59/pop-to-ECX +2419 # . epilog +2420 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2421 5d/pop-to-EBP +2422 c3/return +2423 +2424 test-parse-effective-address-simple: +2425 # . prolog +2426 55/push-EBP +2427 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2428 # var slice/ECX = "*esi" +2429 b8/copy-to-EAX "*esi"/imm32 +2430 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2431 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 +2432 05/add-to-EAX 4/imm32 +2433 # . ECX = {EAX, ECX} +2434 51/push-ECX +2435 50/push-EAX +2436 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2437 # EAX, ECX, EDX, EBX = parse-effective-address(slice) +2438 # . . push args +2439 51/push-ECX +2440 # . . call +2441 e8/call parse-effective-address/disp32 +2442 # . . discard args +2443 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2444 # slice clobbered beyond this point +2445 # check-ints-equal(EAX, 6, msg) +2446 # . . push args +2447 68/push "F - test-parse-effective-address-simple/base"/imm32 +2448 68/push 6/imm32/ESI +2449 50/push-EAX +2450 # . . call +2451 e8/call check-ints-equal/disp32 +2452 # . . discard args +2453 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2454 # check-ints-equal(ECX, 4, msg) +2455 # . . push args +2456 68/push "F - test-parse-effective-address-simple/index"/imm32 +2457 68/push 4/imm32/none +2458 51/push-ECX +2459 # . . call +2460 e8/call check-ints-equal/disp32 +2461 # . . discard args +2462 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2463 # check-ints-equal(EDX, 0, msg) +2464 # . . push args +2465 68/push "F - test-parse-effective-address-simple/scale"/imm32 +2466 68/push 0/imm32/none +2467 52/push-EDX +2468 # . . call +2469 e8/call check-ints-equal/disp32 +2470 # . . discard args +2471 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2472 # check-ints-equal(EBX, 0, msg) +2473 # . . push args +2474 68/push "F - test-parse-effective-address-simple/displacement"/imm32 +2475 68/push 0/imm32/none +2476 53/push-EBX +2477 # . . call +2478 e8/call check-ints-equal/disp32 +2479 # . . discard args +2480 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2481 # . epilog +2482 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2483 5d/pop-to-EBP +2484 c3/return +2485 +2486 test-parse-effective-address-base: +2487 # . prolog +2488 55/push-EBP +2489 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2490 # var slice/ECX = "*(esi )" +2491 b8/copy-to-EAX "*(esi )"/imm32 +2492 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2493 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 +2494 05/add-to-EAX 4/imm32 +2495 # . ECX = {EAX, ECX} +2496 51/push-ECX +2497 50/push-EAX +2498 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2499 # EAX, ECX, EDX, EBX = parse-effective-address(slice) +2500 # . . push args +2501 51/push-ECX +2502 # . . call +2503 e8/call parse-effective-address/disp32 +2504 # . . discard args +2505 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2506 # slice clobbered beyond this point +2507 # check-ints-equal(EAX, 6, msg) +2508 # . . push args +2509 68/push "F - test-parse-effective-address-base/base"/imm32 +2510 68/push 6/imm32/ESI +2511 50/push-EAX +2512 # . . call +2513 e8/call check-ints-equal/disp32 +2514 # . . discard args +2515 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2516 # check-ints-equal(ECX, 4, msg) +2517 # . . push args +2518 68/push "F - test-parse-effective-address-base/index"/imm32 +2519 68/push 4/imm32/none +2520 51/push-ECX +2521 # . . call +2522 e8/call check-ints-equal/disp32 +2523 # . . discard args +2524 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2525 # check-ints-equal(EDX, 0, msg) +2526 # . . push args +2527 68/push "F - test-parse-effective-address-base/scale"/imm32 +2528 68/push 0/imm32/none +2529 52/push-EDX +2530 # . . call +2531 e8/call check-ints-equal/disp32 +2532 # . . discard args +2533 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2534 # check-ints-equal(EBX, 0, msg) +2535 # . . push args +2536 68/push "F - test-parse-effective-address-base/displacement"/imm32 +2537 68/push 0/imm32/none +2538 53/push-EBX +2539 # . . call +2540 e8/call check-ints-equal/disp32 +2541 # . . discard args +2542 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2543 # . epilog +2544 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2545 5d/pop-to-EBP +2546 c3/return +2547 +2548 test-parse-effective-address-base-displacement: +2549 # . prolog +2550 55/push-EBP +2551 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2552 # var slice/ECX = "*(esi+3)" +2553 b8/copy-to-EAX "*(esi+3)"/imm32 +2554 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2555 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 +2556 05/add-to-EAX 4/imm32 +2557 # . ECX = {EAX, ECX} +2558 51/push-ECX +2559 50/push-EAX +2560 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2561 # EAX, ECX, EDX, EBX = parse-effective-address(slice) +2562 # . . push args +2563 51/push-ECX +2564 # . . call +2565 e8/call parse-effective-address/disp32 +2566 # . . discard args +2567 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2568 # slice clobbered beyond this point +2569 # check-ints-equal(EAX, 6, msg) +2570 # . . push args +2571 68/push "F - test-parse-effective-address-base-displacement/base"/imm32 +2572 68/push 6/imm32/ESI +2573 50/push-EAX +2574 # . . call +2575 e8/call check-ints-equal/disp32 +2576 # . . discard args +2577 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2578 # check-ints-equal(ECX, 4, msg) +2579 # . . push args +2580 68/push "F - test-parse-effective-address-base-displacement/index"/imm32 +2581 68/push 4/imm32/none +2582 51/push-ECX +2583 # . . call +2584 e8/call check-ints-equal/disp32 +2585 # . . discard args +2586 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2587 # check-ints-equal(EDX, 0, msg) +2588 # . . push args +2589 68/push "F - test-parse-effective-address-base-displacement/scale"/imm32 +2590 68/push 0/imm32/none +2591 52/push-EDX +2592 # . . call +2593 e8/call check-ints-equal/disp32 +2594 # . . discard args +2595 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2596 # check-ints-equal(EBX, 3, msg) +2597 # . . push args +2598 68/push "F - test-parse-effective-address-base-displacement/displacement"/imm32 +2599 68/push 3/imm32 +2600 53/push-EBX +2601 # . . call +2602 e8/call check-ints-equal/disp32 +2603 # . . discard args +2604 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2605 # . epilog +2606 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2607 5d/pop-to-EBP +2608 c3/return +2609 +2610 test-parse-effective-address-base-negative-displacement: +2611 # . prolog +2612 55/push-EBP +2613 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2614 # var slice/ECX = "*(esi-3)" +2615 b8/copy-to-EAX "*(esi-3)"/imm32 +2616 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2617 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 +2618 05/add-to-EAX 4/imm32 +2619 # . ECX = {EAX, ECX} +2620 51/push-ECX +2621 50/push-EAX +2622 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2623 # EAX, ECX, EDX, EBX = parse-effective-address(slice) +2624 # . . push args +2625 51/push-ECX +2626 # . . call +2627 e8/call parse-effective-address/disp32 +2628 # . . discard args +2629 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2630 # slice clobbered beyond this point +2631 # check-ints-equal(EAX, 6, msg) +2632 # . . push args +2633 68/push "F - test-parse-effective-address-base-negative-displacement/base"/imm32 +2634 68/push 6/imm32/ESI +2635 50/push-EAX +2636 # . . call +2637 e8/call check-ints-equal/disp32 +2638 # . . discard args +2639 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2640 # check-ints-equal(ECX, 4, msg) +2641 # . . push args +2642 68/push "F - test-parse-effective-address-base-negative-displacement/index"/imm32 +2643 68/push 4/imm32/none +2644 51/push-ECX +2645 # . . call +2646 e8/call check-ints-equal/disp32 +2647 # . . discard args +2648 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2649 # check-ints-equal(EDX, 0, msg) +2650 # . . push args +2651 68/push "F - test-parse-effective-address-base-negative-displacement/scale"/imm32 +2652 68/push 0/imm32/none +2653 52/push-EDX +2654 # . . call +2655 e8/call check-ints-equal/disp32 +2656 # . . discard args +2657 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2658 # check-ints-equal(EBX, -3, msg) +2659 # . . push args +2660 68/push "F - test-parse-effective-address-base-negative-displacement/displacement"/imm32 +2661 68/push -3/imm32 +2662 53/push-EBX +2663 # . . call +2664 e8/call check-ints-equal/disp32 +2665 # . . discard args +2666 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2667 # . epilog +2668 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2669 5d/pop-to-EBP +2670 c3/return +2671 +2672 test-parse-effective-address-base-index: +2673 # . prolog +2674 55/push-EBP +2675 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2676 # var slice/ECX = "*(esi+ecx)" +2677 b8/copy-to-EAX "*(esi+ecx)"/imm32 +2678 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2679 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 +2680 05/add-to-EAX 4/imm32 +2681 # . ECX = {EAX, ECX} +2682 51/push-ECX +2683 50/push-EAX +2684 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2685 # EAX, ECX, EDX, EBX = parse-effective-address(slice) +2686 # . . push args +2687 51/push-ECX +2688 # . . call +2689 e8/call parse-effective-address/disp32 +2690 # . . discard args +2691 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2692 # slice clobbered beyond this point +2693 # check-ints-equal(EAX, 6, msg) +2694 # . . push args +2695 68/push "F - test-parse-effective-address-base-index/base"/imm32 +2696 68/push 6/imm32/ESI +2697 50/push-EAX +2698 # . . call +2699 e8/call check-ints-equal/disp32 +2700 # . . discard args +2701 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2702 # check-ints-equal(ECX, 1, msg) +2703 # . . push args +2704 68/push "F - test-parse-effective-address-base-index/index"/imm32 +2705 68/push 1/imm32/none +2706 51/push-ECX +2707 # . . call +2708 e8/call check-ints-equal/disp32 +2709 # . . discard args +2710 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2711 # check-ints-equal(EDX, 0, msg) +2712 # . . push args +2713 68/push "F - test-parse-effective-address-base-index/scale"/imm32 +2714 68/push 0/imm32/none +2715 52/push-EDX +2716 # . . call +2717 e8/call check-ints-equal/disp32 +2718 # . . discard args +2719 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2720 # check-ints-equal(EBX, 0, msg) +2721 # . . push args +2722 68/push "F - test-parse-effective-address-base-index/displacement"/imm32 +2723 68/push 0/imm32 +2724 53/push-EBX +2725 # . . call +2726 e8/call check-ints-equal/disp32 +2727 # . . discard args +2728 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2729 # . epilog +2730 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2731 5d/pop-to-EBP +2732 c3/return +2733 +2734 test-parse-effective-address-base-index-scale: +2735 # . prolog +2736 55/push-EBP +2737 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2738 # var slice/ECX = "*(esi+ecx<<2)" +2739 b8/copy-to-EAX "*(esi+ecx<<2)"/imm32 +2740 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2741 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 +2742 05/add-to-EAX 4/imm32 +2743 # . ECX = {EAX, ECX} +2744 51/push-ECX +2745 50/push-EAX +2746 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2747 # EAX, ECX, EDX, EBX = parse-effective-address(slice) +2748 # . . push args +2749 51/push-ECX +2750 # . . call +2751 e8/call parse-effective-address/disp32 +2752 # . . discard args +2753 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2754 # slice clobbered beyond this point +2755 # check-ints-equal(EAX, 6, msg) +2756 # . . push args +2757 68/push "F - test-parse-effective-address-base-index-scale/base"/imm32 +2758 68/push 6/imm32/ESI +2759 50/push-EAX +2760 # . . call +2761 e8/call check-ints-equal/disp32 +2762 # . . discard args +2763 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2764 # check-ints-equal(ECX, 1, msg) +2765 # . . push args +2766 68/push "F - test-parse-effective-address-base-index-scale/index"/imm32 +2767 68/push 1/imm32/none +2768 51/push-ECX 2769 # . . call -2770 e8/call print-int32-buffered/disp32 +2770 e8/call check-ints-equal/disp32 2771 # . . discard args -2772 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2773 # . write-buffered(out, "/scale ") +2772 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2773 # check-ints-equal(EDX, 2, msg) 2774 # . . push args -2775 68/push "/scale "/imm32 -2776 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2777 # . . call -2778 e8/call write-buffered/disp32 -2779 # . . discard args -2780 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2781 # . print-int32-buffered(out, disp) -2782 # . . push args -2783 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x18/disp8 . # push *(EBP+24) -2784 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2785 # . . call -2786 e8/call print-int32-buffered/disp32 -2787 # . . discard args -2788 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2789 # . write-buffered(out, "/disp32") -2790 # . . push args -2791 68/push "/disp32"/imm32 -2792 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2793 # . . call -2794 e8/call write-buffered/disp32 -2795 # . . discard args -2796 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2797 e9/jump $emit-indirect-mode:end/disp32 -2798 $emit-indirect-mode:check-for-disp: -2799 # if (disp == 0) goto next check -2800 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0x18/disp8 0/imm32 # compare *(EBP+24) -2801 74/jump-if-equal $emit-indirect-mode:emit-indirect/disp8 -2802 $emit-indirect-mode:emit-disp: -2803 # emit(out, "2/mod/*+disp32 " base "/rm32 " disp "/disp32") -2804 # . write-buffered(out, "2/mod/*+disp32 ") -2805 # . . push args -2806 68/push "2/mod/*+disp32 "/imm32 -2807 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2808 # . . call -2809 e8/call write-buffered/disp32 -2810 # . . discard args -2811 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2812 # . print-int32-buffered(out, base) -2813 # . . push args -2814 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -2815 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2816 # . . call -2817 e8/call print-int32-buffered/disp32 -2818 # . . discard args -2819 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2820 # . write-buffered(out, "/rm32 ") -2821 # . . push args -2822 68/push "/rm32 "/imm32 -2823 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2824 # . . call -2825 e8/call write-buffered/disp32 -2826 # . . discard args -2827 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2828 # . print-int32-buffered(out, disp) -2829 # . . push args -2830 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x18/disp8 . # push *(EBP+24) -2831 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2832 # . . call -2833 e8/call print-int32-buffered/disp32 -2834 # . . discard args -2835 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2836 # . write-buffered(out, "/disp32") -2837 # . . push args -2838 68/push "/disp32"/imm32 -2839 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2775 68/push "F - test-parse-effective-address-base-index-scale/scale"/imm32 +2776 68/push 2/imm32 +2777 52/push-EDX +2778 # . . call +2779 e8/call check-ints-equal/disp32 +2780 # . . discard args +2781 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2782 # check-ints-equal(EBX, 0, msg) +2783 # . . push args +2784 68/push "F - test-parse-effective-address-base-index-scale/displacement"/imm32 +2785 68/push 0/imm32 +2786 53/push-EBX +2787 # . . call +2788 e8/call check-ints-equal/disp32 +2789 # . . discard args +2790 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2791 # . epilog +2792 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2793 5d/pop-to-EBP +2794 c3/return +2795 +2796 test-parse-effective-address-base-index-scale-displacement: +2797 # . prolog +2798 55/push-EBP +2799 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2800 # var slice/ECX = "*(esi + ecx<<2 - 0x34)" +2801 b8/copy-to-EAX "*(esi + ecx<<2 - 0x34)"/imm32 +2802 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2803 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 +2804 05/add-to-EAX 4/imm32 +2805 # . ECX = {EAX, ECX} +2806 51/push-ECX +2807 50/push-EAX +2808 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2809 # EAX, ECX, EDX, EBX = parse-effective-address(slice) +2810 # . . push args +2811 51/push-ECX +2812 # . . call +2813 e8/call parse-effective-address/disp32 +2814 # . . discard args +2815 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2816 # slice clobbered beyond this point +2817 # check-ints-equal(EAX, 6, msg) +2818 # . . push args +2819 68/push "F - test-parse-effective-address-base-index-scale/base"/imm32 +2820 68/push 6/imm32/ESI +2821 50/push-EAX +2822 # . . call +2823 e8/call check-ints-equal/disp32 +2824 # . . discard args +2825 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2826 # check-ints-equal(ECX, 1, msg) +2827 # . . push args +2828 68/push "F - test-parse-effective-address-base-index-scale/index"/imm32 +2829 68/push 1/imm32/none +2830 51/push-ECX +2831 # . . call +2832 e8/call check-ints-equal/disp32 +2833 # . . discard args +2834 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2835 # check-ints-equal(EDX, 2, msg) +2836 # . . push args +2837 68/push "F - test-parse-effective-address-base-index-scale/scale"/imm32 +2838 68/push 2/imm32 +2839 52/push-EDX 2840 # . . call -2841 e8/call write-buffered/disp32 +2841 e8/call check-ints-equal/disp32 2842 # . . discard args -2843 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2844 eb/jump $emit-indirect-mode:end/disp8 -2845 $emit-indirect-mode:emit-indirect: -2846 # emit(out, "0/mod/indirect " base "/rm32") -2847 # . write-buffered(out, "0/mod/indirect ") -2848 # . . push args -2849 68/push "0/mod/indirect "/imm32 -2850 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2851 # . . call -2852 e8/call write-buffered/disp32 -2853 # . . discard args -2854 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2855 # . print-int32-buffered(out, base) -2856 # . . push args -2857 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -2858 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2859 # . . call -2860 e8/call print-int32-buffered/disp32 -2861 # . . discard args -2862 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2863 # . write-buffered(out, "/rm32") -2864 # . . push args -2865 68/push "/rm32"/imm32 -2866 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2867 # . . call -2868 e8/call write-buffered/disp32 -2869 # . . discard args -2870 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2871 $emit-indirect-mode:end: -2872 # . epilog -2873 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -2874 5d/pop-to-EBP -2875 c3/return -2876 -2877 test-emit-indirect-mode: -2878 # . prolog -2879 55/push-EBP -2880 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -2881 # setup -2882 # . clear-stream(_test-output-stream) -2883 # . . push args -2884 68/push _test-output-stream/imm32 -2885 # . . call -2886 e8/call clear-stream/disp32 -2887 # . . discard args -2888 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2889 # . clear-stream(_test-output-buffered-file+4) -2890 # . . push args -2891 b8/copy-to-EAX _test-output-buffered-file/imm32 -2892 05/add-to-EAX 4/imm32 -2893 50/push-EAX -2894 # . . call -2895 e8/call clear-stream/disp32 -2896 # . . discard args -2897 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2898 # emit-indirect-mode(_test-output-buffered-file, 0, 4/none, 0, 0) -2899 # . . write args -2900 68/push 0/imm32/.disp -2901 68/push 0/imm32/.scale -2902 68/push 4/imm32/.index/none -2903 68/push 0/imm32/.base -2904 68/push _test-output-buffered-file/imm32 -2905 # . . call -2906 e8/call emit-indirect-mode/disp32 -2907 # . . discard args -2908 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP -2909 # . flush(_test-output-buffered-file) -2910 # . . push args -2911 68/push _test-output-buffered-file/imm32 -2912 # . . call -2913 e8/call flush/disp32 -2914 # . . discard args -2915 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2916 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -2942 # check-stream-equal(_test-output-stream, "0/mod/indirect 0/rm32", msg) -2943 # . . push args -2944 68/push "F - test-emit-indirect-mode"/imm32 -2945 68/push "0/mod/indirect 0x00000000/rm32"/imm32 -2946 68/push _test-output-stream/imm32 -2947 # . . call -2948 e8/call check-stream-equal/disp32 -2949 # . . discard args -2950 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2951 # . epilog -2952 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -2953 5d/pop-to-EBP -2954 c3/return -2955 -2956 test-emit-indirect-mode-2: -2957 # . prolog -2958 55/push-EBP -2959 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -2960 # setup -2961 # . clear-stream(_test-output-stream) -2962 # . . push args -2963 68/push _test-output-stream/imm32 -2964 # . . call -2965 e8/call clear-stream/disp32 -2966 # . . discard args -2967 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2968 # . clear-stream(_test-output-buffered-file+4) -2969 # . . push args -2970 b8/copy-to-EAX _test-output-buffered-file/imm32 -2971 05/add-to-EAX 4/imm32 -2972 50/push-EAX -2973 # . . call -2974 e8/call clear-stream/disp32 -2975 # . . discard args -2976 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2977 # emit-indirect-mode(_test-output-buffered-file, 6, 4/none, 0, 0) -2978 # . . write args -2979 68/push 0/imm32/.disp -2980 68/push 0/imm32/.scale -2981 68/push 4/imm32/.index/none -2982 68/push 7/imm32/.base -2983 68/push _test-output-buffered-file/imm32 -2984 # . . call -2985 e8/call emit-indirect-mode/disp32 -2986 # . . discard args -2987 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP -2988 # . flush(_test-output-buffered-file) -2989 # . . push args -2990 68/push _test-output-buffered-file/imm32 -2991 # . . call -2992 e8/call flush/disp32 -2993 # . . discard args -2994 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2995 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -3021 # check-stream-equal(_test-output-stream, "0/mod/indirect 7/rm32", msg) -3022 # . . push args -3023 68/push "F - test-emit-indirect-mode-2"/imm32 -3024 68/push "0/mod/indirect 0x00000007/rm32"/imm32 -3025 68/push _test-output-stream/imm32 -3026 # . . call -3027 e8/call check-stream-equal/disp32 -3028 # . . discard args -3029 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3030 # . epilog -3031 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3032 5d/pop-to-EBP -3033 c3/return -3034 -3035 test-emit-indirect-mode-with-disp: -3036 # . prolog -3037 55/push-EBP -3038 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3039 # setup -3040 # . clear-stream(_test-output-stream) -3041 # . . push args -3042 68/push _test-output-stream/imm32 -3043 # . . call -3044 e8/call clear-stream/disp32 -3045 # . . discard args -3046 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3047 # . clear-stream(_test-output-buffered-file+4) -3048 # . . push args -3049 b8/copy-to-EAX _test-output-buffered-file/imm32 -3050 05/add-to-EAX 4/imm32 -3051 50/push-EAX +2843 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2844 # check-ints-equal(EBX, -0x34, msg) +2845 # . . push args +2846 68/push "F - test-parse-effective-address-base-index-scale/displacement"/imm32 +2847 68/push -0x34/imm32 +2848 53/push-EBX +2849 # . . call +2850 e8/call check-ints-equal/disp32 +2851 # . . discard args +2852 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2853 # . epilog +2854 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2855 5d/pop-to-EBP +2856 c3/return +2857 +2858 # Code generation: +2859 # if index is none and disp is 0, then mod = 0 and rm32 = base +2860 # if index is none, then mod = 2 and rm32 = base and disp32 = disp +2861 # if index is not none, then mod = 2 and rm32 = 4 and base = base and index = index and disp32 = disp +2862 emit-indirect-mode: # out : (address buffered-file), base : int, index : int, scale : int, disp : int +2863 # . prolog +2864 55/push-EBP +2865 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2866 $emit-indirect-mode:check-for-sib: +2867 # if (index == 4/none) goto next check +2868 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 4/imm32 # compare *(EBP+16) +2869 0f 84/jump-if-equal $emit-indirect-mode:check-for-disp/disp32 +2870 $emit-indirect-mode:emit-sib: +2871 # emit(out, "2/mod/indirect 4/rm32/sib " base "/base " index "/index " scale "/scale " disp "/disp32") +2872 # . write-buffered(out, "2/mod/*+disp32 4/rm32/sib ") +2873 # . . push args +2874 68/push "2/mod/*+disp32 4/rm32/sib "/imm32 +2875 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2876 # . . call +2877 e8/call write-buffered/disp32 +2878 # . . discard args +2879 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2880 # . print-int32-buffered(out, base) +2881 # . . push args +2882 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +2883 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2884 # . . call +2885 e8/call print-int32-buffered/disp32 +2886 # . . discard args +2887 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2888 # . write-buffered(out, "/base ") +2889 # . . push args +2890 68/push "/base "/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, index) +2897 # . . push args +2898 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) +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, "/index ") +2905 # . . push args +2906 68/push "/index "/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, scale) +2913 # . . push args +2914 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x14/disp8 . # push *(EBP+20) +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, "/scale ") +2921 # . . push args +2922 68/push "/scale "/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, disp) +2929 # . . push args +2930 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x18/disp8 . # push *(EBP+24) +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, "/disp32") +2937 # . . push args +2938 68/push "/disp32"/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 e9/jump $emit-indirect-mode:end/disp32 +2945 $emit-indirect-mode:check-for-disp: +2946 # if (disp == 0) goto next check +2947 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0x18/disp8 0/imm32 # compare *(EBP+24) +2948 74/jump-if-equal $emit-indirect-mode:emit-indirect/disp8 +2949 $emit-indirect-mode:emit-disp: +2950 # emit(out, "2/mod/*+disp32 " base "/rm32 " disp "/disp32") +2951 # . write-buffered(out, "2/mod/*+disp32 ") +2952 # . . push args +2953 68/push "2/mod/*+disp32 "/imm32 +2954 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2955 # . . call +2956 e8/call write-buffered/disp32 +2957 # . . discard args +2958 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2959 # . print-int32-buffered(out, base) +2960 # . . push args +2961 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +2962 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2963 # . . call +2964 e8/call print-int32-buffered/disp32 +2965 # . . discard args +2966 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2967 # . write-buffered(out, "/rm32 ") +2968 # . . push args +2969 68/push "/rm32 "/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, disp) +2976 # . . push args +2977 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x18/disp8 . # push *(EBP+24) +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, "/disp32") +2984 # . . push args +2985 68/push "/disp32"/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 eb/jump $emit-indirect-mode:end/disp8 +2992 $emit-indirect-mode:emit-indirect: +2993 # emit(out, "0/mod/indirect " base "/rm32") +2994 # . write-buffered(out, "0/mod/indirect ") +2995 # . . push args +2996 68/push "0/mod/indirect "/imm32 +2997 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2998 # . . call +2999 e8/call write-buffered/disp32 +3000 # . . discard args +3001 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3002 # . print-int32-buffered(out, base) +3003 # . . push args +3004 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +3005 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +3006 # . . call +3007 e8/call print-int32-buffered/disp32 +3008 # . . discard args +3009 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3010 # . write-buffered(out, "/rm32") +3011 # . . push args +3012 68/push "/rm32"/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 $emit-indirect-mode:end: +3019 # . epilog +3020 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3021 5d/pop-to-EBP +3022 c3/return +3023 +3024 test-emit-indirect-mode: +3025 # . prolog +3026 55/push-EBP +3027 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3028 # setup +3029 # . clear-stream(_test-output-stream) +3030 # . . push args +3031 68/push _test-output-stream/imm32 +3032 # . . call +3033 e8/call clear-stream/disp32 +3034 # . . discard args +3035 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3036 # . clear-stream(_test-output-buffered-file+4) +3037 # . . push args +3038 b8/copy-to-EAX _test-output-buffered-file/imm32 +3039 05/add-to-EAX 4/imm32 +3040 50/push-EAX +3041 # . . call +3042 e8/call clear-stream/disp32 +3043 # . . discard args +3044 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3045 # emit-indirect-mode(_test-output-buffered-file, 0, 4/none, 0, 0) +3046 # . . write args +3047 68/push 0/imm32/.disp +3048 68/push 0/imm32/.scale +3049 68/push 4/imm32/.index/none +3050 68/push 0/imm32/.base +3051 68/push _test-output-buffered-file/imm32 3052 # . . call -3053 e8/call clear-stream/disp32 +3053 e8/call emit-indirect-mode/disp32 3054 # . . discard args -3055 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3056 # emit-indirect-mode(_test-output-buffered-file, 6, 4/none, 0, 4) -3057 # . . write args -3058 68/push 4/imm32/.disp -3059 68/push 0/imm32/.scale -3060 68/push 4/imm32/.index/none -3061 68/push 6/imm32/.base -3062 68/push _test-output-buffered-file/imm32 -3063 # . . call -3064 e8/call emit-indirect-mode/disp32 -3065 # . . discard args -3066 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP -3067 # . flush(_test-output-buffered-file) -3068 # . . push args -3069 68/push _test-output-buffered-file/imm32 -3070 # . . call -3071 e8/call flush/disp32 -3072 # . . discard args -3073 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3074 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -3100 # check-stream-equal(_test-output-stream, "2/mod/*+disp32 6/rm32 4/disp32", msg) -3101 # . . push args -3102 68/push "F - test-emit-indirect-mode-with-disp"/imm32 -3103 68/push "2/mod/*+disp32 0x00000006/rm32 0x00000004/disp32"/imm32 -3104 68/push _test-output-stream/imm32 -3105 # . . call -3106 e8/call check-stream-equal/disp32 -3107 # . . discard args -3108 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3109 # . epilog -3110 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3111 5d/pop-to-EBP -3112 c3/return -3113 -3114 test-emit-indirect-mode-with-disp-negative: -3115 # . prolog -3116 55/push-EBP -3117 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3118 # setup -3119 # . clear-stream(_test-output-stream) -3120 # . . push args -3121 68/push _test-output-stream/imm32 -3122 # . . call -3123 e8/call clear-stream/disp32 -3124 # . . discard args -3125 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3126 # . clear-stream(_test-output-buffered-file+4) -3127 # . . push args -3128 b8/copy-to-EAX _test-output-buffered-file/imm32 -3129 05/add-to-EAX 4/imm32 -3130 50/push-EAX +3055 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP +3056 # . flush(_test-output-buffered-file) +3057 # . . push args +3058 68/push _test-output-buffered-file/imm32 +3059 # . . call +3060 e8/call flush/disp32 +3061 # . . discard args +3062 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3063 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +3089 # check-stream-equal(_test-output-stream, "0/mod/indirect 0/rm32", msg) +3090 # . . push args +3091 68/push "F - test-emit-indirect-mode"/imm32 +3092 68/push "0/mod/indirect 0x00000000/rm32"/imm32 +3093 68/push _test-output-stream/imm32 +3094 # . . call +3095 e8/call check-stream-equal/disp32 +3096 # . . discard args +3097 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3098 # . epilog +3099 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3100 5d/pop-to-EBP +3101 c3/return +3102 +3103 test-emit-indirect-mode-2: +3104 # . prolog +3105 55/push-EBP +3106 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3107 # setup +3108 # . clear-stream(_test-output-stream) +3109 # . . push args +3110 68/push _test-output-stream/imm32 +3111 # . . call +3112 e8/call clear-stream/disp32 +3113 # . . discard args +3114 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3115 # . clear-stream(_test-output-buffered-file+4) +3116 # . . push args +3117 b8/copy-to-EAX _test-output-buffered-file/imm32 +3118 05/add-to-EAX 4/imm32 +3119 50/push-EAX +3120 # . . call +3121 e8/call clear-stream/disp32 +3122 # . . discard args +3123 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3124 # emit-indirect-mode(_test-output-buffered-file, 6, 4/none, 0, 0) +3125 # . . write args +3126 68/push 0/imm32/.disp +3127 68/push 0/imm32/.scale +3128 68/push 4/imm32/.index/none +3129 68/push 7/imm32/.base +3130 68/push _test-output-buffered-file/imm32 3131 # . . call -3132 e8/call clear-stream/disp32 +3132 e8/call emit-indirect-mode/disp32 3133 # . . discard args -3134 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3135 # emit-indirect-mode(_test-output-buffered-file, 6, 4/none, 0, -4) -3136 # . . write args -3137 68/push -4/imm32/.disp -3138 68/push 0/imm32/.scale -3139 68/push 4/imm32/.index/none -3140 68/push 6/imm32/.base -3141 68/push _test-output-buffered-file/imm32 -3142 # . . call -3143 e8/call emit-indirect-mode/disp32 -3144 # . . discard args -3145 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP -3146 # . flush(_test-output-buffered-file) -3147 # . . push args -3148 68/push _test-output-buffered-file/imm32 -3149 # . . call -3150 e8/call flush/disp32 -3151 # . . discard args -3152 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3153 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -3179 # check-stream-equal(_test-output-stream, "2/mod/*+disp32 6/rm32 -4/disp32", msg) -3180 # . . push args -3181 68/push "F - test-emit-indirect-mode-with-disp"/imm32 -3182 68/push "2/mod/*+disp32 0x00000006/rm32 0xfffffffc/disp32"/imm32 -3183 68/push _test-output-stream/imm32 -3184 # . . call -3185 e8/call check-stream-equal/disp32 -3186 # . . discard args -3187 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3188 # . epilog -3189 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3190 5d/pop-to-EBP -3191 c3/return -3192 -3193 test-emit-indirect-mode-with-sib: -3194 # . prolog -3195 55/push-EBP -3196 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3197 # setup -3198 # . clear-stream(_test-output-stream) -3199 # . . push args -3200 68/push _test-output-stream/imm32 -3201 # . . call -3202 e8/call clear-stream/disp32 -3203 # . . discard args -3204 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3205 # . clear-stream(_test-output-buffered-file+4) -3206 # . . push args -3207 b8/copy-to-EAX _test-output-buffered-file/imm32 -3208 05/add-to-EAX 4/imm32 -3209 50/push-EAX +3134 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP +3135 # . flush(_test-output-buffered-file) +3136 # . . push args +3137 68/push _test-output-buffered-file/imm32 +3138 # . . call +3139 e8/call flush/disp32 +3140 # . . discard args +3141 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3142 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +3168 # check-stream-equal(_test-output-stream, "0/mod/indirect 7/rm32", msg) +3169 # . . push args +3170 68/push "F - test-emit-indirect-mode-2"/imm32 +3171 68/push "0/mod/indirect 0x00000007/rm32"/imm32 +3172 68/push _test-output-stream/imm32 +3173 # . . call +3174 e8/call check-stream-equal/disp32 +3175 # . . discard args +3176 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3177 # . epilog +3178 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3179 5d/pop-to-EBP +3180 c3/return +3181 +3182 test-emit-indirect-mode-with-disp: +3183 # . prolog +3184 55/push-EBP +3185 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3186 # setup +3187 # . clear-stream(_test-output-stream) +3188 # . . push args +3189 68/push _test-output-stream/imm32 +3190 # . . call +3191 e8/call clear-stream/disp32 +3192 # . . discard args +3193 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3194 # . clear-stream(_test-output-buffered-file+4) +3195 # . . push args +3196 b8/copy-to-EAX _test-output-buffered-file/imm32 +3197 05/add-to-EAX 4/imm32 +3198 50/push-EAX +3199 # . . call +3200 e8/call clear-stream/disp32 +3201 # . . discard args +3202 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3203 # emit-indirect-mode(_test-output-buffered-file, 6, 4/none, 0, 4) +3204 # . . write args +3205 68/push 4/imm32/.disp +3206 68/push 0/imm32/.scale +3207 68/push 4/imm32/.index/none +3208 68/push 6/imm32/.base +3209 68/push _test-output-buffered-file/imm32 3210 # . . call -3211 e8/call clear-stream/disp32 +3211 e8/call emit-indirect-mode/disp32 3212 # . . discard args -3213 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3214 # emit-indirect-mode(_test-output-buffered-file, 6/base, 1/index, 2/scale, 4/disp) -3215 # . . write args -3216 68/push 4/imm32/.disp -3217 68/push 2/imm32/.scale -3218 68/push 1/imm32/.index -3219 68/push 6/imm32/.base -3220 68/push _test-output-buffered-file/imm32 -3221 # . . call -3222 e8/call emit-indirect-mode/disp32 -3223 # . . discard args -3224 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP -3225 # . flush(_test-output-buffered-file) -3226 # . . push args -3227 68/push _test-output-buffered-file/imm32 -3228 # . . call -3229 e8/call flush/disp32 -3230 # . . discard args -3231 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3232 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -3258 # check-stream-equal(_test-output-stream, "2/mod/indirect 4/rm32/sib 6/base 1/index 2/scale 4/disp", msg) -3259 # . . push args -3260 68/push "F - test-emit-indirect-mode-with-sib"/imm32 -3261 68/push "2/mod/*+disp32 4/rm32/sib 0x00000006/base 0x00000001/index 0x00000002/scale 0x00000004/disp32"/imm32 -3262 68/push _test-output-stream/imm32 -3263 # . . call -3264 e8/call check-stream-equal/disp32 -3265 # . . discard args -3266 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3267 # . epilog -3268 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3269 5d/pop-to-EBP -3270 c3/return -3271 -3272 # update line->read to ')' -3273 # line->read ends at ')' -3274 skip-until-close-paren: # line : (address stream) -3275 # . prolog -3276 55/push-EBP -3277 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3278 # . save registers -3279 50/push-EAX -3280 51/push-ECX -3281 52/push-EDX -3282 # ECX = line -3283 8b/copy 1/mod/*+disp8 5/rm32/EBP . . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX -3284 # EAX = skip-until-close-paren-in-slice(&line->data[line->read], &line->data[line->write]) -3285 # . . push &line->data[line->write] -3286 8b/copy 1/mod/*+disp8 1/rm32/ECX . . 2/r32/EDX 8/disp8 . # copy *(ECX+8) to EDX -3287 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 -3288 52/push-EDX -3289 # . . push &line->data[line->read] -3290 8b/copy 1/mod/*+disp8 1/rm32/ECX . . 2/r32/EDX 4/disp8 . # copy *(ECX+4) to EDX -3291 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 -3292 52/push-EDX -3293 # . . call -3294 e8/call skip-until-close-paren-in-slice/disp32 -3295 # . . discard args -3296 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3297 # line->read = EAX - line->data -3298 29/subtract 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # subtract ECX from EAX -3299 2d/subtract-from-EAX 0xc/imm32 -3300 89/copy 1/mod/*+disp8 1/rm32/ECX . . 0/r32/EAX 4/disp8 . # copy EAX to *(ECX+4) -3301 $skip-until-close-paren:end: -3302 # . restore registers -3303 5a/pop-to-EDX -3304 59/pop-to-ECX -3305 58/pop-to-EAX -3306 # . epilog -3307 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3308 5d/pop-to-EBP -3309 c3/return -3310 -3311 test-skip-until-close-paren: -3312 # . prolog -3313 55/push-EBP -3314 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3315 # setup -3316 # . clear-stream(_test-input-stream) -3317 # . . push args -3318 68/push _test-input-stream/imm32 -3319 # . . call -3320 e8/call clear-stream/disp32 -3321 # . . discard args -3322 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3323 # . write(_test-input-stream, "*(abc) def") -3324 # . indices: 0123 45 -3325 # . . push args -3326 68/push "*(abc) def"/imm32 -3327 68/push _test-input-stream/imm32 -3328 # . . call -3329 e8/call write/disp32 -3330 # . . discard args -3331 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3332 # precondition: line->read == 0 -3333 # . . push args -3334 68/push "F - test-skip-until-close-paren/precondition"/imm32 -3335 68/push 0/imm32 -3336 b8/copy-to-EAX _test-input-stream/imm32 -3337 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) -3338 # . . call -3339 e8/call check-ints-equal/disp32 -3340 # . . discard args -3341 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3342 # skip-until-close-paren(_test-input-stream) -3343 # . . push args -3344 68/push _test-input-stream/imm32 -3345 # . . call -3346 e8/call skip-until-close-paren/disp32 -3347 # . . discard args -3348 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3349 # check-ints-equal(line->read, 5, msg) -3350 # . . push args -3351 68/push "F - test-skip-until-close-paren"/imm32 -3352 68/push 5/imm32 -3353 b8/copy-to-EAX _test-input-stream/imm32 -3354 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) -3355 # . . call -3356 e8/call check-ints-equal/disp32 -3357 # . . discard args -3358 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3359 # . epilog -3360 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3361 5d/pop-to-EBP -3362 c3/return -3363 -3364 test-skip-until-close-paren-ignores-spaces: -3365 # . prolog -3366 55/push-EBP -3367 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3368 # setup -3369 # . clear-stream(_test-input-stream) -3370 # . . push args -3371 68/push _test-input-stream/imm32 -3372 # . . call -3373 e8/call clear-stream/disp32 -3374 # . . discard args -3375 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3376 # . write(_test-input-stream, "*(a b)/yz") -3377 # . . push args -3378 68/push "*(a b)/yz"/imm32 -3379 68/push _test-input-stream/imm32 -3380 # . . call -3381 e8/call write/disp32 -3382 # . . discard args -3383 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3384 # precondition: line->read == 0 -3385 # . . push args -3386 68/push "F - test-skip-until-close-paren-ignores-spaces/precondition"/imm32 -3387 68/push 0/imm32 -3388 b8/copy-to-EAX _test-input-stream/imm32 -3389 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) -3390 # . . call -3391 e8/call check-ints-equal/disp32 -3392 # . . discard args -3393 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3394 # skip-until-close-paren(_test-input-stream) -3395 # . . push args -3396 68/push _test-input-stream/imm32 -3397 # . . call -3398 e8/call skip-until-close-paren/disp32 -3399 # . . discard args -3400 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3401 # check-ints-equal(line->read, 5, msg) -3402 # . . push args -3403 68/push "F - test-skip-until-close-paren-ignores-spaces"/imm32 -3404 68/push 5/imm32 -3405 b8/copy-to-EAX _test-input-stream/imm32 -3406 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) -3407 # . . call -3408 e8/call check-ints-equal/disp32 -3409 # . . discard args -3410 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3411 # . epilog -3412 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3413 5d/pop-to-EBP -3414 c3/return -3415 -3416 test-skip-until-close-paren-works-from-mid-stream: -3417 # . prolog -3418 55/push-EBP -3419 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3420 # setup -3421 # . clear-stream(_test-input-stream) -3422 # . . push args -3423 68/push _test-input-stream/imm32 -3424 # . . call -3425 e8/call clear-stream/disp32 -3426 # . . discard args -3427 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3428 # . write(_test-input-stream, "0 *(a b)/yz") -3429 # . . push args -3430 68/push "0 *(a b)/yz"/imm32 -3431 68/push _test-input-stream/imm32 -3432 # . . call -3433 e8/call write/disp32 -3434 # . . discard args -3435 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3436 # precondition: _test-input-stream->read == 2 -3437 c7 0/subop/copy 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 2/imm32 # copy to *(EAX+4) -3438 # skip-until-close-paren(_test-input-stream) -3439 # . . push args -3440 68/push _test-input-stream/imm32 -3441 # . . call -3442 e8/call skip-until-close-paren/disp32 -3443 # . . discard args -3444 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3445 # check-ints-equal(_test-input-stream->read, 7, msg) -3446 # . . push args -3447 68/push "F - test-skip-until-close-paren-works-from-mid-stream"/imm32 -3448 68/push 7/imm32 -3449 b8/copy-to-EAX _test-input-stream/imm32 -3450 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) -3451 # . . call -3452 e8/call check-ints-equal/disp32 -3453 # . . discard args -3454 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3455 # . epilog -3456 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3457 5d/pop-to-EBP -3458 c3/return -3459 -3460 skip-until-close-paren-in-slice: # curr : (address byte), end : (address byte) -> new_curr/EAX -3461 # . prolog -3462 55/push-EBP -3463 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3464 # . save registers -3465 51/push-ECX -3466 52/push-EDX -3467 # ECX = curr -3468 8b/copy 1/mod/*+disp8 5/rm32/EBP . . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX -3469 # EDX = end -3470 8b/copy 1/mod/*+disp8 5/rm32/EBP . . 2/r32/EDX 0xc/disp8 . # copy *(EBP+12) to EDX -3471 # EAX = 0 -3472 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -3473 # skip initial dquote -3474 41/increment-ECX -3475 $skip-until-close-paren-in-slice:loop: -3476 # if (curr >= end) break -3477 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX -3478 73/jump-if-greater-unsigned-or-equal $skip-until-close-paren-in-slice:break/disp8 -3479 # AL = *curr -3480 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL -3481 $skip-until-close-paren-in-slice:check-close: -3482 # if (EAX == ')') break -3483 3d/compare-EAX-and 0x29/imm32/close-paren -3484 74/jump-if-equal $skip-until-close-paren-in-slice:break/disp8 -3485 # ++curr -3486 41/increment-ECX -3487 eb/jump $skip-until-close-paren-in-slice:loop/disp8 -3488 $skip-until-close-paren-in-slice:break: -3489 # return curr -3490 89/copy 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # copy ECX to EAX -3491 $skip-until-close-paren-in-slice:end: -3492 # . restore registers -3493 5a/pop-to-EDX -3494 59/pop-to-ECX -3495 # . epilog -3496 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3497 5d/pop-to-EBP -3498 c3/return -3499 -3500 test-skip-until-close-paren-in-slice: -3501 # . prolog -3502 55/push-EBP -3503 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3504 # setup: (EAX..ECX) = "*(abc) def" -3505 b8/copy-to-EAX "*(abc) def"/imm32 -3506 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -3507 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 -3508 05/add-to-EAX 4/imm32 -3509 # EAX = skip-until-close-paren-in-slice(EAX, ECX) -3510 # . . push args -3511 51/push-ECX -3512 50/push-EAX -3513 # . . call -3514 e8/call skip-until-close-paren-in-slice/disp32 -3515 # . . discard args -3516 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3517 # check-ints-equal(ECX-EAX, 5, msg) # EAX is at the ')' -3518 # . . push args -3519 68/push "F - test-skip-until-close-paren-in-slice"/imm32 -3520 68/push 5/imm32 -3521 # . . push ECX-EAX -3522 29/subtract 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # subtract EAX from ECX -3523 51/push-ECX -3524 # . . call -3525 e8/call check-ints-equal/disp32 -3526 # . . discard args -3527 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3528 # . epilog -3529 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3530 5d/pop-to-EBP -3531 c3/return -3532 -3533 test-skip-until-close-paren-in-slice-ignores-spaces: -3534 # . prolog -3535 55/push-EBP -3536 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3537 # setup: (EAX..ECX) = "*(a b)/yz" -3538 b8/copy-to-EAX "*(a b)/yz"/imm32 -3539 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -3540 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 -3541 05/add-to-EAX 4/imm32 -3542 # EAX = skip-until-close-paren-in-slice(EAX, ECX) -3543 # . . push args -3544 51/push-ECX -3545 50/push-EAX -3546 # . . call -3547 e8/call skip-until-close-paren-in-slice/disp32 -3548 # . . discard args -3549 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3550 # check-ints-equal(ECX-EAX, 4, msg) # EAX is at the ')' -3551 # . . push args -3552 68/push "F - test-skip-until-close-paren-in-slice-ignores-spaces"/imm32 -3553 68/push 4/imm32 -3554 # . . push ECX-EAX -3555 29/subtract 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # subtract EAX from ECX -3556 51/push-ECX -3557 # . . call -3558 e8/call check-ints-equal/disp32 -3559 # . . discard args -3560 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3561 # . epilog -3562 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3563 5d/pop-to-EBP -3564 c3/return -3565 -3566 test-skip-until-close-paren-in-slice-stops-at-end: -3567 # . prolog -3568 55/push-EBP -3569 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3570 # setup: (EAX..ECX) = "*(abc" # unbalanced dquote -3571 b8/copy-to-EAX "*(abc"/imm32 -3572 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -3573 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 -3574 05/add-to-EAX 4/imm32 -3575 # EAX = skip-until-close-paren-in-slice(EAX, ECX) +3213 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP +3214 # . flush(_test-output-buffered-file) +3215 # . . push args +3216 68/push _test-output-buffered-file/imm32 +3217 # . . call +3218 e8/call flush/disp32 +3219 # . . discard args +3220 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3221 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +3247 # check-stream-equal(_test-output-stream, "2/mod/*+disp32 6/rm32 4/disp32", msg) +3248 # . . push args +3249 68/push "F - test-emit-indirect-mode-with-disp"/imm32 +3250 68/push "2/mod/*+disp32 0x00000006/rm32 0x00000004/disp32"/imm32 +3251 68/push _test-output-stream/imm32 +3252 # . . call +3253 e8/call check-stream-equal/disp32 +3254 # . . discard args +3255 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3256 # . epilog +3257 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3258 5d/pop-to-EBP +3259 c3/return +3260 +3261 test-emit-indirect-mode-with-disp-negative: +3262 # . prolog +3263 55/push-EBP +3264 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3265 # setup +3266 # . clear-stream(_test-output-stream) +3267 # . . push args +3268 68/push _test-output-stream/imm32 +3269 # . . call +3270 e8/call clear-stream/disp32 +3271 # . . discard args +3272 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3273 # . clear-stream(_test-output-buffered-file+4) +3274 # . . push args +3275 b8/copy-to-EAX _test-output-buffered-file/imm32 +3276 05/add-to-EAX 4/imm32 +3277 50/push-EAX +3278 # . . call +3279 e8/call clear-stream/disp32 +3280 # . . discard args +3281 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3282 # emit-indirect-mode(_test-output-buffered-file, 6, 4/none, 0, -4) +3283 # . . write args +3284 68/push -4/imm32/.disp +3285 68/push 0/imm32/.scale +3286 68/push 4/imm32/.index/none +3287 68/push 6/imm32/.base +3288 68/push _test-output-buffered-file/imm32 +3289 # . . call +3290 e8/call emit-indirect-mode/disp32 +3291 # . . discard args +3292 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP +3293 # . flush(_test-output-buffered-file) +3294 # . . push args +3295 68/push _test-output-buffered-file/imm32 +3296 # . . call +3297 e8/call flush/disp32 +3298 # . . discard args +3299 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3300 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +3326 # check-stream-equal(_test-output-stream, "2/mod/*+disp32 6/rm32 -4/disp32", msg) +3327 # . . push args +3328 68/push "F - test-emit-indirect-mode-with-disp"/imm32 +3329 68/push "2/mod/*+disp32 0x00000006/rm32 0xfffffffc/disp32"/imm32 +3330 68/push _test-output-stream/imm32 +3331 # . . call +3332 e8/call check-stream-equal/disp32 +3333 # . . discard args +3334 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3335 # . epilog +3336 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3337 5d/pop-to-EBP +3338 c3/return +3339 +3340 test-emit-indirect-mode-with-sib: +3341 # . prolog +3342 55/push-EBP +3343 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3344 # setup +3345 # . clear-stream(_test-output-stream) +3346 # . . push args +3347 68/push _test-output-stream/imm32 +3348 # . . call +3349 e8/call clear-stream/disp32 +3350 # . . discard args +3351 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3352 # . clear-stream(_test-output-buffered-file+4) +3353 # . . push args +3354 b8/copy-to-EAX _test-output-buffered-file/imm32 +3355 05/add-to-EAX 4/imm32 +3356 50/push-EAX +3357 # . . call +3358 e8/call clear-stream/disp32 +3359 # . . discard args +3360 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3361 # emit-indirect-mode(_test-output-buffered-file, 6/base, 1/index, 2/scale, 4/disp) +3362 # . . write args +3363 68/push 4/imm32/.disp +3364 68/push 2/imm32/.scale +3365 68/push 1/imm32/.index +3366 68/push 6/imm32/.base +3367 68/push _test-output-buffered-file/imm32 +3368 # . . call +3369 e8/call emit-indirect-mode/disp32 +3370 # . . discard args +3371 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x14/imm32 # add to ESP +3372 # . flush(_test-output-buffered-file) +3373 # . . push args +3374 68/push _test-output-buffered-file/imm32 +3375 # . . call +3376 e8/call flush/disp32 +3377 # . . discard args +3378 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3379 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +3405 # check-stream-equal(_test-output-stream, "2/mod/indirect 4/rm32/sib 6/base 1/index 2/scale 4/disp", msg) +3406 # . . push args +3407 68/push "F - test-emit-indirect-mode-with-sib"/imm32 +3408 68/push "2/mod/*+disp32 4/rm32/sib 0x00000006/base 0x00000001/index 0x00000002/scale 0x00000004/disp32"/imm32 +3409 68/push _test-output-stream/imm32 +3410 # . . call +3411 e8/call check-stream-equal/disp32 +3412 # . . discard args +3413 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3414 # . epilog +3415 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3416 5d/pop-to-EBP +3417 c3/return +3418 +3419 # update line->read to ')' +3420 # line->read ends at ')' +3421 skip-until-close-paren: # line : (address stream) +3422 # . prolog +3423 55/push-EBP +3424 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3425 # . save registers +3426 50/push-EAX +3427 51/push-ECX +3428 52/push-EDX +3429 # ECX = line +3430 8b/copy 1/mod/*+disp8 5/rm32/EBP . . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX +3431 # EAX = skip-until-close-paren-in-slice(&line->data[line->read], &line->data[line->write]) +3432 # . . push &line->data[line->write] +3433 8b/copy 1/mod/*+disp8 1/rm32/ECX . . 2/r32/EDX 8/disp8 . # copy *(ECX+8) to EDX +3434 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 +3435 52/push-EDX +3436 # . . push &line->data[line->read] +3437 8b/copy 1/mod/*+disp8 1/rm32/ECX . . 2/r32/EDX 4/disp8 . # copy *(ECX+4) to EDX +3438 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 +3439 52/push-EDX +3440 # . . call +3441 e8/call skip-until-close-paren-in-slice/disp32 +3442 # . . discard args +3443 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3444 # line->read = EAX - line->data +3445 29/subtract 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # subtract ECX from EAX +3446 2d/subtract-from-EAX 0xc/imm32 +3447 89/copy 1/mod/*+disp8 1/rm32/ECX . . 0/r32/EAX 4/disp8 . # copy EAX to *(ECX+4) +3448 $skip-until-close-paren:end: +3449 # . restore registers +3450 5a/pop-to-EDX +3451 59/pop-to-ECX +3452 58/pop-to-EAX +3453 # . epilog +3454 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3455 5d/pop-to-EBP +3456 c3/return +3457 +3458 test-skip-until-close-paren: +3459 # . prolog +3460 55/push-EBP +3461 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3462 # setup +3463 # . clear-stream(_test-input-stream) +3464 # . . push args +3465 68/push _test-input-stream/imm32 +3466 # . . call +3467 e8/call clear-stream/disp32 +3468 # . . discard args +3469 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3470 # . write(_test-input-stream, "*(abc) def") +3471 # . indices: 0123 45 +3472 # . . push args +3473 68/push "*(abc) def"/imm32 +3474 68/push _test-input-stream/imm32 +3475 # . . call +3476 e8/call write/disp32 +3477 # . . discard args +3478 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3479 # precondition: line->read == 0 +3480 # . . push args +3481 68/push "F - test-skip-until-close-paren/precondition"/imm32 +3482 68/push 0/imm32 +3483 b8/copy-to-EAX _test-input-stream/imm32 +3484 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +3485 # . . call +3486 e8/call check-ints-equal/disp32 +3487 # . . discard args +3488 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3489 # skip-until-close-paren(_test-input-stream) +3490 # . . push args +3491 68/push _test-input-stream/imm32 +3492 # . . call +3493 e8/call skip-until-close-paren/disp32 +3494 # . . discard args +3495 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3496 # check-ints-equal(line->read, 5, msg) +3497 # . . push args +3498 68/push "F - test-skip-until-close-paren"/imm32 +3499 68/push 5/imm32 +3500 b8/copy-to-EAX _test-input-stream/imm32 +3501 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +3502 # . . call +3503 e8/call check-ints-equal/disp32 +3504 # . . discard args +3505 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3506 # . epilog +3507 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3508 5d/pop-to-EBP +3509 c3/return +3510 +3511 test-skip-until-close-paren-ignores-spaces: +3512 # . prolog +3513 55/push-EBP +3514 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3515 # setup +3516 # . clear-stream(_test-input-stream) +3517 # . . push args +3518 68/push _test-input-stream/imm32 +3519 # . . call +3520 e8/call clear-stream/disp32 +3521 # . . discard args +3522 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3523 # . write(_test-input-stream, "*(a b)/yz") +3524 # . . push args +3525 68/push "*(a b)/yz"/imm32 +3526 68/push _test-input-stream/imm32 +3527 # . . call +3528 e8/call write/disp32 +3529 # . . discard args +3530 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3531 # precondition: line->read == 0 +3532 # . . push args +3533 68/push "F - test-skip-until-close-paren-ignores-spaces/precondition"/imm32 +3534 68/push 0/imm32 +3535 b8/copy-to-EAX _test-input-stream/imm32 +3536 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +3537 # . . call +3538 e8/call check-ints-equal/disp32 +3539 # . . discard args +3540 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3541 # skip-until-close-paren(_test-input-stream) +3542 # . . push args +3543 68/push _test-input-stream/imm32 +3544 # . . call +3545 e8/call skip-until-close-paren/disp32 +3546 # . . discard args +3547 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3548 # check-ints-equal(line->read, 5, msg) +3549 # . . push args +3550 68/push "F - test-skip-until-close-paren-ignores-spaces"/imm32 +3551 68/push 5/imm32 +3552 b8/copy-to-EAX _test-input-stream/imm32 +3553 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +3554 # . . call +3555 e8/call check-ints-equal/disp32 +3556 # . . discard args +3557 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3558 # . epilog +3559 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3560 5d/pop-to-EBP +3561 c3/return +3562 +3563 test-skip-until-close-paren-works-from-mid-stream: +3564 # . prolog +3565 55/push-EBP +3566 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3567 # setup +3568 # . clear-stream(_test-input-stream) +3569 # . . push args +3570 68/push _test-input-stream/imm32 +3571 # . . call +3572 e8/call clear-stream/disp32 +3573 # . . discard args +3574 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3575 # . write(_test-input-stream, "0 *(a b)/yz") 3576 # . . push args -3577 51/push-ECX -3578 50/push-EAX +3577 68/push "0 *(a b)/yz"/imm32 +3578 68/push _test-input-stream/imm32 3579 # . . call -3580 e8/call skip-until-close-paren-in-slice/disp32 +3580 e8/call write/disp32 3581 # . . discard args 3582 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3583 # check-ints-equal(ECX-EAX, 0, msg) # skipped to end of slice -3584 # . . push args -3585 68/push "F - test-skip-until-close-paren-in-slice-stops-at-end"/imm32 -3586 68/push 0/imm32 -3587 # . . push ECX-EAX -3588 29/subtract 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # subtract EAX from ECX -3589 51/push-ECX -3590 # . . call -3591 e8/call check-ints-equal/disp32 -3592 # . . discard args -3593 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3594 # . epilog -3595 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3596 5d/pop-to-EBP -3597 c3/return -3598 -3599 # assumes 'in' starts with optional '+' or '-', optional whitespace, and an unsigned integer -3600 # returns the value of the integer -3601 # side-effect: modifies 'in' to skip past the integer -3602 next-hex-int: # in : (address slice) -> result/EAX -3603 # . prolog -3604 55/push-EBP -3605 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3606 # . save registers -3607 51/push-ECX -3608 52/push-EDX -3609 53/push-EBX -3610 56/push-ESI -3611 57/push-EDI -3612 # result/EDI = 0 -3613 31/xor 3/mod/direct 7/rm32/EDI . . . 7/r32/EDI . . # clear EDI -3614 # ESI = in -3615 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI -3616 # EDX = in->end -3617 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 2/r32/EDX 4/disp8 . # copy *(ESI+4) to EDX -3618 # curr/ECX = in->start -3619 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX -3620 # negate?/EBX = false -3621 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX -3622 # EAX = *curr -3623 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -3624 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL -3625 $next-hex-int:positive: -3626 # if (*curr == '+') ++curr -3627 3d/compare-EAX-and 0x2b/imm32/+ -3628 75/jump-if-not-equal $next-hex-int:negative/disp8 -3629 # . ++curr -3630 41/increment-ECX -3631 eb/jump $next-hex-int:skip-whitespace/disp8 -3632 $next-hex-int:negative: -3633 # else if (*curr == '-') ++curr, negate = true -3634 3d/compare-EAX-and 0x2d/imm32/- -3635 75/jump-if-not-equal $next-hex-int:skip-whitespace/disp8 -3636 $next-hex-int:need-to-negate: -3637 # . ++curr -3638 41/increment-ECX -3639 # . negate = true -3640 bb/copy-to-EBX 1/imm32/true -3641 # fall through -3642 $next-hex-int:skip-whitespace: -3643 # spill EAX -3644 50/push-EAX -3645 # EAX = skip-chars-matching-whitespace-in-slice(word->start, word->end) -3646 # . . push args -3647 52/push-EDX -3648 51/push-ECX -3649 # . . call -3650 e8/call skip-chars-matching-whitespace-in-slice/disp32 -3651 # . . discard args -3652 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3653 # ECX = EAX -3654 89/copy 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # copy EAX to ECX -3655 # restore EAX -3656 58/pop-to-EAX -3657 $next-hex-int:initial-0: -3658 # skip past leading '0x' -3659 # . if (*curr != '0') jump to loop -3660 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL -3661 3d/compare-EAX-and 0x30/imm32/0 -3662 75/jump-if-not-equal $next-hex-int:loop/disp8 -3663 # . ++curr -3664 41/increment-ECX -3665 $next-hex-int:initial-0x: -3666 # . if (curr >= in->end) return result -3667 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX -3668 73/jump-if-greater-or-equal-unsigned $next-hex-int:end/disp8 -3669 # . if (*curr != 'x') jump to loop # the previous '0' is still valid so doesn't need to be checked again -3670 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -3671 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL -3672 3d/compare-EAX-and 0x78/imm32/x -3673 75/jump-if-not-equal $next-hex-int:loop/disp8 -3674 # . ++curr -3675 41/increment-ECX -3676 $next-hex-int:loop: -3677 # if (curr >= in->end) break -3678 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX -3679 73/jump-if-greater-or-equal-unsigned $next-hex-int:break/disp8 -3680 # if (!is-hex-digit?(*curr)) break -3681 # . EAX = *curr -3682 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL -3683 # . EAX = is-hex-digit?(*curr) -3684 # . . push args -3685 50/push-EAX -3686 # . . call -3687 e8/call is-hex-digit?/disp32 -3688 # . . discard args -3689 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3690 # . if (EAX == 0) break -3691 3d/compare-EAX-and 0/imm32 -3692 74/jump-if-equal $next-hex-int:break/disp8 -3693 # EAX = from-hex-char(*curr) -3694 # . . copy arg to EAX -3695 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL -3696 # . . call -3697 e8/call from-hex-char/disp32 -3698 # result = result * 16 + EAX -3699 c1/shift 4/subop/left 3/mod/direct 7/rm32/EDI . . . . . 4/imm8 # shift EDI left by 4 bits -3700 01/add 3/mod/direct 7/rm32/EDI . . . 0/r32/EAX . . # add EAX to EDI -3701 # ++curr -3702 41/increment-ECX -3703 # loop -3704 eb/jump $next-hex-int:loop/disp8 -3705 $next-hex-int:break: -3706 81 7/subop/compare 3/mod/direct 3/rm32/EBX . . . . . 0/imm32 # compare EBX -3707 74/jump-if-equal $next-hex-int:end/disp8 -3708 $next-hex-int:negate: -3709 f7 3/subop/negate 3/mod/direct 7/rm32/EDI . . . . . . # negate EDI -3710 $next-hex-int:end: -3711 # word->start = curr -3712 89/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy ECX to *ESI -3713 # return EDI -3714 89/copy 3/mod/direct 0/rm32/EAX . . . 7/r32/EDI . . # copy EDI to EAX -3715 # . restore registers -3716 5f/pop-to-EDI -3717 5e/pop-to-ESI -3718 5b/pop-to-EBX -3719 5a/pop-to-EDX -3720 59/pop-to-ECX -3721 # . epilog -3722 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3723 5d/pop-to-EBP -3724 c3/return -3725 -3726 $next-hex-int:abort: -3727 # . _write(2/stderr, error) -3728 # . . push args -3729 68/push "next-hex-int: invalid hex char: "/imm32 -3730 68/push 2/imm32/stderr -3731 # . . call -3732 e8/call _write/disp32 -3733 # . . discard args -3734 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3735 # . clear-stream(Stderr+4) -3736 # . . save EAX -3737 50/push-EAX -3738 # . . push args -3739 b8/copy-to-EAX Stderr/imm32 -3740 05/add-to-EAX 4/imm32 -3741 50/push-EAX -3742 # . . call -3743 e8/call clear-stream/disp32 -3744 # . . discard args -3745 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3746 # . . restore EAX -3747 58/pop-to-EAX -3748 # . print-int32-buffered(Stderr, EAX) -3749 # . . push args -3750 50/push-EAX -3751 68/push Stderr/imm32 -3752 # . . call -3753 e8/call print-int32-buffered/disp32 -3754 # . . discard args -3755 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3756 # . flush(Stderr) -3757 # . . push args -3758 68/push Stderr/imm32 -3759 # . . call -3760 e8/call flush/disp32 -3761 # . . discard args -3762 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3763 # . _write(2/stderr, "\n") -3764 # . . push args -3765 68/push "\n"/imm32 -3766 68/push 2/imm32/stderr -3767 # . . call -3768 e8/call _write/disp32 -3769 # . . discard args -3770 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3771 # . syscall(exit, 1) -3772 bb/copy-to-EBX 1/imm32 -3773 b8/copy-to-EAX 1/imm32/exit -3774 cd/syscall 0x80/imm8 -3775 # never gets here -3776 -3777 test-next-hex-int-single-digit: -3778 # . prolog -3779 55/push-EBP -3780 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3781 # (EAX..ECX) = "+a)" -3782 b8/copy-to-EAX "+a)"/imm32 -3783 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -3784 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 -3785 05/add-to-EAX 4/imm32 -3786 # var slice/ECX = {EAX, ECX} -3787 51/push-ECX -3788 50/push-EAX -3789 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -3790 # EAX = next-hex-int(slice) -3791 # . . push args -3792 51/push-ECX -3793 # . . call -3794 e8/call next-hex-int/disp32 -3795 # . . discard args -3796 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3797 # check-ints-equal(EAX, 0xa, msg) -3798 # . . push args -3799 68/push "F - test-next-hex-int-single-digit"/imm32 -3800 68/push 0xa/imm32 -3801 50/push-EAX -3802 # . . call -3803 e8/call check-ints-equal/disp32 -3804 # . . discard args -3805 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3806 # . epilog -3807 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3808 5d/pop-to-EBP -3809 c3/return -3810 -3811 test-next-hex-int-multi-digit: -3812 # . prolog -3813 55/push-EBP -3814 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3815 # (EAX..ECX) = "+ 34a)" -3816 b8/copy-to-EAX "+ 34a)"/imm32 -3817 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -3818 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 -3819 05/add-to-EAX 4/imm32 -3820 # var slice/ECX = {EAX, ECX} -3821 51/push-ECX -3822 50/push-EAX -3823 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -3824 # EAX = next-hex-int(slice) -3825 # . . push args -3826 51/push-ECX -3827 # . . call -3828 e8/call next-hex-int/disp32 -3829 # . . discard args -3830 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3831 # check-ints-equal(EAX, 0x34a, msg) -3832 # . . push args -3833 68/push "F - test-next-hex-int-multi-digit"/imm32 -3834 68/push 0x34a/imm32 -3835 50/push-EAX -3836 # . . call -3837 e8/call check-ints-equal/disp32 -3838 # . . discard args -3839 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3840 # . epilog -3841 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3842 5d/pop-to-EBP -3843 c3/return -3844 -3845 test-next-hex-int-0x-prefix: -3846 # . prolog -3847 55/push-EBP -3848 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3849 # (EAX..ECX) = "+0x34)" -3850 b8/copy-to-EAX "+0x34)"/imm32 -3851 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -3852 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 -3853 05/add-to-EAX 4/imm32 -3854 # var slice/ECX = {EAX, ECX} -3855 51/push-ECX -3856 50/push-EAX -3857 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -3858 # EAX = next-hex-int(slice) -3859 # . . push args -3860 51/push-ECX -3861 # . . call -3862 e8/call next-hex-int/disp32 -3863 # . . discard args -3864 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3865 # check-ints-equal(EAX, 0x34, msg) -3866 # . . push args -3867 68/push "F - test-next-hex-int-0x-prefix"/imm32 -3868 68/push 0x34/imm32 -3869 50/push-EAX -3870 # . . call -3871 e8/call check-ints-equal/disp32 -3872 # . . discard args -3873 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3874 # . epilog -3875 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3876 5d/pop-to-EBP -3877 c3/return -3878 -3879 test-next-hex-int-zero: -3880 # . prolog -3881 55/push-EBP -3882 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3883 # (EAX..ECX) = "+0)" -3884 b8/copy-to-EAX "+0)"/imm32 -3885 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -3886 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 +3583 # precondition: _test-input-stream->read == 2 +3584 c7 0/subop/copy 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 2/imm32 # copy to *(EAX+4) +3585 # skip-until-close-paren(_test-input-stream) +3586 # . . push args +3587 68/push _test-input-stream/imm32 +3588 # . . call +3589 e8/call skip-until-close-paren/disp32 +3590 # . . discard args +3591 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3592 # check-ints-equal(_test-input-stream->read, 7, msg) +3593 # . . push args +3594 68/push "F - test-skip-until-close-paren-works-from-mid-stream"/imm32 +3595 68/push 7/imm32 +3596 b8/copy-to-EAX _test-input-stream/imm32 +3597 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +3598 # . . call +3599 e8/call check-ints-equal/disp32 +3600 # . . discard args +3601 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3602 # . epilog +3603 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3604 5d/pop-to-EBP +3605 c3/return +3606 +3607 skip-until-close-paren-in-slice: # curr : (address byte), end : (address byte) -> new_curr/EAX +3608 # . prolog +3609 55/push-EBP +3610 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3611 # . save registers +3612 51/push-ECX +3613 52/push-EDX +3614 # ECX = curr +3615 8b/copy 1/mod/*+disp8 5/rm32/EBP . . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX +3616 # EDX = end +3617 8b/copy 1/mod/*+disp8 5/rm32/EBP . . 2/r32/EDX 0xc/disp8 . # copy *(EBP+12) to EDX +3618 # EAX = 0 +3619 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +3620 # skip initial dquote +3621 41/increment-ECX +3622 $skip-until-close-paren-in-slice:loop: +3623 # if (curr >= end) break +3624 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX +3625 73/jump-if-greater-unsigned-or-equal $skip-until-close-paren-in-slice:break/disp8 +3626 # AL = *curr +3627 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +3628 $skip-until-close-paren-in-slice:check-close: +3629 # if (EAX == ')') break +3630 3d/compare-EAX-and 0x29/imm32/close-paren +3631 74/jump-if-equal $skip-until-close-paren-in-slice:break/disp8 +3632 # ++curr +3633 41/increment-ECX +3634 eb/jump $skip-until-close-paren-in-slice:loop/disp8 +3635 $skip-until-close-paren-in-slice:break: +3636 # return curr +3637 89/copy 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # copy ECX to EAX +3638 $skip-until-close-paren-in-slice:end: +3639 # . restore registers +3640 5a/pop-to-EDX +3641 59/pop-to-ECX +3642 # . epilog +3643 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3644 5d/pop-to-EBP +3645 c3/return +3646 +3647 test-skip-until-close-paren-in-slice: +3648 # . prolog +3649 55/push-EBP +3650 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3651 # setup: (EAX..ECX) = "*(abc) def" +3652 b8/copy-to-EAX "*(abc) def"/imm32 +3653 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +3654 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 +3655 05/add-to-EAX 4/imm32 +3656 # EAX = skip-until-close-paren-in-slice(EAX, ECX) +3657 # . . push args +3658 51/push-ECX +3659 50/push-EAX +3660 # . . call +3661 e8/call skip-until-close-paren-in-slice/disp32 +3662 # . . discard args +3663 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3664 # check-ints-equal(ECX-EAX, 5, msg) # EAX is at the ')' +3665 # . . push args +3666 68/push "F - test-skip-until-close-paren-in-slice"/imm32 +3667 68/push 5/imm32 +3668 # . . push ECX-EAX +3669 29/subtract 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # subtract EAX from ECX +3670 51/push-ECX +3671 # . . call +3672 e8/call check-ints-equal/disp32 +3673 # . . discard args +3674 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3675 # . epilog +3676 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3677 5d/pop-to-EBP +3678 c3/return +3679 +3680 test-skip-until-close-paren-in-slice-ignores-spaces: +3681 # . prolog +3682 55/push-EBP +3683 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3684 # setup: (EAX..ECX) = "*(a b)/yz" +3685 b8/copy-to-EAX "*(a b)/yz"/imm32 +3686 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +3687 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 +3688 05/add-to-EAX 4/imm32 +3689 # EAX = skip-until-close-paren-in-slice(EAX, ECX) +3690 # . . push args +3691 51/push-ECX +3692 50/push-EAX +3693 # . . call +3694 e8/call skip-until-close-paren-in-slice/disp32 +3695 # . . discard args +3696 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3697 # check-ints-equal(ECX-EAX, 4, msg) # EAX is at the ')' +3698 # . . push args +3699 68/push "F - test-skip-until-close-paren-in-slice-ignores-spaces"/imm32 +3700 68/push 4/imm32 +3701 # . . push ECX-EAX +3702 29/subtract 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # subtract EAX from ECX +3703 51/push-ECX +3704 # . . call +3705 e8/call check-ints-equal/disp32 +3706 # . . discard args +3707 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3708 # . epilog +3709 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3710 5d/pop-to-EBP +3711 c3/return +3712 +3713 test-skip-until-close-paren-in-slice-stops-at-end: +3714 # . prolog +3715 55/push-EBP +3716 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3717 # setup: (EAX..ECX) = "*(abc" # unbalanced dquote +3718 b8/copy-to-EAX "*(abc"/imm32 +3719 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +3720 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 +3721 05/add-to-EAX 4/imm32 +3722 # EAX = skip-until-close-paren-in-slice(EAX, ECX) +3723 # . . push args +3724 51/push-ECX +3725 50/push-EAX +3726 # . . call +3727 e8/call skip-until-close-paren-in-slice/disp32 +3728 # . . discard args +3729 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3730 # check-ints-equal(ECX-EAX, 0, msg) # skipped to end of slice +3731 # . . push args +3732 68/push "F - test-skip-until-close-paren-in-slice-stops-at-end"/imm32 +3733 68/push 0/imm32 +3734 # . . push ECX-EAX +3735 29/subtract 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # subtract EAX from ECX +3736 51/push-ECX +3737 # . . call +3738 e8/call check-ints-equal/disp32 +3739 # . . discard args +3740 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3741 # . epilog +3742 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3743 5d/pop-to-EBP +3744 c3/return +3745 +3746 # assumes 'in' starts with optional '+' or '-', optional whitespace, and an unsigned integer +3747 # returns the value of the integer +3748 # side-effect: modifies 'in' to skip past the integer +3749 next-hex-int: # in : (address slice) -> result/EAX +3750 # . prolog +3751 55/push-EBP +3752 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3753 # . save registers +3754 51/push-ECX +3755 52/push-EDX +3756 53/push-EBX +3757 56/push-ESI +3758 57/push-EDI +3759 # result/EDI = 0 +3760 31/xor 3/mod/direct 7/rm32/EDI . . . 7/r32/EDI . . # clear EDI +3761 # ESI = in +3762 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +3763 # EDX = in->end +3764 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 2/r32/EDX 4/disp8 . # copy *(ESI+4) to EDX +3765 # curr/ECX = in->start +3766 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX +3767 # negate?/EBX = false +3768 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX +3769 # EAX = *curr +3770 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +3771 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +3772 $next-hex-int:positive: +3773 # if (*curr == '+') ++curr +3774 3d/compare-EAX-and 0x2b/imm32/+ +3775 75/jump-if-not-equal $next-hex-int:negative/disp8 +3776 # . ++curr +3777 41/increment-ECX +3778 eb/jump $next-hex-int:skip-whitespace/disp8 +3779 $next-hex-int:negative: +3780 # else if (*curr == '-') ++curr, negate = true +3781 3d/compare-EAX-and 0x2d/imm32/- +3782 75/jump-if-not-equal $next-hex-int:skip-whitespace/disp8 +3783 $next-hex-int:need-to-negate: +3784 # . ++curr +3785 41/increment-ECX +3786 # . negate = true +3787 bb/copy-to-EBX 1/imm32/true +3788 # fall through +3789 $next-hex-int:skip-whitespace: +3790 # spill EAX +3791 50/push-EAX +3792 # EAX = skip-chars-matching-whitespace-in-slice(word->start, word->end) +3793 # . . push args +3794 52/push-EDX +3795 51/push-ECX +3796 # . . call +3797 e8/call skip-chars-matching-whitespace-in-slice/disp32 +3798 # . . discard args +3799 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3800 # ECX = EAX +3801 89/copy 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # copy EAX to ECX +3802 # restore EAX +3803 58/pop-to-EAX +3804 $next-hex-int:initial-0: +3805 # skip past leading '0x' +3806 # . if (*curr != '0') jump to loop +3807 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +3808 3d/compare-EAX-and 0x30/imm32/0 +3809 75/jump-if-not-equal $next-hex-int:loop/disp8 +3810 # . ++curr +3811 41/increment-ECX +3812 $next-hex-int:initial-0x: +3813 # . if (curr >= in->end) return result +3814 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX +3815 73/jump-if-greater-or-equal-unsigned $next-hex-int:end/disp8 +3816 # . if (*curr != 'x') jump to loop # the previous '0' is still valid so doesn't need to be checked again +3817 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +3818 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +3819 3d/compare-EAX-and 0x78/imm32/x +3820 75/jump-if-not-equal $next-hex-int:loop/disp8 +3821 # . ++curr +3822 41/increment-ECX +3823 $next-hex-int:loop: +3824 # if (curr >= in->end) break +3825 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX +3826 73/jump-if-greater-or-equal-unsigned $next-hex-int:break/disp8 +3827 # if (!is-hex-digit?(*curr)) break +3828 # . EAX = *curr +3829 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +3830 # . EAX = is-hex-digit?(*curr) +3831 # . . push args +3832 50/push-EAX +3833 # . . call +3834 e8/call is-hex-digit?/disp32 +3835 # . . discard args +3836 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3837 # . if (EAX == 0) break +3838 3d/compare-EAX-and 0/imm32 +3839 74/jump-if-equal $next-hex-int:break/disp8 +3840 # EAX = from-hex-char(*curr) +3841 # . . copy arg to EAX +3842 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +3843 # . . call +3844 e8/call from-hex-char/disp32 +3845 # result = result * 16 + EAX +3846 c1/shift 4/subop/left 3/mod/direct 7/rm32/EDI . . . . . 4/imm8 # shift EDI left by 4 bits +3847 01/add 3/mod/direct 7/rm32/EDI . . . 0/r32/EAX . . # add EAX to EDI +3848 # ++curr +3849 41/increment-ECX +3850 # loop +3851 eb/jump $next-hex-int:loop/disp8 +3852 $next-hex-int:break: +3853 81 7/subop/compare 3/mod/direct 3/rm32/EBX . . . . . 0/imm32 # compare EBX +3854 74/jump-if-equal $next-hex-int:end/disp8 +3855 $next-hex-int:negate: +3856 f7 3/subop/negate 3/mod/direct 7/rm32/EDI . . . . . . # negate EDI +3857 $next-hex-int:end: +3858 # word->start = curr +3859 89/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy ECX to *ESI +3860 # return EDI +3861 89/copy 3/mod/direct 0/rm32/EAX . . . 7/r32/EDI . . # copy EDI to EAX +3862 # . restore registers +3863 5f/pop-to-EDI +3864 5e/pop-to-ESI +3865 5b/pop-to-EBX +3866 5a/pop-to-EDX +3867 59/pop-to-ECX +3868 # . epilog +3869 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3870 5d/pop-to-EBP +3871 c3/return +3872 +3873 $next-hex-int:abort: +3874 # . _write(2/stderr, error) +3875 # . . push args +3876 68/push "next-hex-int: invalid hex char: "/imm32 +3877 68/push 2/imm32/stderr +3878 # . . call +3879 e8/call _write/disp32 +3880 # . . discard args +3881 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3882 # . clear-stream(Stderr+4) +3883 # . . save EAX +3884 50/push-EAX +3885 # . . push args +3886 b8/copy-to-EAX Stderr/imm32 3887 05/add-to-EAX 4/imm32 -3888 # var slice/ECX = {EAX, ECX} -3889 51/push-ECX -3890 50/push-EAX -3891 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -3892 # EAX = next-hex-int(slice) -3893 # . . push args -3894 51/push-ECX -3895 # . . call -3896 e8/call next-hex-int/disp32 -3897 # . . discard args -3898 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3899 # check-ints-equal(EAX, 0, msg) -3900 # . . push args -3901 68/push "F - test-next-hex-int-zero"/imm32 -3902 68/push 0/imm32 -3903 50/push-EAX -3904 # . . call -3905 e8/call check-ints-equal/disp32 -3906 # . . discard args -3907 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3908 # . epilog -3909 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3910 5d/pop-to-EBP -3911 c3/return -3912 -3913 test-next-hex-int-0-prefix: -3914 # . prolog -3915 55/push-EBP -3916 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3917 # (EAX..ECX) = "+ 03)" -3918 b8/copy-to-EAX "+ 03)"/imm32 -3919 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -3920 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 -3921 05/add-to-EAX 4/imm32 -3922 # var slice/ECX = {EAX, ECX} -3923 51/push-ECX -3924 50/push-EAX -3925 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -3926 # EAX = next-hex-int(slice) -3927 # . . push args -3928 51/push-ECX -3929 # . . call -3930 e8/call next-hex-int/disp32 -3931 # . . discard args -3932 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3933 # check-ints-equal(EAX, 3, msg) -3934 # . . push args -3935 68/push "F - test-next-hex-int-0-prefix"/imm32 -3936 68/push 3/imm32 -3937 50/push-EAX -3938 # . . call -3939 e8/call check-ints-equal/disp32 -3940 # . . discard args -3941 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3942 # . epilog -3943 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3944 5d/pop-to-EBP -3945 c3/return -3946 -3947 test-next-hex-int-negative: -3948 # . prolog -3949 55/push-EBP -3950 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3951 # (EAX..ECX) = "-03)" -3952 b8/copy-to-EAX "-03)"/imm32 -3953 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -3954 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 -3955 05/add-to-EAX 4/imm32 -3956 # var slice/ECX = {EAX, ECX} -3957 51/push-ECX -3958 50/push-EAX -3959 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -3960 # EAX = next-hex-int(slice) -3961 # . . push args -3962 51/push-ECX -3963 # . . call -3964 e8/call next-hex-int/disp32 -3965 # . . discard args -3966 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3967 # check-ints-equal(EAX, -3, msg) -3968 # . . push args -3969 68/push "F - test-next-hex-int-negative"/imm32 -3970 68/push -3/imm32 -3971 50/push-EAX -3972 # . . call -3973 e8/call check-ints-equal/disp32 -3974 # . . discard args -3975 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3976 # . epilog -3977 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3978 5d/pop-to-EBP -3979 c3/return -3980 -3981 test-next-hex-int-negative-with-space: -3982 # . prolog -3983 55/push-EBP -3984 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3985 # (EAX..ECX) = "- 03)" -3986 b8/copy-to-EAX "- 03)"/imm32 -3987 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -3988 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 -3989 05/add-to-EAX 4/imm32 -3990 # var slice/ECX = {EAX, ECX} -3991 51/push-ECX -3992 50/push-EAX -3993 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -3994 # EAX = next-hex-int(slice) -3995 # . . push args -3996 51/push-ECX -3997 # . . call -3998 e8/call next-hex-int/disp32 -3999 # . . discard args -4000 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4001 # check-ints-equal(EAX, -3, msg) -4002 # . . push args -4003 68/push "F - test-next-hex-int-negative-with-space"/imm32 -4004 68/push -3/imm32 -4005 50/push-EAX -4006 # . . call -4007 e8/call check-ints-equal/disp32 -4008 # . . discard args -4009 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -4010 # . epilog -4011 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -4012 5d/pop-to-EBP -4013 c3/return -4014 -4015 # assumes 'in' starts a positive unsigned integer -4016 # returns the value of the integer -4017 # side-effect: modifies 'in' to skip past the integer -4018 next-positive-hex-int: # in : (address slice) -> result/EAX -4019 # . prolog -4020 55/push-EBP -4021 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -4022 # . save registers -4023 51/push-ECX -4024 52/push-EDX -4025 53/push-EBX -4026 56/push-ESI -4027 57/push-EDI -4028 # result/EDI = 0 -4029 31/xor 3/mod/direct 7/rm32/EDI . . . 7/r32/EDI . . # clear EDI -4030 # ESI = in -4031 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI -4032 # EDX = in->end -4033 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 2/r32/EDX 4/disp8 . # copy *(ESI+4) to EDX -4034 # curr/ECX = in->start -4035 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX -4036 # negate?/EBX = false -4037 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX -4038 # EAX = *curr -4039 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -4040 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL -4041 $next-positive-hex-int:initial-0: -4042 # skip past leading '0x' -4043 # . if (*curr != '0') jump to loop -4044 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL -4045 3d/compare-EAX-and 0x30/imm32/0 -4046 75/jump-if-not-equal $next-positive-hex-int:loop/disp8 -4047 # . ++curr -4048 41/increment-ECX -4049 $next-positive-hex-int:initial-0x: -4050 # . if (curr >= in->end) return result -4051 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX -4052 73/jump-if-greater-or-equal-unsigned $next-positive-hex-int:end/disp8 -4053 # . if (*curr != 'x') jump to loop # the previous '0' is still valid so doesn't need to be checked again -4054 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -4055 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL -4056 3d/compare-EAX-and 0x78/imm32/x -4057 75/jump-if-not-equal $next-positive-hex-int:loop/disp8 -4058 # . ++curr -4059 41/increment-ECX -4060 $next-positive-hex-int:loop: -4061 # if (curr >= in->end) break -4062 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX -4063 73/jump-if-greater-or-equal-unsigned $next-positive-hex-int:end/disp8 -4064 # if (!is-hex-digit?(*curr)) break -4065 # . EAX = *curr -4066 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL -4067 # . EAX = is-hex-digit?(*curr) -4068 # . . push args -4069 50/push-EAX -4070 # . . call -4071 e8/call is-hex-digit?/disp32 -4072 # . . discard args -4073 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4074 # . if (EAX == 0) break -4075 3d/compare-EAX-and 0/imm32 -4076 74/jump-if-equal $next-positive-hex-int:end/disp8 -4077 # EAX = from-hex-char(*curr) -4078 # . . copy arg to EAX -4079 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL -4080 # . . call -4081 e8/call from-hex-char/disp32 -4082 # result = result * 16 + EAX -4083 c1/shift 4/subop/left 3/mod/direct 7/rm32/EDI . . . . . 4/imm8 # shift EDI left by 4 bits -4084 01/add 3/mod/direct 7/rm32/EDI . . . 0/r32/EAX . . # add EAX to EDI -4085 # ++curr -4086 41/increment-ECX -4087 # loop -4088 eb/jump $next-positive-hex-int:loop/disp8 -4089 $next-positive-hex-int:end: -4090 # word->start = curr -4091 89/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy ECX to *ESI -4092 # return EDI -4093 89/copy 3/mod/direct 0/rm32/EAX . . . 7/r32/EDI . . # copy EDI to EAX -4094 # . restore registers -4095 5f/pop-to-EDI -4096 5e/pop-to-ESI -4097 5b/pop-to-EBX -4098 5a/pop-to-EDX -4099 59/pop-to-ECX -4100 # . epilog -4101 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -4102 5d/pop-to-EBP -4103 c3/return -4104 -4105 test-next-positive-hex-int-single-digit: -4106 # . prolog -4107 55/push-EBP -4108 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -4109 # (EAX..ECX) = "a)" -4110 b8/copy-to-EAX "a)"/imm32 -4111 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -4112 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 -4113 05/add-to-EAX 4/imm32 -4114 # var slice/ECX = {EAX, ECX} -4115 51/push-ECX -4116 50/push-EAX -4117 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -4118 # EAX = next-positive-hex-int(slice) -4119 # . . push args -4120 51/push-ECX -4121 # . . call -4122 e8/call next-positive-hex-int/disp32 -4123 # . . discard args -4124 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4125 # check-ints-equal(EAX, 0xa, msg) -4126 # . . push args -4127 68/push "F - test-next-positive-hex-int-single-digit"/imm32 -4128 68/push 0xa/imm32 -4129 50/push-EAX -4130 # . . call -4131 e8/call check-ints-equal/disp32 -4132 # . . discard args -4133 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -4134 # . epilog -4135 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -4136 5d/pop-to-EBP -4137 c3/return -4138 -4139 test-next-positive-hex-int-multi-digit: -4140 # . prolog -4141 55/push-EBP -4142 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -4143 # (EAX..ECX) = "34a)" -4144 b8/copy-to-EAX "34a)"/imm32 -4145 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -4146 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 -4147 05/add-to-EAX 4/imm32 -4148 # var slice/ECX = {EAX, ECX} -4149 51/push-ECX -4150 50/push-EAX -4151 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -4152 # EAX = next-positive-hex-int(slice) -4153 # . . push args -4154 51/push-ECX -4155 # . . call -4156 e8/call next-positive-hex-int/disp32 -4157 # . . discard args -4158 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4159 # check-ints-equal(EAX, 0x34a, msg) -4160 # . . push args -4161 68/push "F - test-next-positive-hex-int-multi-digit"/imm32 -4162 68/push 0x34a/imm32 -4163 50/push-EAX -4164 # . . call -4165 e8/call check-ints-equal/disp32 -4166 # . . discard args -4167 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -4168 # . epilog -4169 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -4170 5d/pop-to-EBP -4171 c3/return -4172 -4173 test-next-positive-hex-int-0x-prefix: -4174 # . prolog -4175 55/push-EBP -4176 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -4177 # (EAX..ECX) = "0x34)" -4178 b8/copy-to-EAX "0x34)"/imm32 -4179 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -4180 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 -4181 05/add-to-EAX 4/imm32 -4182 # var slice/ECX = {EAX, ECX} -4183 51/push-ECX -4184 50/push-EAX -4185 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -4186 # EAX = next-positive-hex-int(slice) -4187 # . . push args -4188 51/push-ECX -4189 # . . call -4190 e8/call next-positive-hex-int/disp32 -4191 # . . discard args -4192 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4193 # check-ints-equal(EAX, 0x34, msg) -4194 # . . push args -4195 68/push "F - test-next-positive-hex-int-0x-prefix"/imm32 -4196 68/push 0x34/imm32 -4197 50/push-EAX -4198 # . . call -4199 e8/call check-ints-equal/disp32 -4200 # . . discard args -4201 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -4202 # . epilog -4203 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -4204 5d/pop-to-EBP -4205 c3/return -4206 -4207 test-next-positive-hex-int-zero: -4208 # . prolog -4209 55/push-EBP -4210 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -4211 # (EAX..ECX) = "0" -4212 b8/copy-to-EAX "0"/imm32 -4213 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -4214 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 -4215 05/add-to-EAX 4/imm32 -4216 # var slice/ECX = {EAX, ECX} -4217 51/push-ECX -4218 50/push-EAX -4219 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -4220 # EAX = next-positive-hex-int(slice) -4221 # . . push args -4222 51/push-ECX -4223 # . . call -4224 e8/call next-positive-hex-int/disp32 -4225 # . . discard args -4226 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4227 # check-ints-equal(EAX, 0, msg) -4228 # . . push args -4229 68/push "F - test-next-positive-hex-int-zero"/imm32 -4230 68/push 0/imm32 -4231 50/push-EAX -4232 # . . call -4233 e8/call check-ints-equal/disp32 -4234 # . . discard args -4235 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -4236 # . epilog -4237 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -4238 5d/pop-to-EBP -4239 c3/return -4240 -4241 test-next-positive-hex-int-0-prefix: -4242 # . prolog -4243 55/push-EBP -4244 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -4245 # (EAX..ECX) = "03)" -4246 b8/copy-to-EAX "03)"/imm32 -4247 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -4248 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 -4249 05/add-to-EAX 4/imm32 -4250 # var slice/ECX = {EAX, ECX} -4251 51/push-ECX -4252 50/push-EAX -4253 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -4254 # EAX = next-positive-hex-int(slice) -4255 # . . push args -4256 51/push-ECX -4257 # . . call -4258 e8/call next-positive-hex-int/disp32 -4259 # . . discard args -4260 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4261 # check-ints-equal(EAX, 3, msg) -4262 # . . push args -4263 68/push "F - test-next-positive-hex-int-0-prefix"/imm32 -4264 68/push 3/imm32 -4265 50/push-EAX -4266 # . . call -4267 e8/call check-ints-equal/disp32 -4268 # . . discard args -4269 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -4270 # . epilog -4271 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -4272 5d/pop-to-EBP -4273 c3/return -4274 -4275 == data -4276 Registers: # (table string int) -4277 # a table is a stream -4278 0x40/imm32/write -4279 0/imm32/read -4280 0x40/imm32/length -4281 # data -4282 "eax"/imm32 0/imm32 -4283 "ecx"/imm32 1/imm32 -4284 "edx"/imm32 2/imm32 -4285 "ebx"/imm32 3/imm32 -4286 "esp"/imm32 4/imm32 -4287 "ebp"/imm32 5/imm32 -4288 "esi"/imm32 6/imm32 -4289 "edi"/imm32 7/imm32 -4290 -4291 # . . vim:nowrap:textwidth=0 +3888 50/push-EAX +3889 # . . call +3890 e8/call clear-stream/disp32 +3891 # . . discard args +3892 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3893 # . . restore EAX +3894 58/pop-to-EAX +3895 # . print-int32-buffered(Stderr, EAX) +3896 # . . push args +3897 50/push-EAX +3898 68/push Stderr/imm32 +3899 # . . call +3900 e8/call print-int32-buffered/disp32 +3901 # . . discard args +3902 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3903 # . flush(Stderr) +3904 # . . push args +3905 68/push Stderr/imm32 +3906 # . . call +3907 e8/call flush/disp32 +3908 # . . discard args +3909 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3910 # . _write(2/stderr, "\n") +3911 # . . push args +3912 68/push "\n"/imm32 +3913 68/push 2/imm32/stderr +3914 # . . call +3915 e8/call _write/disp32 +3916 # . . discard args +3917 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3918 # . syscall(exit, 1) +3919 bb/copy-to-EBX 1/imm32 +3920 b8/copy-to-EAX 1/imm32/exit +3921 cd/syscall 0x80/imm8 +3922 # never gets here +3923 +3924 test-next-hex-int-single-digit: +3925 # . prolog +3926 55/push-EBP +3927 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3928 # (EAX..ECX) = "+a)" +3929 b8/copy-to-EAX "+a)"/imm32 +3930 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +3931 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 +3932 05/add-to-EAX 4/imm32 +3933 # var slice/ECX = {EAX, ECX} +3934 51/push-ECX +3935 50/push-EAX +3936 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +3937 # EAX = next-hex-int(slice) +3938 # . . push args +3939 51/push-ECX +3940 # . . call +3941 e8/call next-hex-int/disp32 +3942 # . . discard args +3943 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3944 # check-ints-equal(EAX, 0xa, msg) +3945 # . . push args +3946 68/push "F - test-next-hex-int-single-digit"/imm32 +3947 68/push 0xa/imm32 +3948 50/push-EAX +3949 # . . call +3950 e8/call check-ints-equal/disp32 +3951 # . . discard args +3952 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3953 # . epilog +3954 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3955 5d/pop-to-EBP +3956 c3/return +3957 +3958 test-next-hex-int-multi-digit: +3959 # . prolog +3960 55/push-EBP +3961 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3962 # (EAX..ECX) = "+ 34a)" +3963 b8/copy-to-EAX "+ 34a)"/imm32 +3964 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +3965 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 +3966 05/add-to-EAX 4/imm32 +3967 # var slice/ECX = {EAX, ECX} +3968 51/push-ECX +3969 50/push-EAX +3970 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +3971 # EAX = next-hex-int(slice) +3972 # . . push args +3973 51/push-ECX +3974 # . . call +3975 e8/call next-hex-int/disp32 +3976 # . . discard args +3977 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3978 # check-ints-equal(EAX, 0x34a, msg) +3979 # . . push args +3980 68/push "F - test-next-hex-int-multi-digit"/imm32 +3981 68/push 0x34a/imm32 +3982 50/push-EAX +3983 # . . call +3984 e8/call check-ints-equal/disp32 +3985 # . . discard args +3986 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3987 # . epilog +3988 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3989 5d/pop-to-EBP +3990 c3/return +3991 +3992 test-next-hex-int-0x-prefix: +3993 # . prolog +3994 55/push-EBP +3995 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3996 # (EAX..ECX) = "+0x34)" +3997 b8/copy-to-EAX "+0x34)"/imm32 +3998 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +3999 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 +4000 05/add-to-EAX 4/imm32 +4001 # var slice/ECX = {EAX, ECX} +4002 51/push-ECX +4003 50/push-EAX +4004 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +4005 # EAX = next-hex-int(slice) +4006 # . . push args +4007 51/push-ECX +4008 # . . call +4009 e8/call next-hex-int/disp32 +4010 # . . discard args +4011 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4012 # check-ints-equal(EAX, 0x34, msg) +4013 # . . push args +4014 68/push "F - test-next-hex-int-0x-prefix"/imm32 +4015 68/push 0x34/imm32 +4016 50/push-EAX +4017 # . . call +4018 e8/call check-ints-equal/disp32 +4019 # . . discard args +4020 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4021 # . epilog +4022 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4023 5d/pop-to-EBP +4024 c3/return +4025 +4026 test-next-hex-int-zero: +4027 # . prolog +4028 55/push-EBP +4029 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4030 # (EAX..ECX) = "+0)" +4031 b8/copy-to-EAX "+0)"/imm32 +4032 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +4033 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 +4034 05/add-to-EAX 4/imm32 +4035 # var slice/ECX = {EAX, ECX} +4036 51/push-ECX +4037 50/push-EAX +4038 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +4039 # EAX = next-hex-int(slice) +4040 # . . push args +4041 51/push-ECX +4042 # . . call +4043 e8/call next-hex-int/disp32 +4044 # . . discard args +4045 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4046 # check-ints-equal(EAX, 0, msg) +4047 # . . push args +4048 68/push "F - test-next-hex-int-zero"/imm32 +4049 68/push 0/imm32 +4050 50/push-EAX +4051 # . . call +4052 e8/call check-ints-equal/disp32 +4053 # . . discard args +4054 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4055 # . epilog +4056 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4057 5d/pop-to-EBP +4058 c3/return +4059 +4060 test-next-hex-int-0-prefix: +4061 # . prolog +4062 55/push-EBP +4063 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4064 # (EAX..ECX) = "+ 03)" +4065 b8/copy-to-EAX "+ 03)"/imm32 +4066 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +4067 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 +4068 05/add-to-EAX 4/imm32 +4069 # var slice/ECX = {EAX, ECX} +4070 51/push-ECX +4071 50/push-EAX +4072 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +4073 # EAX = next-hex-int(slice) +4074 # . . push args +4075 51/push-ECX +4076 # . . call +4077 e8/call next-hex-int/disp32 +4078 # . . discard args +4079 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4080 # check-ints-equal(EAX, 3, msg) +4081 # . . push args +4082 68/push "F - test-next-hex-int-0-prefix"/imm32 +4083 68/push 3/imm32 +4084 50/push-EAX +4085 # . . call +4086 e8/call check-ints-equal/disp32 +4087 # . . discard args +4088 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4089 # . epilog +4090 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4091 5d/pop-to-EBP +4092 c3/return +4093 +4094 test-next-hex-int-negative: +4095 # . prolog +4096 55/push-EBP +4097 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4098 # (EAX..ECX) = "-03)" +4099 b8/copy-to-EAX "-03)"/imm32 +4100 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +4101 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 +4102 05/add-to-EAX 4/imm32 +4103 # var slice/ECX = {EAX, ECX} +4104 51/push-ECX +4105 50/push-EAX +4106 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +4107 # EAX = next-hex-int(slice) +4108 # . . push args +4109 51/push-ECX +4110 # . . call +4111 e8/call next-hex-int/disp32 +4112 # . . discard args +4113 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4114 # check-ints-equal(EAX, -3, msg) +4115 # . . push args +4116 68/push "F - test-next-hex-int-negative"/imm32 +4117 68/push -3/imm32 +4118 50/push-EAX +4119 # . . call +4120 e8/call check-ints-equal/disp32 +4121 # . . discard args +4122 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4123 # . epilog +4124 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4125 5d/pop-to-EBP +4126 c3/return +4127 +4128 test-next-hex-int-negative-with-space: +4129 # . prolog +4130 55/push-EBP +4131 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4132 # (EAX..ECX) = "- 03)" +4133 b8/copy-to-EAX "- 03)"/imm32 +4134 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +4135 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 +4136 05/add-to-EAX 4/imm32 +4137 # var slice/ECX = {EAX, ECX} +4138 51/push-ECX +4139 50/push-EAX +4140 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +4141 # EAX = next-hex-int(slice) +4142 # . . push args +4143 51/push-ECX +4144 # . . call +4145 e8/call next-hex-int/disp32 +4146 # . . discard args +4147 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4148 # check-ints-equal(EAX, -3, msg) +4149 # . . push args +4150 68/push "F - test-next-hex-int-negative-with-space"/imm32 +4151 68/push -3/imm32 +4152 50/push-EAX +4153 # . . call +4154 e8/call check-ints-equal/disp32 +4155 # . . discard args +4156 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4157 # . epilog +4158 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4159 5d/pop-to-EBP +4160 c3/return +4161 +4162 # assumes 'in' starts a positive unsigned integer +4163 # returns the value of the integer +4164 # side-effect: modifies 'in' to skip past the integer +4165 next-positive-hex-int: # in : (address slice) -> result/EAX +4166 # . prolog +4167 55/push-EBP +4168 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4169 # . save registers +4170 51/push-ECX +4171 52/push-EDX +4172 53/push-EBX +4173 56/push-ESI +4174 57/push-EDI +4175 # result/EDI = 0 +4176 31/xor 3/mod/direct 7/rm32/EDI . . . 7/r32/EDI . . # clear EDI +4177 # ESI = in +4178 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +4179 # EDX = in->end +4180 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 2/r32/EDX 4/disp8 . # copy *(ESI+4) to EDX +4181 # curr/ECX = in->start +4182 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX +4183 # negate?/EBX = false +4184 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX +4185 # EAX = *curr +4186 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +4187 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +4188 $next-positive-hex-int:initial-0: +4189 # skip past leading '0x' +4190 # . if (*curr != '0') jump to loop +4191 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +4192 3d/compare-EAX-and 0x30/imm32/0 +4193 75/jump-if-not-equal $next-positive-hex-int:loop/disp8 +4194 # . ++curr +4195 41/increment-ECX +4196 $next-positive-hex-int:initial-0x: +4197 # . if (curr >= in->end) return result +4198 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX +4199 73/jump-if-greater-or-equal-unsigned $next-positive-hex-int:end/disp8 +4200 # . if (*curr != 'x') jump to loop # the previous '0' is still valid so doesn't need to be checked again +4201 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +4202 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +4203 3d/compare-EAX-and 0x78/imm32/x +4204 75/jump-if-not-equal $next-positive-hex-int:loop/disp8 +4205 # . ++curr +4206 41/increment-ECX +4207 $next-positive-hex-int:loop: +4208 # if (curr >= in->end) break +4209 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX +4210 73/jump-if-greater-or-equal-unsigned $next-positive-hex-int:end/disp8 +4211 # if (!is-hex-digit?(*curr)) break +4212 # . EAX = *curr +4213 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +4214 # . EAX = is-hex-digit?(*curr) +4215 # . . push args +4216 50/push-EAX +4217 # . . call +4218 e8/call is-hex-digit?/disp32 +4219 # . . discard args +4220 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4221 # . if (EAX == 0) break +4222 3d/compare-EAX-and 0/imm32 +4223 74/jump-if-equal $next-positive-hex-int:end/disp8 +4224 # EAX = from-hex-char(*curr) +4225 # . . copy arg to EAX +4226 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +4227 # . . call +4228 e8/call from-hex-char/disp32 +4229 # result = result * 16 + EAX +4230 c1/shift 4/subop/left 3/mod/direct 7/rm32/EDI . . . . . 4/imm8 # shift EDI left by 4 bits +4231 01/add 3/mod/direct 7/rm32/EDI . . . 0/r32/EAX . . # add EAX to EDI +4232 # ++curr +4233 41/increment-ECX +4234 # loop +4235 eb/jump $next-positive-hex-int:loop/disp8 +4236 $next-positive-hex-int:end: +4237 # word->start = curr +4238 89/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy ECX to *ESI +4239 # return EDI +4240 89/copy 3/mod/direct 0/rm32/EAX . . . 7/r32/EDI . . # copy EDI to EAX +4241 # . restore registers +4242 5f/pop-to-EDI +4243 5e/pop-to-ESI +4244 5b/pop-to-EBX +4245 5a/pop-to-EDX +4246 59/pop-to-ECX +4247 # . epilog +4248 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4249 5d/pop-to-EBP +4250 c3/return +4251 +4252 test-next-positive-hex-int-single-digit: +4253 # . prolog +4254 55/push-EBP +4255 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4256 # (EAX..ECX) = "a)" +4257 b8/copy-to-EAX "a)"/imm32 +4258 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +4259 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 +4260 05/add-to-EAX 4/imm32 +4261 # var slice/ECX = {EAX, ECX} +4262 51/push-ECX +4263 50/push-EAX +4264 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +4265 # EAX = next-positive-hex-int(slice) +4266 # . . push args +4267 51/push-ECX +4268 # . . call +4269 e8/call next-positive-hex-int/disp32 +4270 # . . discard args +4271 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4272 # check-ints-equal(EAX, 0xa, msg) +4273 # . . push args +4274 68/push "F - test-next-positive-hex-int-single-digit"/imm32 +4275 68/push 0xa/imm32 +4276 50/push-EAX +4277 # . . call +4278 e8/call check-ints-equal/disp32 +4279 # . . discard args +4280 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4281 # . epilog +4282 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4283 5d/pop-to-EBP +4284 c3/return +4285 +4286 test-next-positive-hex-int-multi-digit: +4287 # . prolog +4288 55/push-EBP +4289 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4290 # (EAX..ECX) = "34a)" +4291 b8/copy-to-EAX "34a)"/imm32 +4292 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +4293 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 +4294 05/add-to-EAX 4/imm32 +4295 # var slice/ECX = {EAX, ECX} +4296 51/push-ECX +4297 50/push-EAX +4298 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +4299 # EAX = next-positive-hex-int(slice) +4300 # . . push args +4301 51/push-ECX +4302 # . . call +4303 e8/call next-positive-hex-int/disp32 +4304 # . . discard args +4305 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4306 # check-ints-equal(EAX, 0x34a, msg) +4307 # . . push args +4308 68/push "F - test-next-positive-hex-int-multi-digit"/imm32 +4309 68/push 0x34a/imm32 +4310 50/push-EAX +4311 # . . call +4312 e8/call check-ints-equal/disp32 +4313 # . . discard args +4314 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4315 # . epilog +4316 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4317 5d/pop-to-EBP +4318 c3/return +4319 +4320 test-next-positive-hex-int-0x-prefix: +4321 # . prolog +4322 55/push-EBP +4323 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4324 # (EAX..ECX) = "0x34)" +4325 b8/copy-to-EAX "0x34)"/imm32 +4326 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +4327 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 +4328 05/add-to-EAX 4/imm32 +4329 # var slice/ECX = {EAX, ECX} +4330 51/push-ECX +4331 50/push-EAX +4332 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +4333 # EAX = next-positive-hex-int(slice) +4334 # . . push args +4335 51/push-ECX +4336 # . . call +4337 e8/call next-positive-hex-int/disp32 +4338 # . . discard args +4339 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4340 # check-ints-equal(EAX, 0x34, msg) +4341 # . . push args +4342 68/push "F - test-next-positive-hex-int-0x-prefix"/imm32 +4343 68/push 0x34/imm32 +4344 50/push-EAX +4345 # . . call +4346 e8/call check-ints-equal/disp32 +4347 # . . discard args +4348 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4349 # . epilog +4350 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4351 5d/pop-to-EBP +4352 c3/return +4353 +4354 test-next-positive-hex-int-zero: +4355 # . prolog +4356 55/push-EBP +4357 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4358 # (EAX..ECX) = "0" +4359 b8/copy-to-EAX "0"/imm32 +4360 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +4361 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 +4362 05/add-to-EAX 4/imm32 +4363 # var slice/ECX = {EAX, ECX} +4364 51/push-ECX +4365 50/push-EAX +4366 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +4367 # EAX = next-positive-hex-int(slice) +4368 # . . push args +4369 51/push-ECX +4370 # . . call +4371 e8/call next-positive-hex-int/disp32 +4372 # . . discard args +4373 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4374 # check-ints-equal(EAX, 0, msg) +4375 # . . push args +4376 68/push "F - test-next-positive-hex-int-zero"/imm32 +4377 68/push 0/imm32 +4378 50/push-EAX +4379 # . . call +4380 e8/call check-ints-equal/disp32 +4381 # . . discard args +4382 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4383 # . epilog +4384 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4385 5d/pop-to-EBP +4386 c3/return +4387 +4388 test-next-positive-hex-int-0-prefix: +4389 # . prolog +4390 55/push-EBP +4391 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4392 # (EAX..ECX) = "03)" +4393 b8/copy-to-EAX "03)"/imm32 +4394 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +4395 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 +4396 05/add-to-EAX 4/imm32 +4397 # var slice/ECX = {EAX, ECX} +4398 51/push-ECX +4399 50/push-EAX +4400 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +4401 # EAX = next-positive-hex-int(slice) +4402 # . . push args +4403 51/push-ECX +4404 # . . call +4405 e8/call next-positive-hex-int/disp32 +4406 # . . discard args +4407 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4408 # check-ints-equal(EAX, 3, msg) +4409 # . . push args +4410 68/push "F - test-next-positive-hex-int-0-prefix"/imm32 +4411 68/push 3/imm32 +4412 50/push-EAX +4413 # . . call +4414 e8/call check-ints-equal/disp32 +4415 # . . discard args +4416 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4417 # . epilog +4418 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4419 5d/pop-to-EBP +4420 c3/return +4421 +4422 == data +4423 Registers: # (table string int) +4424 # a table is a stream +4425 0x40/imm32/write +4426 0/imm32/read +4427 0x40/imm32/length +4428 # data +4429 "eax"/imm32 0/imm32 +4430 "ecx"/imm32 1/imm32 +4431 "edx"/imm32 2/imm32 +4432 "ebx"/imm32 3/imm32 +4433 "esp"/imm32 4/imm32 +4434 "ebp"/imm32 5/imm32 +4435 "esi"/imm32 6/imm32 +4436 "edi"/imm32 7/imm32 +4437 +4438 # . . vim:nowrap:textwidth=0