From 9c1056f531217f3c1c12b3b3a648ca1cffe4beab Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Fri, 29 Mar 2019 00:47:30 -0700 Subject: 5033 --- html/subx/apps/crenshaw2-1.subx.html | 2 +- html/subx/apps/crenshaw2-1b.subx.html | 4 +- html/subx/apps/hex.subx.html | 6 +- html/subx/apps/pack.subx.html | 4630 +++++++++++++++++++++------------ 4 files changed, 3035 insertions(+), 1607 deletions(-) (limited to 'html/subx/apps') diff --git a/html/subx/apps/crenshaw2-1.subx.html b/html/subx/apps/crenshaw2-1.subx.html index 7a957d61..b950dcfb 100644 --- a/html/subx/apps/crenshaw2-1.subx.html +++ b/html/subx/apps/crenshaw2-1.subx.html @@ -264,7 +264,7 @@ if ('onhashchange' in window) { 201 get-num: # in : (address buffered-file), out : (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void> 202 # pseudocode: 203 # if (!is-digit?(Look)) expected(ed, err, "integer") -204 # if (out->write >= out->length) +204 # if out->write >= out->length 205 # write(err, "Error: too many digits in number\n") 206 # stop(ed, 1) 207 # out->data[out->write] = LSB(Look) diff --git a/html/subx/apps/crenshaw2-1b.subx.html b/html/subx/apps/crenshaw2-1b.subx.html index 42cb3fe0..932e7ed5 100644 --- a/html/subx/apps/crenshaw2-1b.subx.html +++ b/html/subx/apps/crenshaw2-1b.subx.html @@ -266,13 +266,13 @@ if ('onhashchange' in window) { 203 # pseudocode: 204 # if (!is-digit?(Look)) expected(ed, err, "integer") 205 # do -206 # if (out->write >= out->length) +206 # if out->write >= out->length 207 # write(err, "Error: too many digits in number\n") 208 # stop(ed, 1) 209 # out->data[out->write] = LSB(Look) 210 # ++out->write 211 # Look = get-char(in) -212 # while (is-digit?(Look)) +212 # while is-digit?(Look) 213 # This is complicated because I don't want to hard-code the error strategy in 214 # a general helper like write-byte. Maybe I should just create a local helper. 215 # diff --git a/html/subx/apps/hex.subx.html b/html/subx/apps/hex.subx.html index 94515434..125478ec 100644 --- a/html/subx/apps/hex.subx.html +++ b/html/subx/apps/hex.subx.html @@ -135,7 +135,7 @@ if ('onhashchange' in window) { 72 # the main entry point 73 convert: # in : (address buffered-file), out : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> <void> 74 # pseudocode: - 75 # repeatedly + 75 # while true 76 # EAX = convert-next-octet(in, err, ed) 77 # if (EAX == Eof) break 78 # write-byte(out, AL) @@ -551,7 +551,7 @@ if ('onhashchange' in window) { 488 # abort on any other byte 489 scan-next-byte: # in : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> byte-or-Eof/EAX 490 # pseudocode: - 491 # repeatedly + 491 # while true 492 # EAX = read-byte(in) 493 # if (EAX == Eof) return EAX 494 # if (is-hex-digit?(EAX)) return EAX @@ -1475,7 +1475,7 @@ if ('onhashchange' in window) { 1412 skip-until-newline: # in : (address buffered-file) -> <void> 1413 # pseudocode: 1414 # push EAX -1415 # repeatedly: +1415 # while true 1416 # EAX = read-byte(in) 1417 # if (EAX == Eof) break 1418 # if (EAX == 0x0a) break diff --git a/html/subx/apps/pack.subx.html b/html/subx/apps/pack.subx.html index 0bd3e063..f712b539 100644 --- a/html/subx/apps/pack.subx.html +++ b/html/subx/apps/pack.subx.html @@ -16,12 +16,13 @@ a { color:inherit; } * { font-size:12pt; font-size: 1em; } .subxComment { color: #005faf; } .subxS2Comment { color: #8a8a8a; } +.subxMinorFunction { color: #875f5f; } .LineNr { } .subxS1Comment { color: #0000af; } .SpecialChar { color: #d70000; } .Constant { color: #008787; } .subxFunction { color: #af5f00; text-decoration: underline; } -.subxMinorFunction { color: #875f5f; } +.Folded { color: #080808; background-color: #949494; } .Normal { color: #000000; background-color: #c6c6c6; padding-bottom: 1px; } .subxTest { color: #5f8700; } .CommentedCode { color: #8a8a8a; } @@ -85,8 +86,8 @@ if ('onhashchange' in window) { 22 23 Entry: # run tests if necessary, convert stdin if not 24 - 25 #? # for debugging: run a single test - 26 #? e8/call test-convert-instruction-passes-labels-through/disp32 + 25 # for debugging: run a single test + 26 #? e8/call test-convert-in-data-segment/disp32 27 #? 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX 28 #? eb/jump $main:end/disp8 29 @@ -126,7 +127,7 @@ if ('onhashchange' in window) { 63 68/push Stdout/imm32 64 68/push Stdin/imm32 65 # . . call - 66 e8/call convert/disp32 + 66 e8/call convert/disp32 67 # . . discard args 68 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 69 # . syscall(exit, 0) @@ -146,1619 +147,3046 @@ if ('onhashchange' in window) { 83 # primary state: line 84 # stream of 512 bytes; abort if it ever overflows 85 - 86 convert: # in : (address buffered-file), out : (address buffered-file) -> <void> - 87 # pseudocode: - 88 # var line = new-stream(512, 1) - 89 # repeatedly - 90 # clear-stream(line) - 91 # EAX = read-line(in, line) - 92 # if (EAX == Eof) break - 93 # word-slice = next-word(line) - 94 # if (slice-empty?(word-slice)) continue # just whitespace - 95 # if (starts-with(word-slice, "#")) continue # ignore comments - 96 # assert(slice-equal?(word-slice, "==")) - 97 # word-slice = next-word(line) - 98 # if (slice-equal?(word-slice, "code")) - 99 # convert-code-segment(in, out) - 100 # else - 101 # convert-data-segment(in, out) - 102 # flush(out) - 103 # - 104 # . prolog - 105 55/push-EBP - 106 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 107 # . save registers - 108 51/push-ECX - 109 # var line/ECX : (address stream byte) = stream(512) - 110 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0x200/imm32 # subtract from ESP - 111 68/push 0x200/imm32/length - 112 68/push 0/imm32/read - 113 68/push 0/imm32/write - 114 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 115 $convert:loop: - 116 # clear-stream(ECX) - 117 # . . push args - 118 51/push-ECX - 119 # . . call - 120 e8/call clear-stream/disp32 - 121 # . . discard args - 122 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 123 # EAX = read-line(in, line) - 124 # . . push args - 125 51/push-ECX - 126 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 127 # . . call - 128 e8/call convert-instruction/disp32 - 129 # . . discard args - 130 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 131 # if (EAX == Eof) break - 132 3d/compare-with-EAX 0xffffffff/imm32/Eof - 133 74/jump-if-equal $convert:break/disp8 - 134 # convert-instruction(line, out) - 135 # . . push args - 136 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 137 51/push-ECX - 138 # . . call - 139 e8/call convert-instruction/disp32 - 140 # . . discard args - 141 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 142 $convert:break: - 143 # flush(out) - 144 # . . push args - 145 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 146 # . . call - 147 e8/call flush/disp32 - 148 # . . discard args - 149 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 150 $convert:end: - 151 # . reclaim locals - 152 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x20c/imm32 # add to ESP - 153 # . restore registers - 154 59/pop-to-ECX - 155 # . epilog - 156 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 157 5d/pop-to-EBP - 158 c3/return - 159 - 160 convert-code-segment: # in : (address buffered-file), out : (address buffered-file) -> <void> - 161 # pseudocode: - 162 # var line = new-stream(512, 1) - 163 # repeatedly - 164 # clear-stream(line) - 165 # EAX = read-line(in, line) - 166 # if (EAX == Eof) break - 167 # word-slice = next-word(line) - 168 # if (slice-equal?(word-slice, "==")) - 169 # return - 170 # convert-instruction(line, out) - 171 - 172 convert-data-segment: # in : (address buffered-file), out : (address buffered-file) -> <void> - 173 # pseudocode: - 174 # var line = new-stream(512, 1) - 175 # repeatedly - 176 # clear-stream(line) - 177 # EAX = read-line(in, line) - 178 # if (EAX == Eof) break - 179 # word-slice = next-word(line) - 180 # if (slice-equal?(word-slice, "==")) - 181 # return - 182 # convert-data-word(line, out) - 183 - 184 # - To pack an instruction, following the C++ version: - 185 # read first word as opcode and write-slice - 186 # if 0f or f2 or f3 read second opcode and write-slice - 187 # if 'f2 0f' or 'f3 0f' read third opcode and write-slice - 188 # while true: - 189 # word-slice = next-word - 190 # if empty(word-slice) break - 191 # if has metadata 'mod', parse into mod - 192 # if has metadata 'rm32', parse into rm32 - 193 # if has metadata 'r32', parse into r32 - 194 # if has metadata 'subop', parse into r32 - 195 # if at least one of the 3 was present, print-byte - 196 # while true: - 197 # word-slice = next-word - 198 # if empty(word-slice) break - 199 # if has metadata 'base', parse into base - 200 # if has metadata 'index', parse into index - 201 # if has metadata 'scale', parse into scale - 202 # if at least one of the 3 was present, print-byte - 203 # parse errors => <abort> - 204 # while true: - 205 # word-slice = next-word - 206 # if empty(word-slice) break - 207 # if has metadata 'disp8', emit as 1 byte - 208 # if has metadata 'disp16', emit as 2 bytes - 209 # if has metadata 'disp32', emit as 4 bytes - 210 # while true: - 211 # word-slice = next-word - 212 # if empty(word-slice) break - 213 # if has metadata 'imm8', emit - 214 # if has metadata 'imm32', emit as 4 bytes - 215 # finally, emit line prefixed with a ' # ' - 216 - 217 # simplifications since we perform zero error handling (continuing to rely on the C++ version for that): - 218 # missing fields are always 0-filled - 219 # bytes never mentioned are silently dropped; if you don't provide /mod, /rm32 or /r32 you don't get a 0 modrm byte. You get *no* modrm byte. - 220 # in case of conflict, last operand with a name is recognized - 221 # silently drop extraneous operands - 222 # unceremoniously abort on non-numeric operands except disp or imm - 223 - 224 # conceptual hierarchy within a line: - 225 # line = words separated by ' ', maybe followed by comment starting with '#' - 226 # word = name until '/', then 0 or more metadata separated by '/' - 227 # - 228 # we won't bother saving the internal structure of lines; reparsing should be cheap using three primitives: - 229 # next-token(stream, delim char) -> slice (start, end pointers) - 230 # next-token(stream, slice, delim char) -> slice' - 231 # slice-equal?(slice, string) - 232 - 233 convert-instruction: # line : (address stream byte), out : (address buffered-file) -> <void> - 234 # pseudocode: - 235 # word-slice = next-word - 236 # if (slice-starts-with?(word-slice, '#')) - 237 # write-stream-buffered(out, line) - 238 # return - 239 # if (slice-starts-with?(word-slice, '==')) - 240 # write-stream-buffered(out, line) - 241 # return - 242 # - 243 # . prolog - 244 55/push-EBP - 245 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 246 # . save registers - 247 51/push-ECX - 248 # var word-slice/ECX = {0, 0} - 249 68/push 0/imm32/end - 250 68/push 0/imm32/start - 251 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 252 # next-word(line, word-slice) - 253 # . . push args - 254 51/push-ECX - 255 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 256 # . . call - 257 e8/call next-word/disp32 - 258 # . . discard args - 259 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 260 $convert-instruction:pass-line-through: - 261 # write-stream-buffered(out, line) - 262 # . . push args - 263 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 264 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 265 # . . call - 266 e8/call write-stream-buffered/disp32 - 267 # . . discard args - 268 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 269 $convert-instruction:end: - 270 # . restore registers - 271 59/pop-to-ECX - 272 # . epilog - 273 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 274 5d/pop-to-EBP - 275 c3/return - 276 - 277 test-convert-instruction-passes-comments-through: - 278 # if a line starts with '#', pass it along unchanged - 279 # . prolog - 280 55/push-EBP - 281 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 282 # setup - 283 # . clear-stream(_test-stream) - 284 # . . push args - 285 68/push _test-stream/imm32 - 286 # . . call - 287 e8/call clear-stream/disp32 - 288 # . . discard args - 289 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 290 # . clear-stream(_test-buffered-file+4) - 291 # . . push args - 292 b8/copy-to-EAX _test-buffered-file/imm32 - 293 05/add-to-EAX 4/imm32 - 294 50/push-EAX - 295 # . . call - 296 e8/call clear-stream/disp32 - 297 # . . discard args - 298 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 299 # . clear-stream(_test-tmp-stream) - 300 # . . push args - 301 68/push _test-tmp-stream/imm32 - 302 # . . call - 303 e8/call clear-stream/disp32 - 304 # . . discard args - 305 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 306 # initialize input - 307 # . write(_test-tmp-stream, "# abcd") - 308 # . . push args - 309 68/push "# abcd"/imm32 - 310 68/push _test-tmp-stream/imm32 - 311 # . . call - 312 e8/call write/disp32 - 313 # . . discard args - 314 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 315 # convert-instruction(_test-tmp-stream, _test-buffered-file) - 316 # . . push args - 317 68/push _test-buffered-file/imm32 - 318 68/push _test-tmp-stream/imm32 - 319 # . . call - 320 e8/call convert-instruction/disp32 - 321 # . . discard args - 322 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 323 # check that the write happened as expected - 324 # . flush(_test-buffered-file) - 325 # . . push args - 326 68/push _test-buffered-file/imm32 - 327 # . . call - 328 e8/call flush/disp32 - 329 # . . discard args - 330 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 331 # . check-stream-equal(_test-stream, "# abcd", msg) - 332 # . . push args - 333 68/push "F - test-convert-instruction-passes-comments-through"/imm32 - 334 68/push "# abcd"/imm32 - 335 68/push _test-stream/imm32 - 336 # . . call - 337 e8/call check-stream-equal/disp32 - 338 # . . discard args - 339 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 340 # . epilog - 341 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 342 5d/pop-to-EBP - 343 c3/return - 344 - 345 test-convert-instruction-passes-segment-headers-through: - 346 # if a line starts with '==', pass it along unchanged - 347 # . prolog - 348 55/push-EBP - 349 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 350 # setup - 351 # . clear-stream(_test-stream) + 86 # conceptual hierarchy within a line: + 87 # line = words separated by ' ', maybe followed by comment starting with '#' + 88 # word = name until '/', then 0 or more metadata separated by '/' + 89 # + 90 # we won't bother saving the internal structure of lines; reparsing should be cheap using three primitives: + 91 # next-token(stream, delim char) -> slice (start, end pointers) + 92 # next-token-from-slice(start, end, delim char) -> slice + 93 # slice-equal?(slice, string) + 94 + 95 convert: # in : (address buffered-file), out : (address buffered-file) -> <void> + 96 # pseudocode: + 97 # var line = new-stream(512, 1) + 98 # var in-code? = false + 99 # while true + 100 # clear-stream(line) + 101 # read-line(in, line) + 102 # if (line->write == 0) break # end of file + 103 # var word-slice = next-word(line) + 104 # if slice-empty?(word-slice) # whitespace + 105 # write-stream-buffered(out, line) + 106 # else if (slice-equal?(word-slice, "==")) + 107 # word-slice = next-word(line) + 108 # in-code? = slice-equal?(word-slice, "code") + 109 # write-stream-buffered(out, line) + 110 # else if (in-code?) + 111 # rewind-stream(line) + 112 # convert-instruction(line, out) + 113 # else + 114 # rewind-stream(line) + 115 # convert-data(line, out) + 116 # flush(out) + 117 # + 118 # . prolog + 119 55/push-EBP + 120 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 121 # . save registers + 122 50/push-EAX + 123 51/push-ECX + 124 52/push-EDX + 125 53/push-EBX + 126 # var line/ECX : (address stream byte) = stream(512) + 127 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0x200/imm32 # subtract from ESP + 128 68/push 0x200/imm32/length + 129 68/push 0/imm32/read + 130 68/push 0/imm32/write + 131 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 132 # var word-slice/EDX = {0, 0} + 133 68/push 0/imm32/end + 134 68/push 0/imm32/curr + 135 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX + 136 # var in-code?/EBX = false + 137 68/push 0/imm32/false + 138 89/copy 3/mod/direct 3/rm32/EBX . . . 4/r32/ESP . . # copy ESP to EBX + 139 $convert:loop: + 140 # clear-stream(line) + 141 # . . push args + 142 51/push-ECX + 143 # . . call + 144 e8/call clear-stream/disp32 + 145 # . . discard args + 146 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 147 # read-line(in, line) + 148 # . . push args + 149 51/push-ECX + 150 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 151 # . . call + 152 e8/call read-line/disp32 + 153 # . . discard args + 154 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 155 $convert:check0: + 156 # if (line->write == 0) break + 157 81 7/subop/compare 0/mod/indirect 1/rm32/ECX . . . . . 0/imm32 # compare *ECX + 158 0f 84/jump-if-equal $convert:break/disp32 + 159 +-- 34 lines: #? # dump current line --------------------------------------------------------------------------------------------------------------------- + 193 # next-word(line, word-slice) + 194 # . . push args + 195 52/push-EDX + 196 51/push-ECX + 197 # . . call + 198 e8/call next-word/disp32 + 199 # . . discard args + 200 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 201 $convert:check1: + 202 # if (slice-empty?(word-slice)) write-stream-buffered(out, line) + 203 # . EAX = slice-empty?(word-slice) + 204 # . . push args + 205 52/push-EDX + 206 # . . call + 207 e8/call slice-empty?/disp32 + 208 # . . discard args + 209 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 210 # . if (EAX != 0) write-stream-buffered(out, line) + 211 3d/compare-EAX 0/imm32 + 212 0f 85/jump-if-not-equal $convert:pass-through/disp32 + 213 $convert:check2: + 214 +-- 50 lines: #? # dump current word --------------------------------------------------------------------------------------------------------------------- + 264 # if (slice-equal?(word-slice, "==")) + 265 # word-slice = next-word(line) + 266 # in-code? = slice-equal?(word-slice, "code") + 267 # write-stream-buffered(out, line) + 268 # . EAX = slice-equal?(word-slice, "==") + 269 # . . push args + 270 68/push "=="/imm32 + 271 52/push-EDX + 272 # . . call + 273 e8/call slice-equal?/disp32 + 274 # . . discard args + 275 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 276 # . if (EAX == 0) goto check3 + 277 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX + 278 0f 84/jump-if-equal $convert:check3/disp32 + 279 # . next-word(line, word-slice) + 280 # . . push args + 281 52/push-EDX + 282 51/push-ECX + 283 # . . call + 284 e8/call next-word/disp32 + 285 # . . discard args + 286 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 287 +-- 50 lines: #? # dump segment name --------------------------------------------------------------------------------------------------------------------- + 337 # . in-code? = slice-equal?(word-slice, "code") + 338 # . . push args + 339 68/push "code"/imm32 + 340 52/push-EDX + 341 # . . call + 342 e8/call slice-equal?/disp32 + 343 # . . discard args + 344 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 345 # . . in-code? = EAX + 346 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX + 347 # . goto pass-through + 348 eb/jump $convert:pass-through/disp8 + 349 $convert:check3: + 350 # else rewind-stream(line) + 351 # . rewind-stream(line) 352 # . . push args - 353 68/push _test-stream/imm32 + 353 51/push-ECX 354 # . . call - 355 e8/call clear-stream/disp32 + 355 e8/call rewind-stream/disp32 356 # . . discard args 357 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 358 # . clear-stream(_test-buffered-file+4) - 359 # . . push args - 360 b8/copy-to-EAX _test-buffered-file/imm32 - 361 05/add-to-EAX 4/imm32 - 362 50/push-EAX - 363 # . . call - 364 e8/call clear-stream/disp32 - 365 # . . discard args - 366 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 367 # . clear-stream(_test-tmp-stream) - 368 # . . push args - 369 68/push _test-tmp-stream/imm32 - 370 # . . call - 371 e8/call clear-stream/disp32 - 372 # . . discard args - 373 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 374 # initialize input - 375 # . write(_test-tmp-stream, "== abcd") - 376 # . . push args - 377 68/push "== abcd"/imm32 - 378 68/push _test-tmp-stream/imm32 - 379 # . . call - 380 e8/call write/disp32 - 381 # . . discard args - 382 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 383 # convert-instruction(_test-tmp-stream, _test-buffered-file) - 384 # . . push args - 385 68/push _test-buffered-file/imm32 - 386 68/push _test-tmp-stream/imm32 - 387 # . . call - 388 e8/call convert-instruction/disp32 - 389 # . . discard args - 390 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 391 # check that the write happened as expected - 392 # . flush(_test-buffered-file) - 393 # . . push args - 394 68/push _test-buffered-file/imm32 - 395 # . . call - 396 e8/call flush/disp32 - 397 # . . discard args - 398 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 399 # . check-stream-equal(_test-stream, "== abcd", msg) - 400 # . . push args - 401 68/push "F - test-convert-instruction-passes-segment-headers-through"/imm32 - 402 68/push "== abcd"/imm32 - 403 68/push _test-stream/imm32 - 404 # . . call - 405 e8/call check-stream-equal/disp32 - 406 # . . discard args - 407 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 408 # . epilog - 409 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 410 5d/pop-to-EBP - 411 c3/return - 412 - 413 test-convert-instruction-passes-empty-lines-through: - 414 # if a line is empty, pass it along unchanged - 415 # . prolog - 416 55/push-EBP - 417 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 418 # setup - 419 # . clear-stream(_test-stream) - 420 # . . push args - 421 68/push _test-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-buffered-file+4) - 427 # . . push args - 428 b8/copy-to-EAX _test-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 # . clear-stream(_test-tmp-stream) - 436 # . . push args - 437 68/push _test-tmp-stream/imm32 - 438 # . . call - 439 e8/call clear-stream/disp32 - 440 # . . discard args - 441 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 442 # write nothing to input - 443 # convert-instruction(_test-tmp-stream, _test-buffered-file) - 444 # . . push args - 445 68/push _test-buffered-file/imm32 - 446 68/push _test-tmp-stream/imm32 - 447 # . . call - 448 e8/call convert-instruction/disp32 - 449 # . . discard args - 450 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 451 # check that the write happened as expected - 452 # . flush(_test-buffered-file) - 453 # . . push args - 454 68/push _test-buffered-file/imm32 - 455 # . . call - 456 e8/call flush/disp32 - 457 # . . discard args - 458 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 459 # . check-stream-equal(_test-stream, "", msg) - 460 # . . push args - 461 68/push "F - test-convert-instruction-passes-empty-lines-through"/imm32 - 462 68/push ""/imm32 - 463 68/push _test-stream/imm32 - 464 # . . call - 465 e8/call check-stream-equal/disp32 - 466 # . . discard args - 467 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 468 # . epilog - 469 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 470 5d/pop-to-EBP - 471 c3/return - 472 - 473 test-convert-instruction-passes-lines-with-just-whitespace-through: - 474 # if a line is empty, pass it along unchanged - 475 # . prolog - 476 55/push-EBP - 477 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 478 # setup - 479 # . clear-stream(_test-stream) - 480 # . . push args - 481 68/push _test-stream/imm32 - 482 # . . call - 483 e8/call clear-stream/disp32 - 484 # . . discard args - 485 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 486 # . clear-stream(_test-buffered-file+4) - 487 # . . push args - 488 b8/copy-to-EAX _test-buffered-file/imm32 - 489 05/add-to-EAX 4/imm32 - 490 50/push-EAX - 491 # . . call - 492 e8/call clear-stream/disp32 - 493 # . . discard args - 494 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 495 # . clear-stream(_test-tmp-stream) - 496 # . . push args - 497 68/push _test-tmp-stream/imm32 - 498 # . . call - 499 e8/call clear-stream/disp32 - 500 # . . discard args - 501 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 502 # initialize input - 503 # . write(_test-tmp-stream, " ") - 504 # . . push args - 505 68/push " "/imm32 - 506 68/push _test-tmp-stream/imm32 - 507 # . . call - 508 e8/call write/disp32 - 509 # . . discard args - 510 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 511 # convert-instruction(_test-tmp-stream, _test-buffered-file) - 512 # . . push args - 513 68/push _test-buffered-file/imm32 - 514 68/push _test-tmp-stream/imm32 - 515 # . . call - 516 e8/call convert-instruction/disp32 - 517 # . . discard args - 518 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 519 # check that the write happened as expected - 520 # . flush(_test-buffered-file) - 521 # . . push args - 522 68/push _test-buffered-file/imm32 - 523 # . . call - 524 e8/call flush/disp32 - 525 # . . discard args - 526 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 527 # . check-stream-equal(_test-stream, " ", msg) - 528 # . . push args - 529 68/push "F - test-convert-instruction-passes-with-just-whitespace-through"/imm32 - 530 68/push " "/imm32 - 531 68/push _test-stream/imm32 - 532 # . . call - 533 e8/call check-stream-equal/disp32 - 534 # . . discard args - 535 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 536 # . epilog - 537 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 538 5d/pop-to-EBP - 539 c3/return - 540 - 541 test-convert-instruction-passes-labels-through: - 542 # if the first word ends with ':', pass along the entire line unchanged - 543 # . prolog - 544 55/push-EBP - 545 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 546 # setup - 547 # . clear-stream(_test-stream) + 358 # if (in-code? != 0) convert-instruction(line, out) + 359 81 7/subop/compare 3/mod/direct 3/rm32/EBX . . . . . 0/imm32 # compare EBX + 360 74/jump-if-equal $convert:data/disp8 + 361 $convert:code: + 362 # . convert-instruction(line, out) + 363 # . . push args + 364 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 365 51/push-ECX + 366 # . . call + 367 e8/call convert-instruction/disp32 + 368 # . . discard args + 369 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 370 # . loop + 371 e9/jump $convert:loop/disp32 + 372 $convert:data: + 373 # else convert-data(line, out) + 374 # . . push args + 375 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 376 51/push-ECX + 377 # . . call + 378 e8/call convert-data/disp32 + 379 # . . discard args + 380 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 381 # . loop + 382 e9/jump $convert:loop/disp32 + 383 $convert:pass-through: + 384 # write-stream-buffered(out, line) + 385 # . . push args + 386 51/push-ECX + 387 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 388 # . . call + 389 e8/call write-stream-buffered/disp32 + 390 # . . discard args + 391 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 392 # . loop + 393 e9/jump $convert:loop/disp32 + 394 $convert:break: + 395 # flush(out) + 396 # . . push args + 397 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 398 # . . call + 399 e8/call flush/disp32 + 400 # . . discard args + 401 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 402 $convert:end: + 403 # . reclaim locals + 404 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x218/imm32 # add to ESP + 405 # . restore registers + 406 5b/pop-to-EBX + 407 5a/pop-to-EDX + 408 59/pop-to-ECX + 409 58/pop-to-EAX + 410 # . epilog + 411 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 412 5d/pop-to-EBP + 413 c3/return + 414 + 415 test-convert-passes-empty-lines-through: + 416 # if a line is empty, pass it along unchanged + 417 # . prolog + 418 55/push-EBP + 419 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 420 # setup + 421 # . clear-stream(_test-input-stream) + 422 # . . push args + 423 68/push _test-input-stream/imm32 + 424 # . . call + 425 e8/call clear-stream/disp32 + 426 # . . discard args + 427 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 428 # . clear-stream(_test-input-buffered-file+4) + 429 # . . push args + 430 b8/copy-to-EAX _test-input-buffered-file/imm32 + 431 05/add-to-EAX 4/imm32 + 432 50/push-EAX + 433 # . . call + 434 e8/call clear-stream/disp32 + 435 # . . discard args + 436 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 437 # . clear-stream(_test-output-stream) + 438 # . . push args + 439 68/push _test-output-stream/imm32 + 440 # . . call + 441 e8/call clear-stream/disp32 + 442 # . . discard args + 443 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 444 # . clear-stream(_test-output-buffered-file+4) + 445 # . . push args + 446 b8/copy-to-EAX _test-output-buffered-file/imm32 + 447 05/add-to-EAX 4/imm32 + 448 50/push-EAX + 449 # . . call + 450 e8/call clear-stream/disp32 + 451 # . . discard args + 452 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 453 # write nothing to input + 454 # convert(_test-input-buffered-file, _test-output-buffered-file) + 455 # . . push args + 456 68/push _test-output-buffered-file/imm32 + 457 68/push _test-input-buffered-file/imm32 + 458 # . . call + 459 e8/call convert/disp32 + 460 # . . discard args + 461 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 462 # check that the line just passed through + 463 # . flush(_test-output-buffered-file) + 464 # . . push args + 465 68/push _test-output-buffered-file/imm32 + 466 # . . call + 467 e8/call flush/disp32 + 468 # . . discard args + 469 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 470 # . check-stream-equal(_test-output-stream, "", msg) + 471 # . . push args + 472 68/push "F - test-convert-passes-empty-lines-through"/imm32 + 473 68/push ""/imm32 + 474 68/push _test-output-stream/imm32 + 475 # . . call + 476 e8/call check-stream-equal/disp32 + 477 # . . discard args + 478 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 479 # . epilog + 480 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 481 5d/pop-to-EBP + 482 c3/return + 483 + 484 test-convert-passes-lines-with-just-whitespace-through: + 485 # if a line is empty, pass it along unchanged + 486 # . prolog + 487 55/push-EBP + 488 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 489 # setup + 490 # . clear-stream(_test-input-stream) + 491 # . . push args + 492 68/push _test-input-stream/imm32 + 493 # . . call + 494 e8/call clear-stream/disp32 + 495 # . . discard args + 496 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 497 # . clear-stream(_test-input-buffered-file+4) + 498 # . . push args + 499 b8/copy-to-EAX _test-input-buffered-file/imm32 + 500 05/add-to-EAX 4/imm32 + 501 50/push-EAX + 502 # . . call + 503 e8/call clear-stream/disp32 + 504 # . . discard args + 505 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 506 # . clear-stream(_test-output-stream) + 507 # . . push args + 508 68/push _test-output-stream/imm32 + 509 # . . call + 510 e8/call clear-stream/disp32 + 511 # . . discard args + 512 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 513 # . clear-stream(_test-output-buffered-file+4) + 514 # . . push args + 515 b8/copy-to-EAX _test-output-buffered-file/imm32 + 516 05/add-to-EAX 4/imm32 + 517 50/push-EAX + 518 # . . call + 519 e8/call clear-stream/disp32 + 520 # . . discard args + 521 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 522 # initialize input + 523 # . write(_test-input-stream, " ") + 524 # . . push args + 525 68/push " "/imm32 + 526 68/push _test-input-stream/imm32 + 527 # . . call + 528 e8/call write/disp32 + 529 # . . discard args + 530 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 531 # convert(_test-input-buffered-file, _test-output-buffered-file) + 532 # . . push args + 533 68/push _test-output-buffered-file/imm32 + 534 68/push _test-input-buffered-file/imm32 + 535 # . . call + 536 e8/call convert/disp32 + 537 # . . discard args + 538 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 539 # check that the line just passed through + 540 # . flush(_test-output-buffered-file) + 541 # . . push args + 542 68/push _test-output-buffered-file/imm32 + 543 # . . call + 544 e8/call flush/disp32 + 545 # . . discard args + 546 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 547 # . check-next-stream-line-equal(_test-output-stream, " ", msg) 548 # . . push args - 549 68/push _test-stream/imm32 - 550 # . . call - 551 e8/call clear-stream/disp32 - 552 # . . discard args - 553 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 554 # . clear-stream(_test-buffered-file+4) - 555 # . . push args - 556 b8/copy-to-EAX _test-buffered-file/imm32 - 557 05/add-to-EAX 4/imm32 - 558 50/push-EAX - 559 # . . call - 560 e8/call clear-stream/disp32 - 561 # . . discard args - 562 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 563 # . clear-stream(_test-tmp-stream) - 564 # . . push args - 565 68/push _test-tmp-stream/imm32 - 566 # . . call - 567 e8/call clear-stream/disp32 - 568 # . . discard args - 569 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 570 # initialize input - 571 # . write(_test-tmp-stream, "ab: # cd") - 572 # . . push args - 573 68/push "ab: # cd"/imm32 - 574 68/push _test-tmp-stream/imm32 - 575 # . . call - 576 e8/call write/disp32 - 577 # . . discard args - 578 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 579 # convert-instruction(_test-tmp-stream, _test-buffered-file) - 580 # . . push args - 581 68/push _test-buffered-file/imm32 - 582 68/push _test-tmp-stream/imm32 - 583 # . . call - 584 e8/call convert-instruction/disp32 - 585 # . . discard args - 586 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 587 # check that the write happened as expected - 588 # . flush(_test-buffered-file) - 589 # . . push args - 590 68/push _test-buffered-file/imm32 - 591 # . . call - 592 e8/call flush/disp32 - 593 # . . discard args - 594 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 595 # . check-stream-equal(_test-stream, "ab: # cd", msg) - 596 # . . push args - 597 68/push "F - test-convert-instruction-passes-labels-through"/imm32 - 598 68/push "ab: # cd"/imm32 - 599 68/push _test-stream/imm32 - 600 # . . call - 601 e8/call check-stream-equal/disp32 - 602 # . . discard args - 603 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 604 # . epilog - 605 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 606 5d/pop-to-EBP - 607 c3/return - 608 - 609 # (re)compute the bounds of the next word in the line - 610 next-word: # line : (address stream byte), out : (address slice) - 611 # . prolog - 612 55/push-EBP - 613 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 614 # . save registers - 615 50/push-EAX - 616 51/push-ECX - 617 56/push-ESI - 618 57/push-EDI - 619 # ESI = line - 620 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI - 621 # EDI = out - 622 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI - 623 # skip-chars-matching(line, ' ') - 624 # . . push args - 625 68/push 0x20/imm32/space - 626 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 627 # . . call - 628 e8/call skip-chars-matching/disp32 - 629 # . . discard args - 630 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 631 # out->start = &line->data[line->read] - 632 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX - 633 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 - 634 89/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to *EDI - 635 # if (line->data[line->read] == '#') out->end = &line->data[line->write]), skip rest of stream and return - 636 # . EAX = line->data[line->read] - 637 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX - 638 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 - 639 # . compare - 640 3d/compare-EAX-with 0x23/imm32/pound - 641 75/jump-if-not-equal $next-word:not-comment/disp8 - 642 # . out->end = &line->data[line->write] - 643 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX - 644 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 - 645 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDI+4) - 646 # . line->read = line->write - 647 89/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(ESI+4) - 648 # . return - 649 eb/jump $next-word:end/disp8 - 650 $next-word:not-comment: - 651 # otherwise skip-chars-not-matching(line, ' ') + 549 68/push "F - test-convert-passes-with-just-whitespace-through"/imm32 + 550 68/push " "/imm32 + 551 68/push _test-output-stream/imm32 + 552 # . . call + 553 e8/call check-next-stream-line-equal/disp32 + 554 # . . discard args + 555 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 556 # . epilog + 557 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 558 5d/pop-to-EBP + 559 c3/return + 560 + 561 test-convert-passes-segment-headers-through: + 562 # if a line starts with '==', pass it along unchanged + 563 # . prolog + 564 55/push-EBP + 565 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 566 # setup + 567 # . clear-stream(_test-input-stream) + 568 # . . push args + 569 68/push _test-input-stream/imm32 + 570 # . . call + 571 e8/call clear-stream/disp32 + 572 # . . discard args + 573 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 574 # . clear-stream(_test-input-buffered-file+4) + 575 # . . push args + 576 b8/copy-to-EAX _test-input-buffered-file/imm32 + 577 05/add-to-EAX 4/imm32 + 578 50/push-EAX + 579 # . . call + 580 e8/call clear-stream/disp32 + 581 # . . discard args + 582 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 583 # . clear-stream(_test-output-stream) + 584 # . . push args + 585 68/push _test-output-stream/imm32 + 586 # . . call + 587 e8/call clear-stream/disp32 + 588 # . . discard args + 589 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 590 # . clear-stream(_test-output-buffered-file+4) + 591 # . . push args + 592 b8/copy-to-EAX _test-output-buffered-file/imm32 + 593 05/add-to-EAX 4/imm32 + 594 50/push-EAX + 595 # . . call + 596 e8/call clear-stream/disp32 + 597 # . . discard args + 598 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 599 # initialize input + 600 # . write(_test-input-stream, "== abcd") + 601 # . . push args + 602 68/push "== abcd"/imm32 + 603 68/push _test-input-stream/imm32 + 604 # . . call + 605 e8/call write/disp32 + 606 # . . discard args + 607 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 608 # convert(_test-input-buffered-file, _test-output-buffered-file) + 609 # . . push args + 610 68/push _test-output-buffered-file/imm32 + 611 68/push _test-input-buffered-file/imm32 + 612 # . . call + 613 e8/call convert/disp32 + 614 # . . discard args + 615 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 616 # check that the line just passed through + 617 # . flush(_test-output-buffered-file) + 618 # . . push args + 619 68/push _test-output-buffered-file/imm32 + 620 # . . call + 621 e8/call flush/disp32 + 622 # . . discard args + 623 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 624 # . check-stream-equal(_test-output-stream, "== abcd", msg) + 625 # . . push args + 626 68/push "F - test-convert-passes-segment-headers-through"/imm32 + 627 68/push "== abcd"/imm32 + 628 68/push _test-output-stream/imm32 + 629 # . . call + 630 e8/call check-stream-equal/disp32 + 631 # . . discard args + 632 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 633 # . epilog + 634 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 635 5d/pop-to-EBP + 636 c3/return + 637 + 638 test-convert-in-data-segment: + 639 # correctly process lines in the data segment + 640 # . prolog + 641 55/push-EBP + 642 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 643 # setup + 644 # . clear-stream(_test-input-stream) + 645 # . . push args + 646 68/push _test-input-stream/imm32 + 647 # . . call + 648 e8/call clear-stream/disp32 + 649 # . . discard args + 650 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 651 # . clear-stream(_test-input-buffered-file+4) 652 # . . push args - 653 68/push 0x20/imm32/space - 654 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 655 # . . call - 656 e8/call skip-chars-not-matching/disp32 - 657 # . . discard args - 658 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 659 # out->end = &line->data[line->read] - 660 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX - 661 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 - 662 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDI+4) - 663 $next-word:end: - 664 # . restore registers - 665 5f/pop-to-EDI - 666 5e/pop-to-ESI - 667 59/pop-to-ECX - 668 58/pop-to-EAX - 669 # . epilog - 670 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 671 5d/pop-to-EBP - 672 c3/return - 673 - 674 test-next-word: - 675 # . prolog - 676 55/push-EBP - 677 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 678 # setup - 679 # . clear-stream(_test-stream) - 680 # . . push args - 681 68/push _test-stream/imm32 - 682 # . . call - 683 e8/call clear-stream/disp32 - 684 # . . discard args - 685 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 686 # var slice/ECX = {0, 0} - 687 68/push 0/imm32/end - 688 68/push 0/imm32/start - 689 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 690 # write(_test-stream, " ab") - 691 # . . push args - 692 68/push " ab"/imm32 - 693 68/push _test-stream/imm32 - 694 # . . call - 695 e8/call write/disp32 - 696 # . . discard args - 697 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 698 # next-word(_test-stream, slice) - 699 # . . push args - 700 51/push-ECX - 701 68/push _test-stream/imm32 - 702 # . . call - 703 e8/call next-word/disp32 - 704 # . . discard args - 705 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 706 # check-ints-equal(slice->start - _test-stream->data, 2, msg) - 707 # . check-ints-equal(slice->start - _test-stream, 14, msg) - 708 # . . push args - 709 68/push "F - test-next-word: start"/imm32 - 710 68/push 0xe/imm32 - 711 # . . push slice->start - _test-stream - 712 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX - 713 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-stream/imm32 # subtract from EAX - 714 50/push-EAX - 715 # . . call - 716 e8/call check-ints-equal/disp32 - 717 # . . discard args - 718 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 719 # check-ints-equal(slice->end - _test-stream->data, 4, msg) - 720 # . check-ints-equal(slice->end - _test-stream, 16, msg) - 721 # . . push args - 722 68/push "F - test-next-word: end"/imm32 - 723 68/push 0x10/imm32 - 724 # . . push slice->end - _test-stream - 725 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX - 726 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-stream/imm32 # subtract from EAX - 727 50/push-EAX - 728 # . . call - 729 e8/call check-ints-equal/disp32 - 730 # . . discard args - 731 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 732 # . epilog - 733 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 734 5d/pop-to-EBP - 735 c3/return - 736 - 737 test-next-word-returns-whole-comment: - 738 # . prolog - 739 55/push-EBP - 740 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 741 # setup - 742 # . clear-stream(_test-stream) - 743 # . . push args - 744 68/push _test-stream/imm32 - 745 # . . call - 746 e8/call clear-stream/disp32 - 747 # . . discard args - 748 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 749 # var slice/ECX = {0, 0} - 750 68/push 0/imm32/end - 751 68/push 0/imm32/start - 752 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 753 # write(_test-stream, " # a") - 754 # . . push args - 755 68/push " # a"/imm32 - 756 68/push _test-stream/imm32 - 757 # . . call - 758 e8/call write/disp32 - 759 # . . discard args - 760 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 761 # next-word(_test-stream, slice) - 762 # . . push args - 763 51/push-ECX - 764 68/push _test-stream/imm32 - 765 # . . call - 766 e8/call next-word/disp32 - 767 # . . discard args - 768 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 769 # check-ints-equal(slice->start - _test-stream->data, 2, msg) - 770 # . check-ints-equal(slice->start - _test-stream, 14, msg) - 771 # . . push args - 772 68/push "F - test-next-word-returns-whole-comment: start"/imm32 - 773 68/push 0xe/imm32 - 774 # . . push slice->start - _test-stream - 775 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX - 776 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-stream/imm32 # subtract from EAX - 777 50/push-EAX - 778 # . . call - 779 e8/call check-ints-equal/disp32 - 780 # . . discard args - 781 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 782 # check-ints-equal(slice->end - _test-stream->data, 5, msg) - 783 # . check-ints-equal(slice->end - _test-stream, 17, msg) - 784 # . . push args - 785 68/push "F - test-next-word-returns-whole-comment: end"/imm32 - 786 68/push 0x11/imm32 - 787 # . . push slice->end - _test-stream - 788 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX - 789 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-stream/imm32 # subtract from EAX - 790 50/push-EAX - 791 # . . call - 792 e8/call check-ints-equal/disp32 - 793 # . . discard args - 794 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 795 # . epilog - 796 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 797 5d/pop-to-EBP - 798 c3/return - 799 - 800 has-metadata?: # word : (address slice), s : (address string) -> EAX : boolean - 801 # pseudocode: - 802 # var twig : &slice = next-token-from-slice(word->start, word->end, '/') # skip name - 803 # curr = twig->end - 804 # while true: - 805 # twig = next-token-from-slice(curr, word->end, '/') - 806 # if (twig.empty()) break - 807 # if (slice-equal?(twig, s)) return true - 808 # curr = twig->end - 809 # return false - 810 # . prolog - 811 55/push-EBP - 812 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 813 # . save registers - 814 51/push-ECX - 815 52/push-EDX - 816 56/push-ESI - 817 57/push-EDI - 818 # ESI = word - 819 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI - 820 # EDX = word->end - 821 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 2/r32/EDX 4/disp8 . # copy *(ESI+4) to EDX - 822 # var twig/EDI : (address slice) = {0, 0} - 823 68/push 0/imm32/end - 824 68/push 0/imm32/start - 825 89/copy 3/mod/direct 7/rm32/EDI . . . 4/r32/ESP . . # copy ESP to EDI - 826 # next-token-from-slice(word->start, word->end, '/', twig) - 827 # . . push args - 828 57/push-EDI - 829 68/push 0x2f/imm32/slash - 830 52/push-EDX - 831 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI - 832 # . . call - 833 e8/call next-token-from-slice/disp32 - 834 # . . discard args - 835 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP - 836 # curr/ECX = twig->end - 837 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 1/r32/ECX 4/disp8 . # copy *(EDI+4) to ECX - 838 $has-metadata?:loop: - 839 # next-token-from-slice(curr, word->end, '/', twig) - 840 # . . push args - 841 57/push-EDI - 842 68/push 0x2f/imm32/slash - 843 52/push-EDX - 844 51/push-ECX - 845 # . . call - 846 e8/call next-token-from-slice/disp32 - 847 # . . discard args - 848 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP - 849 # if (slice-empty?(twig)) return false - 850 # . EAX = slice-empty?(twig) - 851 # . . push args - 852 57/push-EDI - 853 # . . call - 854 e8/call slice-empty?/disp32 - 855 # . . discard args - 856 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 857 # . if (EAX != 0) return false - 858 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX - 859 75/compare-if-not-equal $has-metadata?:false/disp8 - 860 # if (slice-equal?(twig, s)) return true - 861 # . EAX = slice-equal?(twig, s) - 862 # . . push args - 863 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 864 57/push-EDI - 865 # . . call - 866 e8/call slice-equal?/disp32 - 867 # . . discard args - 868 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 869 # . if (EAX != 0) return true - 870 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX - 871 75/compare-if-not-equal $has-metadata?:true/disp8 - 872 # curr = twig->end - 873 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 1/r32/ECX 4/disp8 . # copy *(EDI+4) to ECX - 874 eb/jump $has-metadata?:loop/disp8 - 875 $has-metadata?:true: - 876 b8/copy-to-EAX 1/imm32/true - 877 eb/jump $has-metadata?:end/disp8 - 878 $has-metadata?:false: - 879 b8/copy-to-EAX 0/imm32/false - 880 $has-metadata?:end: - 881 # . reclaim locals - 882 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 883 # . restore registers - 884 5f/pop-to-EDI - 885 5e/pop-to-ESI - 886 5a/pop-to-EDX - 887 59/pop-to-ECX - 888 # . epilog - 889 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 890 5d/pop-to-EBP - 891 c3/return - 892 - 893 test-has-metadata-true: - 894 # . prolog - 895 55/push-EBP - 896 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 897 # (EAX..ECX) = "ab/c" - 898 b8/copy-to-EAX "ab/c"/imm32 - 899 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX - 900 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 - 901 05/add-to-EAX 4/imm32 - 902 # var in/ESI : (address slice) = {EAX, ECX} - 903 51/push-ECX - 904 50/push-EAX - 905 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI - 906 # EAX = has-metadata?(ESI, "c") - 907 # . . push args - 908 68/push "c"/imm32 - 909 56/push-ESI - 910 # . . call - 911 e8/call has-metadata?/disp32 - 912 # . . discard args - 913 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x8/imm32 # add to ESP - 914 # check-ints-equal(EAX, 1, msg) - 915 # . . push args - 916 68/push "F - test-has-metadata-true"/imm32 - 917 68/push 1/imm32/true - 918 50/push-EAX - 919 # . . call - 920 e8/call check-ints-equal/disp32 - 921 # . . discard args - 922 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 923 # . epilog - 924 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 925 5d/pop-to-EBP - 926 c3/return - 927 - 928 test-has-metadata-false: - 929 # . prolog - 930 55/push-EBP - 931 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 932 # (EAX..ECX) = "ab/c" - 933 b8/copy-to-EAX "ab/c"/imm32 - 934 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX - 935 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 - 936 05/add-to-EAX 4/imm32 - 937 # var in/ESI : (address slice) = {EAX, ECX} - 938 51/push-ECX - 939 50/push-EAX - 940 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI - 941 # EAX = has-metadata?(ESI, "c") - 942 # . . push args - 943 68/push "d"/imm32 - 944 56/push-ESI - 945 # . . call - 946 e8/call has-metadata?/disp32 - 947 # . . discard args - 948 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x8/imm32 # add to ESP - 949 # check-ints-equal(EAX, 0, msg) - 950 # . . push args - 951 68/push "F - test-has-metadata-false"/imm32 - 952 68/push 0/imm32/false - 953 50/push-EAX - 954 # . . call - 955 e8/call check-ints-equal/disp32 - 956 # . . discard args - 957 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 958 # . epilog - 959 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 960 5d/pop-to-EBP - 961 c3/return - 962 - 963 test-has-metadata-ignore-name: - 964 # . prolog - 965 55/push-EBP - 966 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 967 # (EAX..ECX) = "a/b" - 968 b8/copy-to-EAX "a/b"/imm32 - 969 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX - 970 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 - 971 05/add-to-EAX 4/imm32 - 972 # var in/ESI : (address slice) = {EAX, ECX} - 973 51/push-ECX - 974 50/push-EAX - 975 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI - 976 # EAX = has-metadata?(ESI, "a") - 977 # . . push args - 978 68/push "a"/imm32 - 979 56/push-ESI - 980 # . . call - 981 e8/call has-metadata?/disp32 - 982 # . . discard args - 983 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x8/imm32 # add to ESP - 984 # check-ints-equal(EAX, 0, msg) - 985 # . . push args - 986 68/push "F - test-has-metadata-ignore-name"/imm32 - 987 68/push 0/imm32/false - 988 50/push-EAX - 989 # . . call - 990 e8/call check-ints-equal/disp32 - 991 # . . discard args - 992 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 993 # . epilog - 994 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 995 5d/pop-to-EBP - 996 c3/return - 997 - 998 test-has-metadata-multiple-true: - 999 # . prolog -1000 55/push-EBP -1001 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1002 # (EAX..ECX) = "a/b/c" -1003 b8/copy-to-EAX "a/b/c"/imm32 -1004 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -1005 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 -1006 05/add-to-EAX 4/imm32 -1007 # var in/ESI : (address slice) = {EAX, ECX} -1008 51/push-ECX -1009 50/push-EAX -1010 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI -1011 # EAX = has-metadata?(ESI, "c") -1012 # . . push args -1013 68/push "c"/imm32 -1014 56/push-ESI -1015 # . . call -1016 e8/call has-metadata?/disp32 -1017 # . . discard args -1018 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x8/imm32 # add to ESP -1019 # check-ints-equal(EAX, 1, msg) -1020 # . . push args -1021 68/push "F - test-has-metadata-multiple-true"/imm32 -1022 68/push 1/imm32/true -1023 50/push-EAX -1024 # . . call -1025 e8/call check-ints-equal/disp32 -1026 # . . discard args -1027 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1028 # . epilog -1029 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1030 5d/pop-to-EBP -1031 c3/return -1032 -1033 test-has-metadata-multiple-false: -1034 # . prolog -1035 55/push-EBP -1036 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1037 # (EAX..ECX) = "a/b/c" -1038 b8/copy-to-EAX "a/b/c"/imm32 -1039 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -1040 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 -1041 05/add-to-EAX 4/imm32 -1042 # var in/ESI : (address slice) = {EAX, ECX} -1043 51/push-ECX -1044 50/push-EAX -1045 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI -1046 # EAX = has-metadata?(ESI, "d") -1047 # . . push args -1048 68/push "d"/imm32 -1049 56/push-ESI -1050 # . . call -1051 e8/call has-metadata?/disp32 -1052 # . . discard args -1053 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x8/imm32 # add to ESP -1054 # check-ints-equal(EAX, 0, msg) -1055 # . . push args -1056 68/push "F - test-has-metadata-multiple-false"/imm32 -1057 68/push 0/imm32/false -1058 50/push-EAX -1059 # . . call -1060 e8/call check-ints-equal/disp32 -1061 # . . discard args -1062 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1063 # . epilog -1064 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1065 5d/pop-to-EBP -1066 c3/return -1067 -1068 # if the name of 'word' is all hex digits, parse and print its value in 'width' bytes of hex, least significant first -1069 # otherwise just print the entire word -1070 emit: # out : (address buffered-file), word : (address slice), width : int -1071 # . prolog -1072 55/push-EBP -1073 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1074 # . save registers -1075 50/push-EAX -1076 56/push-ESI -1077 57/push-EDI -1078 # ESI = word -1079 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI -1080 # var name/EDI : (address slice) = {0, 0} -1081 68/push 0/imm32/end -1082 68/push 0/imm32/start -1083 89/copy 3/mod/direct 7/rm32/EDI . . . 4/r32/ESP . . # copy ESP to EDI -1084 # name = next-token-from-slice(word->start, word->end, '/') -1085 # . . push args -1086 57/push-EDI -1087 68/push 0x2f/imm32/slash -1088 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) -1089 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI -1090 # . . call -1091 e8/call next-token-from-slice/disp32 -1092 # . . discard args -1093 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -1094 # if (!is-hex-int?(name)) write-slice(out, word) and return -1095 # . is-hex-int?(name) -1096 # . . push args -1097 57/push-EDI -1098 # . . call -1099 e8/call is-hex-int?/disp32 -1100 # . . discard args -1101 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1102 # . if (EAX == 0) -1103 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX -1104 75/jump-if-not-equal $emit:hex-int/disp8 -1105 # . write-slice(out, word) -1106 # . . push args -1107 56/push-ESI -1108 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -1109 # . . call -1110 e8/call write-slice/disp32 -1111 # . . discard args -1112 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1113 # . return -1114 eb/jump $emit:end/disp8 -1115 # otherwise emit-hex(out, parse-hex-int(name), width) -1116 $emit:hex-int: -1117 # . n/EAX = parse-hex-int(name) -1118 # . . push args -1119 57/push-EDI -1120 # . . call -1121 e8/call parse-hex-int/disp32 -1122 # . . discard args -1123 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1124 # . emit-hex(out, n, width) -1125 # . . push args -1126 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) -1127 50/push-EAX -1128 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -1129 # . . call -1130 e8/call emit-hex/disp32 -1131 # . . discard args -1132 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1133 $emit:end: -1134 # . reclaim locals -1135 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1136 # . restore registers -1137 5f/pop-to-EDI -1138 5e/pop-to-ESI -1139 58/pop-to-EAX -1140 # . epilog -1141 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1142 5d/pop-to-EBP -1143 c3/return -1144 -1145 test-emit-number: -1146 # . prolog -1147 55/push-EBP -1148 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1149 # setup -1150 # . clear-stream(_test-stream) -1151 # . . push args -1152 68/push _test-stream/imm32 -1153 # . . call -1154 e8/call clear-stream/disp32 -1155 # . . discard args -1156 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1157 # . clear-stream(_test-buffered-file+4) -1158 # . . push args -1159 b8/copy-to-EAX _test-buffered-file/imm32 -1160 05/add-to-EAX 4/imm32 -1161 50/push-EAX -1162 # . . call -1163 e8/call clear-stream/disp32 -1164 # . . discard args -1165 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1166 # var slice/ECX = "-2" -1167 68/push _test-slice-negative-two-end/imm32/end -1168 68/push _test-slice-negative-two/imm32/start -1169 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1170 # emit(_test-buffered-file, slice, 2) -1171 # . . push args -1172 68/push 2/imm32 -1173 51/push-ECX -1174 68/push _test-buffered-file/imm32 -1175 # . . call -1176 e8/call emit/disp32 -1177 # . . discard args -1178 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1179 # flush(_test-buffered-file) -1180 # . . push args -1181 68/push _test-buffered-file/imm32 -1182 # . . call -1183 e8/call flush/disp32 -1184 # . . discard args -1185 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1186 # check(_test-stream->data == 'fe ff ') -1187 # . check-ints-equal(_test-stream->data[0..3], 'fe f', msg) -1188 # . . push args -1189 68/push "F - test-emit-number/1"/imm32 -1190 68/push 0x66206566/imm32 -1191 # . . push *_test-stream->data -1192 b8/copy-to-EAX _test-stream/imm32 -1193 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) -1194 # . . call -1195 e8/call check-ints-equal/disp32 -1196 # . . discard args -1197 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1198 # . check-ints-equal(_test-stream->data[4..7], 'f ', msg) + 653 b8/copy-to-EAX _test-input-buffered-file/imm32 + 654 05/add-to-EAX 4/imm32 + 655 50/push-EAX + 656 # . . call + 657 e8/call clear-stream/disp32 + 658 # . . discard args + 659 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 660 # . clear-stream(_test-output-stream) + 661 # . . push args + 662 68/push _test-output-stream/imm32 + 663 # . . call + 664 e8/call clear-stream/disp32 + 665 # . . discard args + 666 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 667 # . clear-stream(_test-output-buffered-file+4) + 668 # . . push args + 669 b8/copy-to-EAX _test-output-buffered-file/imm32 + 670 05/add-to-EAX 4/imm32 + 671 50/push-EAX + 672 # . . call + 673 e8/call clear-stream/disp32 + 674 # . . discard args + 675 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 676 # initialize input + 677 # . write(_test-input-stream, "== code") + 678 # . . push args + 679 68/push "== code"/imm32 + 680 68/push _test-input-stream/imm32 + 681 # . . call + 682 e8/call write/disp32 + 683 # . . discard args + 684 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 685 # . write(_test-input-stream, "\n") + 686 # . . push args + 687 68/push Newline/imm32 + 688 68/push _test-input-stream/imm32 + 689 # . . call + 690 e8/call write/disp32 + 691 # . . discard args + 692 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 693 # . write(_test-input-stream, "== data") + 694 # . . push args + 695 68/push "== data"/imm32 + 696 68/push _test-input-stream/imm32 + 697 # . . call + 698 e8/call write/disp32 + 699 # . . discard args + 700 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 701 # . write(_test-input-stream, "\n") + 702 # . . push args + 703 68/push Newline/imm32 + 704 68/push _test-input-stream/imm32 + 705 # . . call + 706 e8/call write/disp32 + 707 # . . discard args + 708 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 709 # . write(_test-input-stream, "3 4/imm32") + 710 # . . push args + 711 68/push "3 4/imm32"/imm32 + 712 68/push _test-input-stream/imm32 + 713 # . . call + 714 e8/call write/disp32 + 715 # . . discard args + 716 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 717 # . write(_test-input-stream, "\n") + 718 # . . push args + 719 68/push Newline/imm32 + 720 68/push _test-input-stream/imm32 + 721 # . . call + 722 e8/call write/disp32 + 723 # . . discard args + 724 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 725 # convert(_test-input-buffered-file, _test-output-buffered-file) + 726 # . . push args + 727 68/push _test-output-buffered-file/imm32 + 728 68/push _test-input-buffered-file/imm32 + 729 # . . call + 730 e8/call convert/disp32 + 731 # . . discard args + 732 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 733 # check output + 734 +-- 34 lines: #? # debug print --------------------------------------------------------------------------------------------------------------------------- + 768 # . flush(_test-output-buffered-file) + 769 # . . push args + 770 68/push _test-output-buffered-file/imm32 + 771 # . . call + 772 e8/call flush/disp32 + 773 # . . discard args + 774 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 775 # . check-next-stream-line-equal(_test-output-stream, "== code", msg) + 776 # . . push args + 777 68/push "F - test-convert-in-data-segment/0"/imm32 + 778 68/push "== code"/imm32 + 779 68/push _test-output-stream/imm32 + 780 # . . call + 781 e8/call check-next-stream-line-equal/disp32 + 782 # . . discard args + 783 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 784 # . check-next-stream-line-equal(_test-output-stream, "== data", msg) + 785 # . . push args + 786 68/push "F - test-convert-in-data-segment/1"/imm32 + 787 68/push "== data"/imm32 + 788 68/push _test-output-stream/imm32 + 789 # . . call + 790 e8/call check-next-stream-line-equal/disp32 + 791 # . . discard args + 792 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 793 # . check-next-stream-line-equal(_test-output-stream, "03 04 00 00 00 ", msg) + 794 # . . push args + 795 68/push "F - test-convert-in-data-segment/2"/imm32 + 796 68/push "03 04 00 00 00 "/imm32 + 797 68/push _test-output-stream/imm32 + 798 # . . call + 799 e8/call check-next-stream-line-equal/disp32 + 800 # . . discard args + 801 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 802 # . epilog + 803 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 804 5d/pop-to-EBP + 805 c3/return + 806 + 807 convert-data: # line : (address stream byte), out : (address buffered-file) -> <void> + 808 # pseudocode: + 809 # while true + 810 # word-slice = next-word(line) + 811 # if slice-empty?(word-slice) # end of file (maybe including trailing whitespace) + 812 # break # skip emitting some whitespace + 813 # if slice-starts-with?(word-slice, "#") # comment + 814 # write-stream-buffered(out, line) + 815 # break + 816 # if slice-ends-with?(word-slice, ":") # label + 817 # write-stream-buffered(out, line) + 818 # break + 819 # if has-metadata?(word-slice, "imm32") + 820 # emit(out, word-slice, 4) + 821 # # disp32 is not permitted in data segments, and anything else is only a byte long + 822 # else + 823 # emit(out, word-slice, 1) + 824 # + 825 # . prolog + 826 55/push-EBP + 827 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 828 # . save registers + 829 50/push-EAX + 830 51/push-ECX + 831 52/push-EDX + 832 # var word-slice/ECX = {0, 0} + 833 68/push 0/imm32/end + 834 68/push 0/imm32/start + 835 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 836 +-- 26 lines: #? # dump line ----------------------------------------------------------------------------------------------------------------------------- + 862 $convert-data:loop: + 863 # next-word(line, word-slice) + 864 # . . push args + 865 51/push-ECX + 866 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 867 # . . call + 868 e8/call next-word/disp32 + 869 # . . discard args + 870 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 871 +-- 26 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- + 897 $convert-data:check0: + 898 # if (slice-empty?(word-slice)) break + 899 # . EAX = slice-empty?(word-slice) + 900 # . . push args + 901 51/push-ECX + 902 # . . call + 903 e8/call slice-empty?/disp32 + 904 # . . discard args + 905 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 906 # . if (EAX != 0) pass through + 907 3d/compare-EAX 0/imm32 + 908 75/jump-if-not-equal $convert-data:break/disp8 + 909 $convert-data:check1: + 910 # if (slice-starts-with?(word-slice, "#")) write-stream-buffered(out, line) + 911 # . start/EDX = word-slice->start + 912 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX + 913 # . c/EAX = *start + 914 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX + 915 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 0/r32/AL . . # copy byte at *EDX to AL + 916 # . if (EAX == '#') pass through + 917 3d/compare-with-EAX 0x23/imm32/hash + 918 74/jump-if-equal $convert-data:pass-line-through/disp8 + 919 $convert-data:check2: + 920 # if (slice-ends-with?(word-slice, ":")) write-stream-buffered(out, line) + 921 # . end/EDX = word-slice->end + 922 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 2/r32/EDX 4/disp8 . # copy *(ECX+4) to EDX + 923 # . c/EAX = *(end-1) + 924 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX + 925 8a/copy-byte 1/mod/*+disp8 2/rm32/EDX . . . 0/r32/AL -1/disp8 . # copy byte at *ECX to AL + 926 # . if (EAX == ':') pass through + 927 3d/compare-with-EAX 0x3a/imm32/colon + 928 74/jump-if-equal $convert-data:pass-line-through/disp8 + 929 $convert-data:check3: + 930 # if (has-metadata?(word-slice, "imm32")) + 931 # . EAX = has-metadata?(ECX, "c") + 932 # . . push args + 933 68/push "imm32"/imm32 + 934 51/push-ECX + 935 # . . call + 936 e8/call has-metadata?/disp32 + 937 # . . discard args + 938 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x8/imm32 # add to ESP + 939 # . if (EAX == 0) process as a single byte + 940 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX + 941 74/jump-if-equal $convert-data:single-byte/disp8 + 942 $convert-data:imm32: + 943 # emit(out, word-slice, 4) + 944 # . . push args + 945 68/push 4/imm32 + 946 51/push-ECX + 947 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 948 # . . call + 949 e8/call emit/disp32 + 950 # . . discard args + 951 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 952 e9/jump $convert-data:loop/disp32 + 953 $convert-data:single-byte: + 954 # emit(out, word-slice, 1) + 955 # . . push args + 956 68/push 1/imm32 + 957 51/push-ECX + 958 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 959 # . . call + 960 e8/call emit/disp32 + 961 # . . discard args + 962 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 963 e9/jump $convert-data:loop/disp32 + 964 $convert-data:pass-line-through: + 965 # write-stream-buffered(out, line) + 966 # . . push args + 967 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 968 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 969 # . . call + 970 e8/call write-stream-buffered/disp32 + 971 # . . discard args + 972 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 973 # break + 974 $convert-data:break: + 975 $convert-data:end: + 976 # . reclaim locals + 977 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 978 # . restore registers + 979 5a/pop-to-EDX + 980 59/pop-to-ECX + 981 58/pop-to-EAX + 982 # . epilog + 983 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 984 5d/pop-to-EBP + 985 c3/return + 986 + 987 test-convert-data-passes-comments-through: + 988 # if a line starts with '#', pass it along unchanged + 989 # . prolog + 990 55/push-EBP + 991 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 992 # setup + 993 # . clear-stream(_test-input-stream) + 994 # . . push args + 995 68/push _test-input-stream/imm32 + 996 # . . call + 997 e8/call clear-stream/disp32 + 998 # . . discard args + 999 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1000 # . clear-stream(_test-output-stream) +1001 # . . push args +1002 68/push _test-output-stream/imm32 +1003 # . . call +1004 e8/call clear-stream/disp32 +1005 # . . discard args +1006 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1007 # . clear-stream(_test-output-buffered-file+4) +1008 # . . push args +1009 b8/copy-to-EAX _test-buffered-file/imm32 +1010 05/add-to-EAX 4/imm32 +1011 50/push-EAX +1012 # . . call +1013 e8/call clear-stream/disp32 +1014 # . . discard args +1015 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1016 # initialize input +1017 # . write(_test-input-stream, "# abcd") +1018 # . . push args +1019 68/push "# abcd"/imm32 +1020 68/push _test-input-stream/imm32 +1021 # . . call +1022 e8/call write/disp32 +1023 # . . discard args +1024 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1025 # convert-data(_test-input-stream, _test-output-buffered-file) +1026 # . . push args +1027 68/push _test-output-buffered-file/imm32 +1028 68/push _test-input-stream/imm32 +1029 # . . call +1030 e8/call convert-data/disp32 +1031 # . . discard args +1032 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1033 # check that the line just passed through +1034 # . flush(_test-output-buffered-file) +1035 # . . push args +1036 68/push _test-output-buffered-file/imm32 +1037 # . . call +1038 e8/call flush/disp32 +1039 # . . discard args +1040 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1041 # . check-stream-equal(_test-output-stream, "# abcd", msg) +1042 # . . push args +1043 68/push "F - test-convert-data-passes-comments-through"/imm32 +1044 68/push "# abcd"/imm32 +1045 68/push _test-output-stream/imm32 +1046 # . . call +1047 e8/call check-stream-equal/disp32 +1048 # . . discard args +1049 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1050 # . epilog +1051 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1052 5d/pop-to-EBP +1053 c3/return +1054 +1055 test-convert-data-passes-labels-through: +1056 # if the first word ends with ':', pass along the entire line unchanged +1057 # . prolog +1058 55/push-EBP +1059 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1060 # setup +1061 # . clear-stream(_test-input-stream) +1062 # . . push args +1063 68/push _test-input-stream/imm32 +1064 # . . call +1065 e8/call clear-stream/disp32 +1066 # . . discard args +1067 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1068 # . clear-stream(_test-output-stream) +1069 # . . push args +1070 68/push _test-output-stream/imm32 +1071 # . . call +1072 e8/call clear-stream/disp32 +1073 # . . discard args +1074 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1075 # . clear-stream(_test-output-buffered-file+4) +1076 # . . push args +1077 b8/copy-to-EAX _test-output-buffered-file/imm32 +1078 05/add-to-EAX 4/imm32 +1079 50/push-EAX +1080 # . . call +1081 e8/call clear-stream/disp32 +1082 # . . discard args +1083 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1084 # initialize input +1085 # . write(_test-input-stream, "ab: # cd") +1086 # . . push args +1087 68/push "ab: # cd"/imm32 +1088 68/push _test-input-stream/imm32 +1089 # . . call +1090 e8/call write/disp32 +1091 # . . discard args +1092 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1093 # convert-data(_test-input-stream, _test-output-buffered-file) +1094 # . . push args +1095 68/push _test-output-buffered-file/imm32 +1096 68/push _test-input-stream/imm32 +1097 # . . call +1098 e8/call convert-data/disp32 +1099 # . . discard args +1100 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1101 # check that the line just passed through +1102 # . flush(_test-output-buffered-file) +1103 # . . push args +1104 68/push _test-output-buffered-file/imm32 +1105 # . . call +1106 e8/call flush/disp32 +1107 # . . discard args +1108 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1109 # . check-stream-equal(_test-output-stream, "ab: # cd", msg) +1110 # . . push args +1111 68/push "F - test-convert-data-passes-labels-through"/imm32 +1112 68/push "ab: # cd"/imm32 +1113 68/push _test-output-stream/imm32 +1114 # . . call +1115 e8/call check-stream-equal/disp32 +1116 # . . discard args +1117 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1118 # . epilog +1119 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1120 5d/pop-to-EBP +1121 c3/return +1122 +1123 test-convert-data-passes-names-through: +1124 # If a word is a valid name, just emit it unchanged. +1125 # Later phases will deal with it. +1126 # . prolog +1127 55/push-EBP +1128 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1129 # setup +1130 # . clear-stream(_test-input-stream) +1131 # . . push args +1132 68/push _test-input-stream/imm32 +1133 # . . call +1134 e8/call clear-stream/disp32 +1135 # . . discard args +1136 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1137 # . clear-stream(_test-output-stream) +1138 # . . push args +1139 68/push _test-output-stream/imm32 +1140 # . . call +1141 e8/call clear-stream/disp32 +1142 # . . discard args +1143 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1144 # . clear-stream(_test-output-buffered-file+4) +1145 # . . push args +1146 b8/copy-to-EAX _test-output-buffered-file/imm32 +1147 05/add-to-EAX 4/imm32 +1148 50/push-EAX +1149 # . . call +1150 e8/call clear-stream/disp32 +1151 # . . discard args +1152 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1153 # initialize input +1154 # . write(_test-input-stream, "abcd/imm32") +1155 # . . push args +1156 68/push "abcd/imm32"/imm32 +1157 68/push _test-input-stream/imm32 +1158 # . . call +1159 e8/call write/disp32 +1160 # . . discard args +1161 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1162 # convert-data(_test-input-stream, _test-output-buffered-file) +1163 # . . push args +1164 68/push _test-output-buffered-file/imm32 +1165 68/push _test-input-stream/imm32 +1166 # . . call +1167 e8/call convert-data/disp32 +1168 # . . discard args +1169 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1170 # check that the line just passed through +1171 # . flush(_test-output-buffered-file) +1172 # . . push args +1173 68/push _test-output-buffered-file/imm32 +1174 # . . call +1175 e8/call flush/disp32 +1176 # . . discard args +1177 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1178 # . check-stream-equal(_test-output-stream, "abcd/imm32", msg) +1179 # . . push args +1180 68/push "F - test-convert-data-passes-names-through"/imm32 +1181 68/push "abcd/imm32 "/imm32 +1182 68/push _test-output-stream/imm32 +1183 # . . call +1184 e8/call check-stream-equal/disp32 +1185 # . . discard args +1186 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1187 # . epilog +1188 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1189 5d/pop-to-EBP +1190 c3/return +1191 +1192 test-convert-data-handles-imm32: +1193 # If a word has the /imm32 metadata, emit it in 4 bytes. +1194 # . prolog +1195 55/push-EBP +1196 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1197 # setup +1198 # . clear-stream(_test-input-stream) 1199 # . . push args -1200 68/push "F - test-emit-number/2"/imm32 -1201 68/push 0x2066/imm32 -1202 # . . push *_test-stream->data -1203 b8/copy-to-EAX _test-stream/imm32 -1204 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0x10/disp8 . # push *(EAX+16) -1205 # . . call -1206 e8/call check-ints-equal/disp32 -1207 # . . discard args -1208 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1209 # . epilog -1210 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1211 5d/pop-to-EBP -1212 c3/return -1213 -1214 test-emit-number-with-metadata: -1215 # . prolog -1216 55/push-EBP -1217 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1218 # setup -1219 # . clear-stream(_test-stream) -1220 # . . push args -1221 68/push _test-stream/imm32 -1222 # . . call -1223 e8/call clear-stream/disp32 -1224 # . . discard args -1225 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1226 # . clear-stream(_test-buffered-file+4) -1227 # . . push args -1228 b8/copy-to-EAX _test-buffered-file/imm32 -1229 05/add-to-EAX 4/imm32 -1230 50/push-EAX -1231 # . . call -1232 e8/call clear-stream/disp32 -1233 # . . discard args -1234 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1235 # var slice/ECX = "-2/foo" -1236 68/push _test-slice-negative-two-metadata-end/imm32/end -1237 68/push _test-slice-negative-two/imm32/start -1238 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1239 # emit(_test-buffered-file, slice, 2) +1200 68/push _test-input-stream/imm32 +1201 # . . call +1202 e8/call clear-stream/disp32 +1203 # . . discard args +1204 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1205 # . clear-stream(_test-output-stream) +1206 # . . push args +1207 68/push _test-output-stream/imm32 +1208 # . . call +1209 e8/call clear-stream/disp32 +1210 # . . discard args +1211 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1212 # . clear-stream(_test-output-buffered-file+4) +1213 # . . push args +1214 b8/copy-to-EAX _test-output-buffered-file/imm32 +1215 05/add-to-EAX 4/imm32 +1216 50/push-EAX +1217 # . . call +1218 e8/call clear-stream/disp32 +1219 # . . discard args +1220 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1221 # initialize input +1222 # . write(_test-input-stream, "30/imm32") +1223 # . . push args +1224 68/push "30/imm32"/imm32 +1225 68/push _test-input-stream/imm32 +1226 # . . call +1227 e8/call write/disp32 +1228 # . . discard args +1229 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1230 # convert-data(_test-input-stream, _test-output-buffered-file) +1231 # . . push args +1232 68/push _test-output-buffered-file/imm32 +1233 68/push _test-input-stream/imm32 +1234 # . . call +1235 e8/call convert-data/disp32 +1236 # . . discard args +1237 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1238 # check that 4 bytes were written +1239 # . flush(_test-output-buffered-file) 1240 # . . push args -1241 68/push 2/imm32 -1242 51/push-ECX -1243 68/push _test-buffered-file/imm32 -1244 # . . call -1245 e8/call emit/disp32 -1246 # . . discard args -1247 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1248 # flush(_test-buffered-file) -1249 # . . push args -1250 68/push _test-buffered-file/imm32 +1241 68/push _test-output-buffered-file/imm32 +1242 # . . call +1243 e8/call flush/disp32 +1244 # . . discard args +1245 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1246 # . check-stream-equal(_test-output-stream, "30 00 00 00 ", msg) +1247 # . . push args +1248 68/push "F - test-convert-data-handles-imm32"/imm32 +1249 68/push "30 00 00 00 "/imm32 +1250 68/push _test-output-stream/imm32 1251 # . . call -1252 e8/call flush/disp32 +1252 e8/call check-stream-equal/disp32 1253 # . . discard args -1254 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1255 # the '/foo' will have no impact on the output -1256 # check(_test-stream->data == 'fe ff ') -1257 # . check-ints-equal(_test-stream->data[0..3], 'fe f', msg) -1258 # . . push args -1259 68/push "F - test-emit-number-with-metadata/1"/imm32 -1260 68/push 0x66206566/imm32 -1261 # . . push *_test-stream->data -1262 b8/copy-to-EAX _test-stream/imm32 -1263 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) -1264 # . . call -1265 e8/call check-ints-equal/disp32 -1266 # . . discard args -1267 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1268 # . check-ints-equal(_test-stream->data[4..7], 'f ', msg) -1269 # . . push args -1270 68/push "F - test-emit-number-with-metadata/2"/imm32 -1271 68/push 0x2066/imm32 -1272 # . . push *_test-stream->data -1273 b8/copy-to-EAX _test-stream/imm32 -1274 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0x10/disp8 . # push *(EAX+16) -1275 # . . call -1276 e8/call check-ints-equal/disp32 -1277 # . . discard args -1278 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1279 # . epilog -1280 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1281 5d/pop-to-EBP -1282 c3/return -1283 -1284 test-emit-non-number: -1285 # . prolog -1286 55/push-EBP -1287 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1288 # setup -1289 # . clear-stream(_test-stream) -1290 # . . push args -1291 68/push _test-stream/imm32 -1292 # . . call -1293 e8/call clear-stream/disp32 -1294 # . . discard args -1295 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1296 # . clear-stream(_test-buffered-file+4) -1297 # . . push args -1298 b8/copy-to-EAX _test-buffered-file/imm32 -1299 05/add-to-EAX 4/imm32 -1300 50/push-EAX -1301 # . . call -1302 e8/call clear-stream/disp32 -1303 # . . discard args -1304 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1305 # var slice/ECX = "xyz" -1306 68/push _test-slice-non-number-word-end/imm32/end -1307 68/push _test-slice-non-number-word/imm32/start -1308 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1309 # emit(_test-buffered-file, slice, 2) -1310 # . . push args -1311 68/push 2/imm32 -1312 51/push-ECX -1313 68/push _test-buffered-file/imm32 -1314 # . . call -1315 e8/call emit/disp32 -1316 # . . discard args -1317 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1318 # flush(_test-buffered-file) -1319 # . . push args -1320 68/push _test-buffered-file/imm32 -1321 # . . call -1322 e8/call flush/disp32 -1323 # . . discard args -1324 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1325 # check(_test-stream->data == 'xyz') -1326 # . check-ints-equal(_test-stream->data[0..3], 'xyz', msg) -1327 # . . push args -1328 68/push "F - test-emit-non-number"/imm32 -1329 68/push 0x7a7978/imm32 -1330 # . . push *_test-stream->data -1331 b8/copy-to-EAX _test-stream/imm32 -1332 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) -1333 # . . call -1334 e8/call check-ints-equal/disp32 -1335 # . . discard args -1336 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1337 # . epilog -1338 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1339 5d/pop-to-EBP -1340 c3/return -1341 -1342 test-emit-non-number-with-metadata: -1343 # . prolog -1344 55/push-EBP -1345 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1346 # setup -1347 # . clear-stream(_test-stream) -1348 # . . push args -1349 68/push _test-stream/imm32 -1350 # . . call -1351 e8/call clear-stream/disp32 -1352 # . . discard args -1353 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1354 # . clear-stream(_test-buffered-file+4) -1355 # . . push args -1356 b8/copy-to-EAX _test-buffered-file/imm32 -1357 05/add-to-EAX 4/imm32 -1358 50/push-EAX -1359 # . . call -1360 e8/call clear-stream/disp32 -1361 # . . discard args -1362 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1363 # var slice/ECX = "xyz/" -1364 68/push _test-slice-non-number-word-metadata-end/imm32/end -1365 68/push _test-slice-non-number-word/imm32/start -1366 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1367 # emit(_test-buffered-file, slice, 2) +1254 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1255 # . epilog +1256 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1257 5d/pop-to-EBP +1258 c3/return +1259 +1260 test-convert-data-handles-single-byte: +1261 # Any metadata but /imm32 will emit a single byte. +1262 # Data segments can't have /disp32, and SubX doesn't support 16-bit operands. +1263 # . prolog +1264 55/push-EBP +1265 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1266 # setup +1267 # . clear-stream(_test-input-stream) +1268 # . . push args +1269 68/push _test-input-stream/imm32 +1270 # . . call +1271 e8/call clear-stream/disp32 +1272 # . . discard args +1273 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1274 # . clear-stream(_test-output-stream) +1275 # . . push args +1276 68/push _test-output-stream/imm32 +1277 # . . call +1278 e8/call clear-stream/disp32 +1279 # . . discard args +1280 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1281 # . clear-stream(_test-output-buffered-file+4) +1282 # . . push args +1283 b8/copy-to-EAX _test-output-buffered-file/imm32 +1284 05/add-to-EAX 4/imm32 +1285 50/push-EAX +1286 # . . call +1287 e8/call clear-stream/disp32 +1288 # . . discard args +1289 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1290 # initialize input +1291 # . write(_test-input-stream, "30/imm16") +1292 # . . push args +1293 68/push "30/imm16"/imm32 +1294 68/push _test-input-stream/imm32 +1295 # . . call +1296 e8/call write/disp32 +1297 # . . discard args +1298 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1299 # convert-data(_test-input-stream, _test-output-buffered-file) +1300 # . . push args +1301 68/push _test-output-buffered-file/imm32 +1302 68/push _test-input-stream/imm32 +1303 # . . call +1304 e8/call convert-data/disp32 +1305 # . . discard args +1306 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1307 # check that a single byte was written (imm16 is not a valid operand type) +1308 # . flush(_test-output-buffered-file) +1309 # . . push args +1310 68/push _test-output-buffered-file/imm32 +1311 # . . call +1312 e8/call flush/disp32 +1313 # . . discard args +1314 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1315 # . check-stream-equal(_test-output-stream, "30 ", msg) +1316 # . . push args +1317 68/push "F - test-convert-data-handles-single-byte"/imm32 +1318 68/push "30 "/imm32 +1319 68/push _test-output-stream/imm32 +1320 # . . call +1321 e8/call check-stream-equal/disp32 +1322 # . . discard args +1323 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1324 # . epilog +1325 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1326 5d/pop-to-EBP +1327 c3/return +1328 +1329 test-convert-data-multiple-bytes: +1330 # Multiple single-byte words in input stream get processed one by one. +1331 # . prolog +1332 55/push-EBP +1333 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1334 # setup +1335 # . clear-stream(_test-input-stream) +1336 # . . push args +1337 68/push _test-input-stream/imm32 +1338 # . . call +1339 e8/call clear-stream/disp32 +1340 # . . discard args +1341 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1342 # . clear-stream(_test-output-stream) +1343 # . . push args +1344 68/push _test-output-stream/imm32 +1345 # . . call +1346 e8/call clear-stream/disp32 +1347 # . . discard args +1348 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1349 # . clear-stream(_test-output-buffered-file+4) +1350 # . . push args +1351 b8/copy-to-EAX _test-output-buffered-file/imm32 +1352 05/add-to-EAX 4/imm32 +1353 50/push-EAX +1354 # . . call +1355 e8/call clear-stream/disp32 +1356 # . . discard args +1357 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1358 # initialize input +1359 # . write(_test-input-stream, "1 2") +1360 # . . push args +1361 68/push "1 2"/imm32 +1362 68/push _test-input-stream/imm32 +1363 # . . call +1364 e8/call write/disp32 +1365 # . . discard args +1366 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1367 # convert-data(_test-input-stream, _test-output-buffered-file) 1368 # . . push args -1369 68/push 2/imm32 -1370 51/push-ECX -1371 68/push _test-buffered-file/imm32 -1372 # . . call -1373 e8/call emit/disp32 -1374 # . . discard args -1375 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1376 # flush(_test-buffered-file) +1369 68/push _test-output-buffered-file/imm32 +1370 68/push _test-input-stream/imm32 +1371 # . . call +1372 e8/call convert-data/disp32 +1373 # . . discard args +1374 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1375 # check output +1376 # . flush(_test-output-buffered-file) 1377 # . . push args -1378 68/push _test-buffered-file/imm32 +1378 68/push _test-output-buffered-file/imm32 1379 # . . call 1380 e8/call flush/disp32 1381 # . . discard args 1382 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1383 # check(_test-stream->data == 'xyz/') -1384 # . check-ints-equal(_test-stream->data[0..3], 'xyz/', msg) -1385 # . . push args -1386 68/push "F - test-emit-non-number-with-metadata"/imm32 -1387 68/push 0x2f7a7978/imm32 -1388 # . . push *_test-stream->data -1389 b8/copy-to-EAX _test-stream/imm32 -1390 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) -1391 # . . call -1392 e8/call check-ints-equal/disp32 -1393 # . . discard args -1394 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1395 # . epilog -1396 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1397 5d/pop-to-EBP -1398 c3/return -1399 -1400 # print 'n' in hex in 'width' bytes in lower-endian order, with a space after every byte -1401 emit-hex: # out : (address buffered-file), n : int, width : int -1402 # . prolog -1403 55/push-EBP -1404 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1405 # . save registers -1406 50/push-EAX -1407 51/push-ECX -1408 52/push-EDX -1409 53/push-EBX -1410 57/push-EDI -1411 # EDI = out -1412 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI -1413 # EBX = n -1414 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX -1415 # EDX = width -1416 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 2/r32/EDX 0x10/disp8 . # copy *(EBP+16) to EDX -1417 # var curr/ECX = 0 -1418 31/xor 3/mod/direct 1/rm32/ECX . . . 1/r32/ECX . . # clear ECX -1419 $emit-hex:loop: -1420 # if (curr >= width) break -1421 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX and EDX -1422 7d/jump-if-greater-or-equal $emit-hex:end/disp8 -1423 # print-byte(out, EBX) -1424 # . . push args -1425 53/push-EBX -1426 57/push-EDI -1427 # . . call -1428 e8/call print-byte/disp32 -1429 # . . discard args -1430 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1431 # write-byte(out, ' ') -1432 # . . push args -1433 68/push 0x20/imm32/space -1434 57/push-EDI -1435 # . . call -1436 e8/call write-byte/disp32 -1437 # . . discard args -1438 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1439 # EBX = EBX >> 8 -1440 c1/shift 5/subop/logic-right 3/mod/direct 3/rm32/EBX . . . . . 8/imm8 # shift EBX right by 8 bits, while padding zeroes -1441 # ++curr -1442 41/increment-ECX -1443 eb/jump $emit-hex:loop/disp8 -1444 $emit-hex:end: -1445 # . restore registers -1446 5f/pop-to-EDI -1447 5b/pop-to-EBX -1448 5a/pop-to-EAX -1449 59/pop-to-ECX -1450 58/pop-to-EAX -1451 # . epilog -1452 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1453 5d/pop-to-EBP -1454 c3/return -1455 -1456 test-emit-hex-single-byte: -1457 # setup -1458 # . clear-stream(_test-stream) -1459 # . . push args -1460 68/push _test-stream/imm32 -1461 # . . call -1462 e8/call clear-stream/disp32 -1463 # . . discard args -1464 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1465 # . clear-stream(_test-buffered-file+4) -1466 # . . push args -1467 b8/copy-to-EAX _test-buffered-file/imm32 -1468 05/add-to-EAX 4/imm32 -1469 50/push-EAX -1470 # . . call -1471 e8/call clear-stream/disp32 -1472 # . . discard args -1473 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1474 # emit-hex(_test-buffered-file, 0xab, 1) -1475 # . . push args -1476 68/push 1/imm32 -1477 68/push 0xab/imm32 -1478 68/push _test-buffered-file/imm32 -1479 # . . call -1480 e8/call emit-hex/disp32 -1481 # . . discard args -1482 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1483 # flush(_test-buffered-file) -1484 # . . push args -1485 68/push _test-buffered-file/imm32 -1486 # . . call -1487 e8/call flush/disp32 -1488 # . . discard args -1489 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1490 # check-ints-equal(*_test-stream->data, 'ab ', msg) -1491 # . . push args -1492 68/push "F - test-emit-hex-single-byte"/imm32 -1493 68/push 0x206261/imm32 -1494 # . . push *_test-stream->data -1495 b8/copy-to-EAX _test-stream/imm32 -1496 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) -1497 # . . call -1498 e8/call check-ints-equal/disp32 -1499 # . . discard args -1500 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1501 # . end -1502 c3/return -1503 -1504 test-emit-hex-multiple-byte: -1505 # setup -1506 # . clear-stream(_test-stream) -1507 # . . push args -1508 68/push _test-stream/imm32 -1509 # . . call -1510 e8/call clear-stream/disp32 -1511 # . . discard args -1512 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1513 # . clear-stream(_test-buffered-file+4) -1514 # . . push args -1515 b8/copy-to-EAX _test-buffered-file/imm32 -1516 05/add-to-EAX 4/imm32 -1517 50/push-EAX -1518 # . . call -1519 e8/call clear-stream/disp32 -1520 # . . discard args -1521 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1522 # emit-hex(_test-buffered-file, 0x1234, 2) -1523 # . . push args -1524 68/push 2/imm32 -1525 68/push 0x1234/imm32 -1526 68/push _test-buffered-file/imm32 -1527 # . . call -1528 e8/call emit-hex/disp32 -1529 # . . discard args -1530 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1531 # flush(_test-buffered-file) -1532 # . . push args -1533 68/push _test-buffered-file/imm32 -1534 # . . call -1535 e8/call flush/disp32 -1536 # . . discard args -1537 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1538 # check(_test-stream->data == '34 12 ') -1539 # . check-ints-equal(_test-stream->data[0..3], '34 1', msg) -1540 # . . push args -1541 68/push "F - test-emit-hex-multiple-byte/1"/imm32 -1542 68/push 0x31203433/imm32 -1543 # . . push *_test-stream->data -1544 b8/copy-to-EAX _test-stream/imm32 -1545 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) -1546 # . . call -1547 e8/call check-ints-equal/disp32 -1548 # . . discard args -1549 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1550 # . check-ints-equal(_test-stream->data[4..7], '2 ', msg) -1551 # . . push args -1552 68/push "F - test-emit-hex-multiple-byte/2"/imm32 -1553 68/push 0x2032/imm32 -1554 # . . push *_test-stream->data -1555 b8/copy-to-EAX _test-stream/imm32 -1556 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0x10/disp8 . # push *(EAX+16) -1557 # . . call -1558 e8/call check-ints-equal/disp32 -1559 # . . discard args -1560 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1561 # . end -1562 c3/return -1563 -1564 test-emit-hex-zero-pad: -1565 # setup -1566 # . clear-stream(_test-stream) -1567 # . . push args -1568 68/push _test-stream/imm32 -1569 # . . call -1570 e8/call clear-stream/disp32 -1571 # . . discard args -1572 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1573 # . clear-stream(_test-buffered-file+4) -1574 # . . push args -1575 b8/copy-to-EAX _test-buffered-file/imm32 -1576 05/add-to-EAX 4/imm32 -1577 50/push-EAX -1578 # . . call -1579 e8/call clear-stream/disp32 -1580 # . . discard args -1581 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1582 # emit-hex(_test-buffered-file, 0xab, 2) -1583 # . . push args -1584 68/push 2/imm32 -1585 68/push 0xab/imm32 -1586 68/push _test-buffered-file/imm32 -1587 # . . call -1588 e8/call emit-hex/disp32 -1589 # . . discard args -1590 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1591 # flush(_test-buffered-file) -1592 # . . push args -1593 68/push _test-buffered-file/imm32 -1594 # . . call -1595 e8/call flush/disp32 -1596 # . . discard args -1597 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1598 # check(_test-stream->data == '00 ab') -1599 # . check-ints-equal(*_test-stream->data, 'ab 0', msg) -1600 # . . push args -1601 68/push "F - test-emit-hex-zero-pad/1"/imm32 -1602 68/push 0x30206261/imm32 -1603 # . . push *_test-stream->data -1604 b8/copy-to-EAX _test-stream/imm32 -1605 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) -1606 # . . call -1607 e8/call check-ints-equal/disp32 -1608 # . . discard args -1609 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1610 # . check-ints-equal(*_test-stream->data[1], '0 ', msg) -1611 # . . push args -1612 68/push "F - test-emit-hex-zero-pad/2"/imm32 -1613 68/push 0x2030/imm32 -1614 # . . push *_test-stream->data -1615 b8/copy-to-EAX _test-stream/imm32 -1616 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0x10/disp8 . # push *(EAX+16) -1617 # . . call -1618 e8/call check-ints-equal/disp32 -1619 # . . discard args -1620 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1621 # . end -1622 c3/return -1623 -1624 test-emit-hex-negative: -1625 # setup -1626 # . clear-stream(_test-stream) -1627 # . . push args -1628 68/push _test-stream/imm32 -1629 # . . call -1630 e8/call clear-stream/disp32 -1631 # . . discard args -1632 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1633 # . clear-stream(_test-buffered-file+4) -1634 # . . push args -1635 b8/copy-to-EAX _test-buffered-file/imm32 -1636 05/add-to-EAX 4/imm32 -1637 50/push-EAX -1638 # . . call -1639 e8/call clear-stream/disp32 -1640 # . . discard args -1641 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1642 # emit-hex(_test-buffered-file, -1, 2) -1643 # . . push args -1644 68/push 2/imm32 -1645 68/push -1/imm32 -1646 68/push _test-buffered-file/imm32 -1647 # . . call -1648 e8/call emit-hex/disp32 -1649 # . . discard args -1650 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1651 # flush(_test-buffered-file) -1652 # . . push args -1653 68/push _test-buffered-file/imm32 -1654 # . . call -1655 e8/call flush/disp32 -1656 # . . discard args -1657 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1658 # check(_test-stream->data == 'ff ff ') -1659 # . check-ints-equal(_test-stream->data[0..3], 'ff f', msg) -1660 # . . push args -1661 68/push "F - test-emit-hex-negative/1"/imm32 -1662 68/push 0x66206666/imm32 -1663 # . . push *_test-stream->data -1664 b8/copy-to-EAX _test-stream/imm32 -1665 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) -1666 # . . call -1667 e8/call check-ints-equal/disp32 -1668 # . . discard args -1669 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1670 # . check-ints-equal(_test-stream->data[4..7], 'f ', msg) -1671 # . . push args -1672 68/push "F - test-emit-hex-negative/2"/imm32 -1673 68/push 0x2066/imm32 -1674 # . . push *_test-stream->data -1675 b8/copy-to-EAX _test-stream/imm32 -1676 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0x10/disp8 . # push *(EAX+16) -1677 # . . call -1678 e8/call check-ints-equal/disp32 -1679 # . . discard args -1680 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1681 # . end -1682 c3/return -1683 -1684 == data -1685 -1686 _test-slice-negative-two: -1687 2d/- 32/2 -1688 _test-slice-negative-two-end: -1689 2f/slash 66/f 6f/o 6f/o -1690 _test-slice-negative-two-metadata-end: -1691 -1692 _test-slice-non-number-word: -1693 78/x 79/y 7a/z -1694 _test-slice-non-number-word-end: -1695 2f/slash -1696 _test-slice-non-number-word-metadata-end: -1697 -1698 # . . vim:nowrap:textwidth=0 +1383 # . check-stream-equal(_test-output-stream, "01 02 ", msg) +1384 # . . push args +1385 68/push "F - test-convert-data-multiple-bytes"/imm32 +1386 68/push "01 02 "/imm32 +1387 68/push _test-output-stream/imm32 +1388 # . . call +1389 e8/call check-stream-equal/disp32 +1390 # . . discard args +1391 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1392 # . epilog +1393 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1394 5d/pop-to-EBP +1395 c3/return +1396 +1397 test-convert-data-byte-then-name: +1398 # Single-byte word followed by valid name get processed one by one. +1399 # . prolog +1400 55/push-EBP +1401 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1402 # setup +1403 # . clear-stream(_test-input-stream) +1404 # . . push args +1405 68/push _test-input-stream/imm32 +1406 # . . call +1407 e8/call clear-stream/disp32 +1408 # . . discard args +1409 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1410 # . clear-stream(_test-output-stream) +1411 # . . push args +1412 68/push _test-output-stream/imm32 +1413 # . . call +1414 e8/call clear-stream/disp32 +1415 # . . discard args +1416 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1417 # . clear-stream(_test-output-buffered-file+4) +1418 # . . push args +1419 b8/copy-to-EAX _test-output-buffered-file/imm32 +1420 05/add-to-EAX 4/imm32 +1421 50/push-EAX +1422 # . . call +1423 e8/call clear-stream/disp32 +1424 # . . discard args +1425 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1426 # initialize input +1427 # . write(_test-input-stream, "30 abcd/o") +1428 # . . push args +1429 68/push "30 abcd/o"/imm32 +1430 68/push _test-input-stream/imm32 +1431 # . . call +1432 e8/call write/disp32 +1433 # . . discard args +1434 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1435 # convert-data(_test-input-stream, _test-output-buffered-file) +1436 # . . push args +1437 68/push _test-output-buffered-file/imm32 +1438 68/push _test-input-stream/imm32 +1439 # . . call +1440 e8/call convert-data/disp32 +1441 # . . discard args +1442 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1443 # check output +1444 # . flush(_test-output-buffered-file) +1445 # . . push args +1446 68/push _test-output-buffered-file/imm32 +1447 # . . call +1448 e8/call flush/disp32 +1449 # . . discard args +1450 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1451 # . check-stream-equal(_test-output-stream, "30 abcd/o ", msg) +1452 # . . push args +1453 68/push "F - test-convert-data-byte-then-name"/imm32 +1454 68/push "30 abcd/o "/imm32 +1455 68/push _test-output-stream/imm32 +1456 # . . call +1457 e8/call check-stream-equal/disp32 +1458 # . . discard args +1459 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1460 # . epilog +1461 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1462 5d/pop-to-EBP +1463 c3/return +1464 +1465 test-convert-data-multiple-words: +1466 # Multiple words in input stream get processed one by one. +1467 # . prolog +1468 55/push-EBP +1469 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1470 # setup +1471 # . clear-stream(_test-input-stream) +1472 # . . push args +1473 68/push _test-input-stream/imm32 +1474 # . . call +1475 e8/call clear-stream/disp32 +1476 # . . discard args +1477 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1478 # . clear-stream(_test-output-stream) +1479 # . . push args +1480 68/push _test-output-stream/imm32 +1481 # . . call +1482 e8/call clear-stream/disp32 +1483 # . . discard args +1484 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1485 # . clear-stream(_test-output-buffered-file+4) +1486 # . . push args +1487 b8/copy-to-EAX _test-output-buffered-file/imm32 +1488 05/add-to-EAX 4/imm32 +1489 50/push-EAX +1490 # . . call +1491 e8/call clear-stream/disp32 +1492 # . . discard args +1493 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1494 # initialize input +1495 # . write(_test-input-stream, "30 abcd/o 42e1/imm32") +1496 # . . push args +1497 68/push "30 abcd/o 42e1/imm32"/imm32 +1498 68/push _test-input-stream/imm32 +1499 # . . call +1500 e8/call write/disp32 +1501 # . . discard args +1502 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1503 # convert-data(_test-input-stream, _test-output-buffered-file) +1504 # . . push args +1505 68/push _test-output-buffered-file/imm32 +1506 68/push _test-input-stream/imm32 +1507 # . . call +1508 e8/call convert-data/disp32 +1509 # . . discard args +1510 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1511 # check output +1512 # . flush(_test-output-buffered-file) +1513 # . . push args +1514 68/push _test-output-buffered-file/imm32 +1515 # . . call +1516 e8/call flush/disp32 +1517 # . . discard args +1518 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1519 +-- 34 lines: # dump output ---------------------------------------------------------------------------------------------------------------------------------- +1553 # . check-stream-equal(_test-output-stream, "30 abcd/o 42 e1 00 00 ", msg) +1554 # . . push args +1555 68/push "F - test-convert-data-multiple-words"/imm32 +1556 68/push "30 abcd/o e1 42 00 00 "/imm32 +1557 68/push _test-output-stream/imm32 +1558 # . . call +1559 e8/call check-stream-equal/disp32 +1560 # . . discard args +1561 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1562 # . epilog +1563 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1564 5d/pop-to-EBP +1565 c3/return +1566 +1567 # simplifications since we perform zero error handling (continuing to rely on the C++ version for that): +1568 # missing fields are always 0-filled +1569 # bytes never mentioned are silently dropped; if you don't provide /mod, /rm32 or /r32 you don't get a 0 modrm byte. You get *no* modrm byte. +1570 # in case of conflict, last operand with a name is recognized +1571 # silently drop extraneous operands +1572 # unceremoniously abort on non-numeric operands except disp or imm +1573 # opcodes must be lowercase and zero padded +1574 +1575 # todo: end each line with original unprocessed line in a comment +1576 +1577 # pack an instruction, following the C++ version: +1578 convert-instruction: # line : (address stream byte), out : (address buffered-file) -> <void> +1579 # pseudocode: +1580 # var word-slice = next-word(line) +1581 # if slice-empty?(word-slice) +1582 # write-stream-buffered(out, line) +1583 # return +1584 # if slice-starts-with?(word-slice, "#") +1585 # write-stream-buffered(out, line) +1586 # return +1587 # if slice-ends-with?(word-slice, ":") +1588 # write-stream-buffered(out, line) +1589 # return +1590 # # convert opcodes +1591 # var op1 = word-slice +1592 # write-slice(out, op1) +1593 # if slice-equal?(op1, "0f") or slice-equal?(op1, "f2") or slice-equal?(op1, "f3") +1594 # var op2 = next-word(line) +1595 # if slice-empty?(op2) +1596 # return +1597 # if slice-starts-with?(op2, "#") +1598 # return +1599 # write-slice(out, op2) +1600 # if slice-equal?(op1, "f2") or slice-equal?(op1, "f3") +1601 # if slice-equal?(op2, "0f") +1602 # var op3 = next-word(line) +1603 # if slice-empty?(op3) +1604 # return +1605 # if slice-starts-with?(op2, "#") +1606 # return +1607 # write-slice(out, op3) +1608 # # pack modrm and sib +1609 # var has-modrm? = false, mod = 0, rm32 = 0, r32 = 0 +1610 # var has-sib? = false, base = 0, index = 4 (none), scale = 0 +1611 # while true +1612 # word-slice = next-word(line) +1613 # if (empty(word-slice)) break +1614 # if (slice-starts-with?(word-slice, "#")) break +1615 # if (has-metadata?(word-slice, "mod")) +1616 # var mod = parse-hex-int(next-token-from-slice(word-slice, "/")) +1617 # has-modrm? = true +1618 # else if (has-metadata?(word-slice, "rm32")) +1619 # var rm32 = parse-hex-int(next-token-from-slice(word-slice, "/")) +1620 # has-modrm? = true +1621 # else if (has-metadata?(word-slice, "r32") or has-metadata?(word-slice, "subop")) +1622 # var r32 = parse-hex-int(next-token-from-slice(word-slice, "/")) +1623 # has-modrm? = true +1624 # else if (has-metadata?(word-slice, "base") +1625 # var base = parse-hex-int(next-token-from-slice(word-slice, "/")) +1626 # has-sib? = true +1627 # else if (has-metadata?(word-slice, "index") +1628 # var index = parse-hex-int(next-token-from-slice(word-slice, "/")) +1629 # has-sib? = true +1630 # else if (has-metadata?(word-slice, "scale") +1631 # var scale = parse-hex-int(next-token-from-slice(word-slice, "/")) +1632 # has-sib? = true +1633 # if has-modrm? +1634 # var modrm = mod & 0b11 +1635 # modrm <<= 2 +1636 # modrm |= r32 & 0b111 +1637 # modrm <<= 3 +1638 # modrm |= rm32 & 0b111 +1639 # emit-hex(out, modrm, 1) +1640 # if has-sib? +1641 # var sib = scale & 0b11 +1642 # sib <<= 2 +1643 # sib |= index & 0b111 +1644 # sib <<= 3 +1645 # sib |= base & 0b111 +1646 # emit-hex(out, sib, 1) +1647 # # emit disp bytes +1648 # rewind-stream(line) +1649 # while true +1650 # word-slice = next-word(line) +1651 # if (empty(word-slice)) break +1652 # if (slice-starts-with?(word-slice, "#")) break +1653 # if has-metadata?(word-slice, "disp8") +1654 # var disp = parse-hex-int(next-token-from-slice(word-slice, "/")) +1655 # emit-hex(out, disp, 1) +1656 # break +1657 # else if has-metadata?(word-slice, "disp16") +1658 # var disp = parse-hex-int(next-token-from-slice(word-slice, "/")) +1659 # emit-hex(out, disp, 2) +1660 # break +1661 # else if has-metadata?(word-slice, "disp32") +1662 # var disp = parse-hex-int(next-token-from-slice(word-slice, "/")) +1663 # emit-hex(out, disp, 4) +1664 # break +1665 # # emit imm bytes +1666 # rewind-stream(line) +1667 # while true +1668 # word-slice = next-word(line) +1669 # if (slice-starts-with?(word-slice, "#")) break +1670 # if (empty(word-slice)) break +1671 # if has-metadata?(word-slice, "imm8") +1672 # var imm = parse-hex-int(next-token-from-slice(word-slice, "/")) +1673 # emit-hex(out, imm, 1) +1674 # break +1675 # if has-metadata?(word-slice, "imm16") +1676 # var imm = parse-hex-int(next-token-from-slice(word-slice, "/")) +1677 # emit-hex(out, imm, 2) +1678 # break +1679 # else if has-metadata?(word-slice, "imm32") +1680 # var imm = parse-hex-int(next-token-from-slice(word-slice, "/")) +1681 # emit-hex(out, imm, 4) +1682 # break +1683 # +1684 # Exit blocks: +1685 # pass-through: +1686 # write-stream-buffered(out, line) +1687 # return +1688 # +1689 # . prolog +1690 55/push-EBP +1691 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1692 # . save registers +1693 51/push-ECX +1694 # var word-slice/ECX = {0, 0} +1695 68/push 0/imm32/end +1696 68/push 0/imm32/start +1697 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1698 # next-word(line, word-slice) +1699 # . . push args +1700 51/push-ECX +1701 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1702 # . . call +1703 e8/call next-word/disp32 +1704 # . . discard args +1705 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1706 $convert-instruction:pass-line-through: +1707 # write-stream-buffered(out, line) +1708 # . . push args +1709 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1710 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +1711 # . . call +1712 e8/call write-stream-buffered/disp32 +1713 # . . discard args +1714 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1715 $convert-instruction:end: +1716 # . reclaim locals +1717 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1718 # . restore registers +1719 59/pop-to-ECX +1720 # . epilog +1721 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1722 5d/pop-to-EBP +1723 c3/return +1724 +1725 test-convert-instruction-passes-comments-through: +1726 # if a line starts with '#', pass it along unchanged +1727 # . prolog +1728 55/push-EBP +1729 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1730 # setup +1731 # . clear-stream(_test-input-stream) +1732 # . . push args +1733 68/push _test-input-stream/imm32 +1734 # . . call +1735 e8/call clear-stream/disp32 +1736 # . . discard args +1737 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1738 # . clear-stream(_test-output-stream) +1739 # . . push args +1740 68/push _test-output-stream/imm32 +1741 # . . call +1742 e8/call clear-stream/disp32 +1743 # . . discard args +1744 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1745 # . clear-stream(_test-output-buffered-file+4) +1746 # . . push args +1747 b8/copy-to-EAX _test-buffered-file/imm32 +1748 05/add-to-EAX 4/imm32 +1749 50/push-EAX +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 # initialize input +1755 # . write(_test-input-stream, "# abcd") +1756 # . . push args +1757 68/push "# abcd"/imm32 +1758 68/push _test-input-stream/imm32 +1759 # . . call +1760 e8/call write/disp32 +1761 # . . discard args +1762 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1763 # convert-instruction(_test-input-stream, _test-output-buffered-file) +1764 # . . push args +1765 68/push _test-output-buffered-file/imm32 +1766 68/push _test-input-stream/imm32 +1767 # . . call +1768 e8/call convert-instruction/disp32 +1769 # . . discard args +1770 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1771 # check that the line just passed through +1772 # . flush(_test-output-buffered-file) +1773 # . . push args +1774 68/push _test-output-buffered-file/imm32 +1775 # . . call +1776 e8/call flush/disp32 +1777 # . . discard args +1778 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1779 # . check-stream-equal(_test-output-stream, "# abcd", msg) +1780 # . . push args +1781 68/push "F - test-convert-instruction-passes-comments-through"/imm32 +1782 68/push "# abcd"/imm32 +1783 68/push _test-output-stream/imm32 +1784 # . . call +1785 e8/call check-stream-equal/disp32 +1786 # . . discard args +1787 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1788 # . epilog +1789 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1790 5d/pop-to-EBP +1791 c3/return +1792 +1793 test-convert-instruction-passes-labels-through: +1794 # if the first word ends with ':', pass along the entire line unchanged +1795 # . prolog +1796 55/push-EBP +1797 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1798 # setup +1799 # . clear-stream(_test-input-stream) +1800 # . . push args +1801 68/push _test-input-stream/imm32 +1802 # . . call +1803 e8/call clear-stream/disp32 +1804 # . . discard args +1805 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1806 # . clear-stream(_test-output-stream) +1807 # . . push args +1808 68/push _test-output-stream/imm32 +1809 # . . call +1810 e8/call clear-stream/disp32 +1811 # . . discard args +1812 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1813 # . clear-stream(_test-output-buffered-file+4) +1814 # . . push args +1815 b8/copy-to-EAX _test-output-buffered-file/imm32 +1816 05/add-to-EAX 4/imm32 +1817 50/push-EAX +1818 # . . call +1819 e8/call clear-stream/disp32 +1820 # . . discard args +1821 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1822 # initialize input +1823 # . write(_test-input-stream, "ab: # cd") +1824 # . . push args +1825 68/push "ab: # cd"/imm32 +1826 68/push _test-input-stream/imm32 +1827 # . . call +1828 e8/call write/disp32 +1829 # . . discard args +1830 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1831 # convert-instruction(_test-input-stream, _test-output-buffered-file) +1832 # . . push args +1833 68/push _test-output-buffered-file/imm32 +1834 68/push _test-input-stream/imm32 +1835 # . . call +1836 e8/call convert-instruction/disp32 +1837 # . . discard args +1838 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1839 # check that the line just passed through +1840 # . flush(_test-output-buffered-file) +1841 # . . push args +1842 68/push _test-output-buffered-file/imm32 +1843 # . . call +1844 e8/call flush/disp32 +1845 # . . discard args +1846 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1847 # . check-stream-equal(_test-output-stream, "ab: # cd", msg) +1848 # . . push args +1849 68/push "F - test-convert-instruction-passes-labels-through"/imm32 +1850 68/push "ab: # cd"/imm32 +1851 68/push _test-output-stream/imm32 +1852 # . . call +1853 e8/call check-stream-equal/disp32 +1854 # . . discard args +1855 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1856 # . epilog +1857 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1858 5d/pop-to-EBP +1859 c3/return +1860 +1861 # (re)compute the bounds of the next word in the line +1862 # return empty string on reaching end of file +1863 next-word: # line : (address stream byte), out : (address slice) +1864 # . prolog +1865 55/push-EBP +1866 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1867 # . save registers +1868 50/push-EAX +1869 51/push-ECX +1870 56/push-ESI +1871 57/push-EDI +1872 # ESI = line +1873 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +1874 # EDI = out +1875 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI +1876 # skip-chars-matching(line, ' ') +1877 # . . push args +1878 68/push 0x20/imm32/space +1879 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1880 # . . call +1881 e8/call skip-chars-matching/disp32 +1882 # . . discard args +1883 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1884 $next-word:check0: +1885 # if (line->read >= line->write) clear out and return +1886 # . EAX = line->read +1887 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy *(ESI+4) to EAX +1888 # . if (EAX < line->write) goto next check +1889 3b/compare 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # compare EAX with *ESI +1890 7c/jump-if-lesser $next-word:check1/disp8 +1891 # . return out = {0, 0} +1892 c7 0/subop/copy 0/mod/direct 7/rm32/EDI . . . . . 0/imm32 # copy to *EDI +1893 c7 0/subop/copy 1/mod/*+disp8 7/rm32/EDI . . . . 4/disp8 0/imm32 # copy to *(EDI+4) +1894 eb/jump $next-word:end/disp8 +1895 $next-word:check1: +1896 # out->start = &line->data[line->read] +1897 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX +1898 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 +1899 89/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to *EDI +1900 # if (line->data[line->read] == '#') out->end = &line->data[line->write]), skip rest of stream and return +1901 # . EAX = line->data[line->read] +1902 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +1903 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 +1904 # . compare +1905 3d/compare-EAX-with 0x23/imm32/pound +1906 75/jump-if-not-equal $next-word:not-comment/disp8 +1907 # . out->end = &line->data[line->write] +1908 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX +1909 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 +1910 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDI+4) +1911 # . line->read = line->write +1912 89/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(ESI+4) +1913 # . return +1914 eb/jump $next-word:end/disp8 +1915 $next-word:not-comment: +1916 # otherwise skip-chars-not-matching-whitespace(line) +1917 # . . push args +1918 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1919 # . . call +1920 e8/call skip-chars-not-matching-whitespace/disp32 +1921 # . . discard args +1922 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1923 # out->end = &line->data[line->read] +1924 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX +1925 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 +1926 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDI+4) +1927 $next-word:end: +1928 # . restore registers +1929 5f/pop-to-EDI +1930 5e/pop-to-ESI +1931 59/pop-to-ECX +1932 58/pop-to-EAX +1933 # . epilog +1934 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1935 5d/pop-to-EBP +1936 c3/return +1937 +1938 test-next-word: +1939 # . prolog +1940 55/push-EBP +1941 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1942 # setup +1943 # . clear-stream(_test-stream) +1944 # . . push args +1945 68/push _test-stream/imm32 +1946 # . . call +1947 e8/call clear-stream/disp32 +1948 # . . discard args +1949 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1950 # var slice/ECX = {0, 0} +1951 68/push 0/imm32/end +1952 68/push 0/imm32/start +1953 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1954 # write(_test-stream, " ab") +1955 # . . push args +1956 68/push " ab"/imm32 +1957 68/push _test-stream/imm32 +1958 # . . call +1959 e8/call write/disp32 +1960 # . . discard args +1961 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1962 # next-word(_test-stream, slice) +1963 # . . push args +1964 51/push-ECX +1965 68/push _test-stream/imm32 +1966 # . . call +1967 e8/call next-word/disp32 +1968 # . . discard args +1969 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1970 # check-ints-equal(slice->start - _test-stream->data, 2, msg) +1971 # . check-ints-equal(slice->start - _test-stream, 14, msg) +1972 # . . push args +1973 68/push "F - test-next-word: start"/imm32 +1974 68/push 0xe/imm32 +1975 # . . push slice->start - _test-stream +1976 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX +1977 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-stream/imm32 # subtract from EAX +1978 50/push-EAX +1979 # . . call +1980 e8/call check-ints-equal/disp32 +1981 # . . discard args +1982 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1983 # check-ints-equal(slice->end - _test-stream->data, 4, msg) +1984 # . check-ints-equal(slice->end - _test-stream, 16, msg) +1985 # . . push args +1986 68/push "F - test-next-word: end"/imm32 +1987 68/push 0x10/imm32 +1988 # . . push slice->end - _test-stream +1989 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +1990 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-stream/imm32 # subtract from EAX +1991 50/push-EAX +1992 # . . call +1993 e8/call check-ints-equal/disp32 +1994 # . . discard args +1995 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1996 # . epilog +1997 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1998 5d/pop-to-EBP +1999 c3/return +2000 +2001 test-next-word-returns-whole-comment: +2002 # . prolog +2003 55/push-EBP +2004 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2005 # setup +2006 # . clear-stream(_test-stream) +2007 # . . push args +2008 68/push _test-stream/imm32 +2009 # . . call +2010 e8/call clear-stream/disp32 +2011 # . . discard args +2012 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2013 # var slice/ECX = {0, 0} +2014 68/push 0/imm32/end +2015 68/push 0/imm32/start +2016 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2017 # write(_test-stream, " # a") +2018 # . . push args +2019 68/push " # a"/imm32 +2020 68/push _test-stream/imm32 +2021 # . . call +2022 e8/call write/disp32 +2023 # . . discard args +2024 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2025 # next-word(_test-stream, slice) +2026 # . . push args +2027 51/push-ECX +2028 68/push _test-stream/imm32 +2029 # . . call +2030 e8/call next-word/disp32 +2031 # . . discard args +2032 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2033 # check-ints-equal(slice->start - _test-stream->data, 2, msg) +2034 # . check-ints-equal(slice->start - _test-stream, 14, msg) +2035 # . . push args +2036 68/push "F - test-next-word-returns-whole-comment: start"/imm32 +2037 68/push 0xe/imm32 +2038 # . . push slice->start - _test-stream +2039 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX +2040 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-stream/imm32 # subtract from EAX +2041 50/push-EAX +2042 # . . call +2043 e8/call check-ints-equal/disp32 +2044 # . . discard args +2045 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2046 # check-ints-equal(slice->end - _test-stream->data, 5, msg) +2047 # . check-ints-equal(slice->end - _test-stream, 17, msg) +2048 # . . push args +2049 68/push "F - test-next-word-returns-whole-comment: end"/imm32 +2050 68/push 0x11/imm32 +2051 # . . push slice->end - _test-stream +2052 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +2053 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-stream/imm32 # subtract from EAX +2054 50/push-EAX +2055 # . . call +2056 e8/call check-ints-equal/disp32 +2057 # . . discard args +2058 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2059 # . epilog +2060 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2061 5d/pop-to-EBP +2062 c3/return +2063 +2064 test-next-word-returns-empty-string-on-eof: +2065 # . prolog +2066 55/push-EBP +2067 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2068 # setup +2069 # . clear-stream(_test-stream) +2070 # . . push args +2071 68/push _test-stream/imm32 +2072 # . . call +2073 e8/call clear-stream/disp32 +2074 # . . discard args +2075 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2076 # var slice/ECX = {0, 0} +2077 68/push 0/imm32/end +2078 68/push 0/imm32/start +2079 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2080 # write nothing to _test-stream +2081 # next-word(_test-stream, slice) +2082 # . . push args +2083 51/push-ECX +2084 68/push _test-stream/imm32 +2085 # . . call +2086 e8/call next-word/disp32 +2087 # . . discard args +2088 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2089 # check-ints-equal(slice->end - slice->start, 0, msg) +2090 # . . push args +2091 68/push "F - test-next-word-returns-empty-string-on-eof"/imm32 +2092 68/push 0/imm32 +2093 # . . push slice->end - slice->start +2094 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +2095 2b/subtract 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # subtract *ECX from EAX +2096 50/push-EAX +2097 # . . call +2098 e8/call check-ints-equal/disp32 +2099 # . . discard args +2100 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2101 # . epilog +2102 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2103 5d/pop-to-EBP +2104 c3/return +2105 +2106 has-metadata?: # word : (address slice), s : (address string) -> EAX : boolean +2107 # pseudocode: +2108 # var twig : &slice = next-token-from-slice(word->start, word->end, '/') # skip name +2109 # curr = twig->end +2110 # while true +2111 # twig = next-token-from-slice(curr, word->end, '/') +2112 # if (twig.empty()) break +2113 # if (slice-equal?(twig, s)) return true +2114 # curr = twig->end +2115 # return false +2116 # . prolog +2117 55/push-EBP +2118 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2119 # . save registers +2120 51/push-ECX +2121 52/push-EDX +2122 56/push-ESI +2123 57/push-EDI +2124 # ESI = word +2125 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +2126 # EDX = word->end +2127 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 2/r32/EDX 4/disp8 . # copy *(ESI+4) to EDX +2128 # var twig/EDI : (address slice) = {0, 0} +2129 68/push 0/imm32/end +2130 68/push 0/imm32/start +2131 89/copy 3/mod/direct 7/rm32/EDI . . . 4/r32/ESP . . # copy ESP to EDI +2132 # next-token-from-slice(word->start, word->end, '/', twig) +2133 # . . push args +2134 57/push-EDI +2135 68/push 0x2f/imm32/slash +2136 52/push-EDX +2137 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI +2138 # . . call +2139 e8/call next-token-from-slice/disp32 +2140 # . . discard args +2141 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +2142 # curr/ECX = twig->end +2143 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 1/r32/ECX 4/disp8 . # copy *(EDI+4) to ECX +2144 $has-metadata?:loop: +2145 # next-token-from-slice(curr, word->end, '/', twig) +2146 # . . push args +2147 57/push-EDI +2148 68/push 0x2f/imm32/slash +2149 52/push-EDX +2150 51/push-ECX +2151 # . . call +2152 e8/call next-token-from-slice/disp32 +2153 # . . discard args +2154 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +2155 # if (slice-empty?(twig)) return false +2156 # . EAX = slice-empty?(twig) +2157 # . . push args +2158 57/push-EDI +2159 # . . call +2160 e8/call slice-empty?/disp32 +2161 # . . discard args +2162 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2163 # . if (EAX != 0) return false +2164 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX +2165 75/jump-if-not-equal $has-metadata?:false/disp8 +2166 # if (slice-equal?(twig, s)) return true +2167 # . EAX = slice-equal?(twig, s) +2168 # . . push args +2169 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +2170 57/push-EDI +2171 # . . call +2172 e8/call slice-equal?/disp32 +2173 # . . discard args +2174 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2175 # . if (EAX != 0) return true +2176 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX +2177 75/jump-if-not-equal $has-metadata?:true/disp8 +2178 # curr = twig->end +2179 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 1/r32/ECX 4/disp8 . # copy *(EDI+4) to ECX +2180 eb/jump $has-metadata?:loop/disp8 +2181 $has-metadata?:true: +2182 b8/copy-to-EAX 1/imm32/true +2183 eb/jump $has-metadata?:end/disp8 +2184 $has-metadata?:false: +2185 b8/copy-to-EAX 0/imm32/false +2186 $has-metadata?:end: +2187 # . reclaim locals +2188 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2189 # . restore registers +2190 5f/pop-to-EDI +2191 5e/pop-to-ESI +2192 5a/pop-to-EDX +2193 59/pop-to-ECX +2194 # . epilog +2195 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2196 5d/pop-to-EBP +2197 c3/return +2198 +2199 test-has-metadata-true: +2200 # . prolog +2201 55/push-EBP +2202 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2203 # (EAX..ECX) = "ab/c" +2204 b8/copy-to-EAX "ab/c"/imm32 +2205 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2206 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 +2207 05/add-to-EAX 4/imm32 +2208 # var in/ESI : (address slice) = {EAX, ECX} +2209 51/push-ECX +2210 50/push-EAX +2211 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI +2212 # EAX = has-metadata?(ESI, "c") +2213 # . . push args +2214 68/push "c"/imm32 +2215 56/push-ESI +2216 # . . call +2217 e8/call has-metadata?/disp32 +2218 # . . discard args +2219 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x8/imm32 # add to ESP +2220 # check-ints-equal(EAX, 1, msg) +2221 # . . push args +2222 68/push "F - test-has-metadata-true"/imm32 +2223 68/push 1/imm32/true +2224 50/push-EAX +2225 # . . call +2226 e8/call check-ints-equal/disp32 +2227 # . . discard args +2228 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2229 # . epilog +2230 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2231 5d/pop-to-EBP +2232 c3/return +2233 +2234 test-has-metadata-false: +2235 # . prolog +2236 55/push-EBP +2237 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2238 # (EAX..ECX) = "ab/c" +2239 b8/copy-to-EAX "ab/c"/imm32 +2240 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2241 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 +2242 05/add-to-EAX 4/imm32 +2243 # var in/ESI : (address slice) = {EAX, ECX} +2244 51/push-ECX +2245 50/push-EAX +2246 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI +2247 # EAX = has-metadata?(ESI, "c") +2248 # . . push args +2249 68/push "d"/imm32 +2250 56/push-ESI +2251 # . . call +2252 e8/call has-metadata?/disp32 +2253 # . . discard args +2254 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x8/imm32 # add to ESP +2255 # check-ints-equal(EAX, 0, msg) +2256 # . . push args +2257 68/push "F - test-has-metadata-false"/imm32 +2258 68/push 0/imm32/false +2259 50/push-EAX +2260 # . . call +2261 e8/call check-ints-equal/disp32 +2262 # . . discard args +2263 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2264 # . epilog +2265 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2266 5d/pop-to-EBP +2267 c3/return +2268 +2269 test-has-metadata-ignore-name: +2270 # . prolog +2271 55/push-EBP +2272 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2273 # (EAX..ECX) = "a/b" +2274 b8/copy-to-EAX "a/b"/imm32 +2275 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2276 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 +2277 05/add-to-EAX 4/imm32 +2278 # var in/ESI : (address slice) = {EAX, ECX} +2279 51/push-ECX +2280 50/push-EAX +2281 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI +2282 # EAX = has-metadata?(ESI, "a") +2283 # . . push args +2284 68/push "a"/imm32 +2285 56/push-ESI +2286 # . . call +2287 e8/call has-metadata?/disp32 +2288 # . . discard args +2289 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x8/imm32 # add to ESP +2290 # check-ints-equal(EAX, 0, msg) +2291 # . . push args +2292 68/push "F - test-has-metadata-ignore-name"/imm32 +2293 68/push 0/imm32/false +2294 50/push-EAX +2295 # . . call +2296 e8/call check-ints-equal/disp32 +2297 # . . discard args +2298 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2299 # . epilog +2300 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2301 5d/pop-to-EBP +2302 c3/return +2303 +2304 test-has-metadata-multiple-true: +2305 # . prolog +2306 55/push-EBP +2307 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2308 # (EAX..ECX) = "a/b/c" +2309 b8/copy-to-EAX "a/b/c"/imm32 +2310 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +2311 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 +2312 05/add-to-EAX 4/imm32 +2313 # var in/ESI : (address slice) = {EAX, ECX} +2314 51/push-ECX +2315 50/push-EAX +2316 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI +2317 # EAX = has-metadata?(ESI, "c") +2318 # . . push args +2319 68/push "c"/imm32 +2320 56/push-ESI +2321 # . . call +2322 e8/call has-metadata?/disp32 +2323 # . . discard args +2324 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x8/imm32 # add to ESP +2325 # check-ints-equal(EAX, 1, msg) +2326 # . . push args +2327 68/push "F - test-has-metadata-multiple-true"/imm32 +2328 68/push 1/imm32/true +2329 50/push-EAX +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-has-metadata-multiple-false: +2340 # . prolog +2341 55/push-EBP +2342 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2343 # (EAX..ECX) = "a/b/c" +2344 b8/copy-to-EAX "a/b/c"/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 # var in/ESI : (address slice) = {EAX, ECX} +2349 51/push-ECX +2350 50/push-EAX +2351 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI +2352 # EAX = has-metadata?(ESI, "d") +2353 # . . push args +2354 68/push "d"/imm32 +2355 56/push-ESI +2356 # . . call +2357 e8/call has-metadata?/disp32 +2358 # . . discard args +2359 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x8/imm32 # add to ESP +2360 # check-ints-equal(EAX, 0, msg) +2361 # . . push args +2362 68/push "F - test-has-metadata-multiple-false"/imm32 +2363 68/push 0/imm32/false +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 # . epilog +2370 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2371 5d/pop-to-EBP +2372 c3/return +2373 +2374 # If value of 'word' is not a valid name, it must be a hex int. Parse and print +2375 # it in 'width' bytes of hex, least significant first. +2376 # Otherwise just print the entire word including metadata. +2377 # Always print a trailing space. +2378 emit: # out : (address buffered-file), word : (address slice), width : int -> <void> +2379 # . prolog +2380 55/push-EBP +2381 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2382 # . save registers +2383 50/push-EAX +2384 56/push-ESI +2385 57/push-EDI +2386 # ESI = word +2387 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI +2388 # var name/EDI : (address slice) = {0, 0} +2389 68/push 0/imm32/end +2390 68/push 0/imm32/start +2391 89/copy 3/mod/direct 7/rm32/EDI . . . 4/r32/ESP . . # copy ESP to EDI +2392 # name = next-token-from-slice(word->start, word->end, '/') +2393 # . . push args +2394 57/push-EDI +2395 68/push 0x2f/imm32/slash +2396 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) +2397 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI +2398 # . . call +2399 e8/call next-token-from-slice/disp32 +2400 # . . discard args +2401 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +2402 # if (is-valid-name?(name)) write-slice(out, word) and return +2403 # . EAX = is-valid-name?(name) +2404 # . . push args +2405 57/push-EDI +2406 # . . call +2407 e8/call is-valid-name?/disp32 +2408 # . . discard args +2409 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2410 # . if (EAX != 0) +2411 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX +2412 74/jump-if-equal $emit:hex-int/disp8 +2413 $emit:name: +2414 # . write-slice(out, word) +2415 # . . push args +2416 56/push-ESI +2417 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2418 # . . call +2419 e8/call write-slice/disp32 +2420 # . . discard args +2421 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2422 # . write-buffered(out, " ") +2423 # . . push args +2424 68/push " "/imm32 +2425 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2426 # . . call +2427 e8/call write-buffered/disp32 +2428 # . . discard args +2429 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2430 # . return +2431 eb/jump $emit:end/disp8 +2432 # otherwise emit-hex(out, parse-hex-int(name), width) +2433 # (Weird shit can happen here if the value of 'word' isn't either a valid +2434 # name or a hex number, but we're only going to be passing in real legal +2435 # programs. We just want to make sure that valid names aren't treated as +2436 # (valid) hex numbers.) +2437 $emit:hex-int: +2438 # . n/EAX = parse-hex-int(name) +2439 # . . push args +2440 57/push-EDI +2441 # . . call +2442 e8/call parse-hex-int/disp32 +2443 # . . discard args +2444 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2445 # . emit-hex(out, n, width) +2446 # . . push args +2447 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) +2448 50/push-EAX +2449 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2450 # . . call +2451 e8/call emit-hex/disp32 +2452 # . . discard args +2453 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2454 $emit:end: +2455 # . reclaim locals +2456 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2457 # . restore registers +2458 5f/pop-to-EDI +2459 5e/pop-to-ESI +2460 58/pop-to-EAX +2461 # . epilog +2462 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2463 5d/pop-to-EBP +2464 c3/return +2465 +2466 test-emit-number: +2467 # . prolog +2468 55/push-EBP +2469 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2470 # setup +2471 # . clear-stream(_test-stream) +2472 # . . push args +2473 68/push _test-stream/imm32 +2474 # . . call +2475 e8/call clear-stream/disp32 +2476 # . . discard args +2477 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2478 # . clear-stream(_test-buffered-file+4) +2479 # . . push args +2480 b8/copy-to-EAX _test-buffered-file/imm32 +2481 05/add-to-EAX 4/imm32 +2482 50/push-EAX +2483 # . . call +2484 e8/call clear-stream/disp32 +2485 # . . discard args +2486 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2487 # var slice/ECX = "30" +2488 68/push _test-slice-three-zero-end/imm32/end +2489 68/push _test-slice-three-zero/imm32/start +2490 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2491 # emit(_test-buffered-file, slice, 1) +2492 # . . push args +2493 68/push 1/imm32 +2494 51/push-ECX +2495 68/push _test-buffered-file/imm32 +2496 # . . call +2497 e8/call emit/disp32 +2498 # . . discard args +2499 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2500 # flush(_test-buffered-file) +2501 # . . push args +2502 68/push _test-buffered-file/imm32 +2503 # . . call +2504 e8/call flush/disp32 +2505 # . . discard args +2506 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2507 # check-stream-equal(_test-stream, "30 ", msg) +2508 # . . push args +2509 68/push "F - test-emit-number/1"/imm32 +2510 68/push "30 "/imm32 +2511 68/push _test-stream/imm32 +2512 # . . call +2513 e8/call check-stream-equal/disp32 +2514 # . . discard args +2515 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2516 # . epilog +2517 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2518 5d/pop-to-EBP +2519 c3/return +2520 +2521 test-emit-negative-number: +2522 # test support for sign-extending negative numbers +2523 # . prolog +2524 55/push-EBP +2525 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2526 # setup +2527 # . clear-stream(_test-stream) +2528 # . . push args +2529 68/push _test-stream/imm32 +2530 # . . call +2531 e8/call clear-stream/disp32 +2532 # . . discard args +2533 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2534 # . clear-stream(_test-buffered-file+4) +2535 # . . push args +2536 b8/copy-to-EAX _test-buffered-file/imm32 +2537 05/add-to-EAX 4/imm32 +2538 50/push-EAX +2539 # . . call +2540 e8/call clear-stream/disp32 +2541 # . . discard args +2542 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2543 # var slice/ECX = "-2" +2544 68/push _test-slice-negative-two-end/imm32/end +2545 68/push _test-slice-negative-two/imm32/start +2546 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2547 # emit(_test-buffered-file, slice, 2) +2548 # . . push args +2549 68/push 2/imm32 +2550 51/push-ECX +2551 68/push _test-buffered-file/imm32 +2552 # . . call +2553 e8/call emit/disp32 +2554 # . . discard args +2555 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2556 # flush(_test-buffered-file) +2557 # . . push args +2558 68/push _test-buffered-file/imm32 +2559 # . . call +2560 e8/call flush/disp32 +2561 # . . discard args +2562 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2563 # check-stream-equal(_test-stream, "fe ff ", msg) +2564 # . . push args +2565 68/push "F - test-emit-number/1"/imm32 +2566 68/push "fe ff "/imm32 +2567 68/push _test-stream/imm32 +2568 # . . call +2569 e8/call check-stream-equal/disp32 +2570 # . . discard args +2571 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2572 # . epilog +2573 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2574 5d/pop-to-EBP +2575 c3/return +2576 +2577 test-emit-number-with-metadata: +2578 # . prolog +2579 55/push-EBP +2580 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2581 # setup +2582 # . clear-stream(_test-stream) +2583 # . . push args +2584 68/push _test-stream/imm32 +2585 # . . call +2586 e8/call clear-stream/disp32 +2587 # . . discard args +2588 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2589 # . clear-stream(_test-buffered-file+4) +2590 # . . push args +2591 b8/copy-to-EAX _test-buffered-file/imm32 +2592 05/add-to-EAX 4/imm32 +2593 50/push-EAX +2594 # . . call +2595 e8/call clear-stream/disp32 +2596 # . . discard args +2597 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2598 # var slice/ECX = "-2/foo" +2599 68/push _test-slice-negative-two-metadata-end/imm32/end +2600 68/push _test-slice-negative-two/imm32/start +2601 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2602 # emit(_test-buffered-file, slice, 2) +2603 # . . push args +2604 68/push 2/imm32 +2605 51/push-ECX +2606 68/push _test-buffered-file/imm32 +2607 # . . call +2608 e8/call emit/disp32 +2609 # . . discard args +2610 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2611 # flush(_test-buffered-file) +2612 # . . push args +2613 68/push _test-buffered-file/imm32 +2614 # . . call +2615 e8/call flush/disp32 +2616 # . . discard args +2617 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2618 # the '/foo' will have no impact on the output +2619 # check-stream-equal(_test-stream, "fe ff ", msg) +2620 # . . push args +2621 68/push "F - test-emit-number-with-metadata"/imm32 +2622 68/push "fe ff "/imm32 +2623 68/push _test-stream/imm32 +2624 # . . call +2625 e8/call check-stream-equal/disp32 +2626 # . . discard args +2627 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2628 # . epilog +2629 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2630 5d/pop-to-EBP +2631 c3/return +2632 +2633 test-emit-non-number: +2634 # . prolog +2635 55/push-EBP +2636 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2637 # setup +2638 # . clear-stream(_test-stream) +2639 # . . push args +2640 68/push _test-stream/imm32 +2641 # . . call +2642 e8/call clear-stream/disp32 +2643 # . . discard args +2644 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2645 # . clear-stream(_test-buffered-file+4) +2646 # . . push args +2647 b8/copy-to-EAX _test-buffered-file/imm32 +2648 05/add-to-EAX 4/imm32 +2649 50/push-EAX +2650 # . . call +2651 e8/call clear-stream/disp32 +2652 # . . discard args +2653 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2654 # var slice/ECX = "xyz" +2655 68/push _test-slice-non-number-word-end/imm32/end +2656 68/push _test-slice-non-number-word/imm32/start +2657 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2658 # emit(_test-buffered-file, slice, 2) +2659 # . . push args +2660 68/push 2/imm32 +2661 51/push-ECX +2662 68/push _test-buffered-file/imm32 +2663 # . . call +2664 e8/call emit/disp32 +2665 # . . discard args +2666 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2667 # flush(_test-buffered-file) +2668 # . . push args +2669 68/push _test-buffered-file/imm32 +2670 # . . call +2671 e8/call flush/disp32 +2672 # . . discard args +2673 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2674 # check-stream-equal(_test-stream, "xyz", msg) +2675 # . . push args +2676 68/push "F - test-emit-non-number"/imm32 +2677 68/push "xyz "/imm32 +2678 68/push _test-stream/imm32 +2679 # . . call +2680 e8/call check-stream-equal/disp32 +2681 # . . discard args +2682 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2683 # . epilog +2684 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2685 5d/pop-to-EBP +2686 c3/return +2687 +2688 test-emit-non-number-with-metadata: +2689 # . prolog +2690 55/push-EBP +2691 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2692 # setup +2693 # . clear-stream(_test-stream) +2694 # . . push args +2695 68/push _test-stream/imm32 +2696 # . . call +2697 e8/call clear-stream/disp32 +2698 # . . discard args +2699 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2700 # . clear-stream(_test-buffered-file+4) +2701 # . . push args +2702 b8/copy-to-EAX _test-buffered-file/imm32 +2703 05/add-to-EAX 4/imm32 +2704 50/push-EAX +2705 # . . call +2706 e8/call clear-stream/disp32 +2707 # . . discard args +2708 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2709 # var slice/ECX = "xyz/" +2710 68/push _test-slice-non-number-word-metadata-end/imm32/end +2711 68/push _test-slice-non-number-word/imm32/start +2712 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2713 # emit(_test-buffered-file, slice, 2) +2714 # . . push args +2715 68/push 2/imm32 +2716 51/push-ECX +2717 68/push _test-buffered-file/imm32 +2718 # . . call +2719 e8/call emit/disp32 +2720 # . . discard args +2721 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2722 # flush(_test-buffered-file) +2723 # . . push args +2724 68/push _test-buffered-file/imm32 +2725 # . . call +2726 e8/call flush/disp32 +2727 # . . discard args +2728 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2729 # check-stream-equal(_test-stream, "xyz/", msg) +2730 # . . push args +2731 68/push "F - test-emit-non-number-with-metadata"/imm32 +2732 68/push "xyz/ "/imm32 +2733 68/push _test-stream/imm32 +2734 # . . call +2735 e8/call check-stream-equal/disp32 +2736 # . . discard args +2737 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2738 # . epilog +2739 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2740 5d/pop-to-EBP +2741 c3/return +2742 +2743 test-emit-non-number-with-all-hex-digits-and-metadata: +2744 # . prolog +2745 55/push-EBP +2746 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2747 # setup +2748 # . clear-stream(_test-stream) +2749 # . . push args +2750 68/push _test-stream/imm32 +2751 # . . call +2752 e8/call clear-stream/disp32 +2753 # . . discard args +2754 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2755 # . clear-stream(_test-buffered-file+4) +2756 # . . push args +2757 b8/copy-to-EAX _test-buffered-file/imm32 +2758 05/add-to-EAX 4/imm32 +2759 50/push-EAX +2760 # . . call +2761 e8/call clear-stream/disp32 +2762 # . . discard args +2763 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2764 # var slice/ECX = "abcd/xyz" +2765 68/push _test-slice-hexlike-non-number-word-metadata-end/imm32/end +2766 68/push _test-slice-hexlike-non-number-word/imm32/start +2767 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2768 # emit(_test-buffered-file, slice, 2) +2769 # . . push args +2770 68/push 2/imm32 +2771 51/push-ECX +2772 68/push _test-buffered-file/imm32 +2773 # . . call +2774 e8/call emit/disp32 +2775 # . . discard args +2776 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2777 # flush(_test-buffered-file) +2778 # . . push args +2779 68/push _test-buffered-file/imm32 +2780 # . . call +2781 e8/call flush/disp32 +2782 # . . discard args +2783 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2784 # check-stream-equal(_test-stream, "abcd/xyz") +2785 # . . push args +2786 68/push "F - test-emit-non-number-with-all-hex-digits"/imm32 +2787 68/push "abcd/xyz"/imm32 +2788 68/push _test-stream/imm32 +2789 # . . call +2790 e8/call check-stream-equal/disp32 +2791 # . . discard args +2792 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2793 # . epilog +2794 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2795 5d/pop-to-EBP +2796 c3/return +2797 +2798 # conditions for 'valid' names that are not at risk of looking like hex numbers +2799 # keep in sync with the rules in labels.cc +2800 #: - if it starts with a digit, it's treated as a number. If it can't be +2801 #: parsed as hex it will raise an error. +2802 #: - if it starts with '-' it's treated as a number. +2803 #: - if it starts with '0x' it's treated as a number. (redundant) +2804 #: - if it's two characters long, it can't be a name. Either it's a hex +2805 #: byte, or it raises an error. +2806 is-valid-name?: # in : (address slice) -> EAX : boolean +2807 # . prolog +2808 55/push-EBP +2809 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2810 # . save registers +2811 51/push-ECX +2812 56/push-ESI +2813 # ESI = in +2814 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +2815 # start/ECX = in->start +2816 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX +2817 # end/EAX = in->end +2818 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy *(ESI+4) to EAX +2819 $is-valid-name?:check0: +2820 # if (start >= end) return false +2821 39/compare 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # compare ECX with EAX +2822 7d/jump-if-greater-or-equal $is-valid-name?:false/disp8 +2823 $is-valid-name?:check1: +2824 # EAX -= ECX +2825 29/subtract 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # subtract ECX from EAX +2826 # if (EAX == 2) return false +2827 3d/compare-with-EAX 2/imm32 +2828 74/jump-if-equal $is-valid-name?:false/disp8 +2829 $is-valid-name?:check2: +2830 # c/EAX = *ECX +2831 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +2832 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +2833 # if (c == "-") return false +2834 3d/compare-with-EAX 2d/imm32/- +2835 74/jump-if-equal $is-valid-name?:false/disp8 +2836 $is-valid-name?:check3a: +2837 # if (c < "0") return true +2838 3d/compare-with-EAX 30/imm32/0 +2839 7c/jump-if-lesser $is-valid-name?:true/disp8 +2840 $is-valid-name?:check3b: +2841 # if (c > "9") return true +2842 3d/compare-with-EAX 39/imm32/9 +2843 7f/jump-if-greater $is-valid-name?:true/disp8 +2844 $is-valid-name?:false: +2845 # return false +2846 b8/copy-to-EAX 0/imm32/false +2847 eb/jump $is-valid-name?:end/disp8 +2848 $is-valid-name?:true: +2849 # return true +2850 b8/copy-to-EAX 1/imm32/true +2851 $is-valid-name?:end: +2852 # . restore registers +2853 5e/pop-to-ESI +2854 59/pop-to-ECX +2855 # . epilog +2856 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2857 5d/pop-to-EBP +2858 c3/return +2859 +2860 test-is-valid-name-digit-prefix: +2861 # . prolog +2862 55/push-EBP +2863 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2864 # var slice/ECX = "34" +2865 68/push _test-slice-hex-int-end/imm32 +2866 68/push _test-slice-hex-int/imm32 +2867 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2868 # EAX = is-valid-name?(slice) +2869 # . . push args +2870 51/push-ECX +2871 # . . call +2872 e8/call is-valid-name?/disp32 +2873 # . . discard args +2874 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2875 # check-ints-equal(EAX, 0, msg) +2876 # . . push args +2877 68/push "F - test-is-valid-name-digit-prefix"/imm32 +2878 68/push 0/imm32/false +2879 50/push-EAX +2880 # . . call +2881 e8/call check-ints-equal/disp32 +2882 # . . discard args +2883 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2884 # . epilog +2885 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2886 5d/pop-to-EBP +2887 c3/return +2888 +2889 test-is-valid-name-negative-prefix: +2890 # . prolog +2891 55/push-EBP +2892 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2893 # var slice/ECX = "-0x34" +2894 68/push _test-slice-hex-int-with-0x-prefix-end/imm32 +2895 68/push _test-slice-hex-int-with-0x-prefix-negative/imm32 +2896 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2897 # EAX = is-valid-name?(slice) +2898 # . . push args +2899 51/push-ECX +2900 # . . call +2901 e8/call is-valid-name?/disp32 +2902 # . . discard args +2903 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2904 # check-ints-equal(EAX, 0, msg) +2905 # . . push args +2906 68/push "F - test-is-valid-name-negative-prefix"/imm32 +2907 68/push 0/imm32/false +2908 50/push-EAX +2909 # . . call +2910 e8/call check-ints-equal/disp32 +2911 # . . discard args +2912 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2913 # . epilog +2914 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2915 5d/pop-to-EBP +2916 c3/return +2917 +2918 test-is-valid-name-0x-prefix: +2919 # . prolog +2920 55/push-EBP +2921 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2922 # var slice/ECX = "0x34" +2923 68/push _test-slice-hex-int-with-0x-prefix-end/imm32 +2924 68/push _test-slice-hex-int-with-0x-prefix/imm32 +2925 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2926 # EAX = is-valid-name?(slice) +2927 # . . push args +2928 51/push-ECX +2929 # . . call +2930 e8/call is-valid-name?/disp32 +2931 # . . discard args +2932 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2933 # check-ints-equal(EAX, 0, msg) +2934 # . . push args +2935 68/push "F - test-is-valid-name-0x-prefix"/imm32 +2936 68/push 0/imm32/false +2937 50/push-EAX +2938 # . . call +2939 e8/call check-ints-equal/disp32 +2940 # . . discard args +2941 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2942 # . epilog +2943 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2944 5d/pop-to-EBP +2945 c3/return +2946 +2947 test-is-valid-name-starts-with-pre-digit: +2948 # . prolog +2949 55/push-EBP +2950 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2951 # var slice/ECX = "/03" +2952 68/push _test-slice-with-slash-prefix-end/imm32 +2953 68/push _test-slice-with-slash-prefix/imm32 +2954 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2955 # EAX = is-valid-name?(slice) +2956 # . . push args +2957 51/push-ECX +2958 # . . call +2959 e8/call is-valid-name?/disp32 +2960 # . . discard args +2961 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2962 # check-ints-equal(EAX, 1, msg) +2963 # . . push args +2964 68/push "F - test-is-valid-name-starts-with-pre-digit"/imm32 +2965 68/push 1/imm32/true +2966 50/push-EAX +2967 # . . call +2968 e8/call check-ints-equal/disp32 +2969 # . . discard args +2970 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2971 # . epilog +2972 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2973 5d/pop-to-EBP +2974 c3/return +2975 +2976 test-is-valid-name-starts-with-post-digit: +2977 # . prolog +2978 55/push-EBP +2979 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2980 # var slice/ECX = "q34" +2981 68/push _test-slice-char-and-digits-end/imm32 +2982 68/push _test-slice-char-and-digits/imm32 +2983 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2984 # EAX = is-valid-name?(slice) +2985 # . . push args +2986 51/push-ECX +2987 # . . call +2988 e8/call is-valid-name?/disp32 +2989 # . . discard args +2990 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2991 # check-ints-equal(EAX, 1, msg) +2992 # . . push args +2993 68/push "F - test-is-valid-name-starts-with-post-digit"/imm32 +2994 68/push 1/imm32/true +2995 50/push-EAX +2996 # . . call +2997 e8/call check-ints-equal/disp32 +2998 # . . discard args +2999 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3000 # . epilog +3001 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3002 5d/pop-to-EBP +3003 c3/return +3004 +3005 test-is-valid-name-starts-with-digit: +3006 # . prolog +3007 55/push-EBP +3008 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3009 # var slice/ECX = "0x34" +3010 68/push _test-slice-hex-int-with-0x-prefix-end/imm32 +3011 68/push _test-slice-hex-int-with-0x-prefix/imm32 +3012 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +3013 # EAX = is-valid-name?(slice) +3014 # . . push args +3015 51/push-ECX +3016 # . . call +3017 e8/call is-valid-name?/disp32 +3018 # . . discard args +3019 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3020 # check-ints-equal(EAX, 0, msg) +3021 # . . push args +3022 68/push "F - test-is-valid-name-starts-with-digit"/imm32 +3023 68/push 0/imm32/false +3024 50/push-EAX +3025 # . . call +3026 e8/call check-ints-equal/disp32 +3027 # . . discard args +3028 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3029 # . epilog +3030 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3031 5d/pop-to-EBP +3032 c3/return +3033 +3034 # print 'n' in hex in 'width' bytes in lower-endian order, with a space after every byte +3035 emit-hex: # out : (address buffered-file), n : int, width : int -> <void> +3036 # . prolog +3037 55/push-EBP +3038 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3039 # . save registers +3040 50/push-EAX +3041 51/push-ECX +3042 52/push-EDX +3043 53/push-EBX +3044 57/push-EDI +3045 # EDI = out +3046 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI +3047 # EBX = n +3048 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX +3049 # EDX = width +3050 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 2/r32/EDX 0x10/disp8 . # copy *(EBP+16) to EDX +3051 # var curr/ECX = 0 +3052 31/xor 3/mod/direct 1/rm32/ECX . . . 1/r32/ECX . . # clear ECX +3053 $emit-hex:loop: +3054 # if (curr >= width) break +3055 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX and EDX +3056 7d/jump-if-greater-or-equal $emit-hex:end/disp8 +3057 #? # if (EBX == 0) write(out, "00 ") and continue +3058 #? 81 7/subop/compare 3/mod/direct 1/rm32/ECX . . . . . 0/imm32 # compare ECX +3059 #? 75/jump-if-not-equal $emit-hex:print-octet/disp8 +3060 #? $emit-hex:pad-zero: +3061 #? # . write(out, "00 ") +3062 #? # . . push args +3063 #? 68/push "00 "/imm32 +3064 #? 57/push-EDI +3065 #? # . . call +3066 #? e8/call write/disp32 +3067 #? # . . discard args +3068 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3069 #? eb/jump $emit-hex:continue/disp8 +3070 #? $emit-hex:print-octet: +3071 # print-byte(out, EBX) +3072 # . . push args +3073 53/push-EBX +3074 57/push-EDI +3075 # . . call +3076 e8/call print-byte/disp32 +3077 # . . discard args +3078 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3079 # write-byte(out, ' ') +3080 # . . push args +3081 68/push 0x20/imm32/space +3082 57/push-EDI +3083 # . . call +3084 e8/call write-byte/disp32 +3085 # . . discard args +3086 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3087 # EBX = EBX >> 8 +3088 c1/shift 5/subop/logic-right 3/mod/direct 3/rm32/EBX . . . . . 8/imm8 # shift EBX right by 8 bits, while padding zeroes +3089 #? $emit-hex:continue: +3090 # ++curr +3091 41/increment-ECX +3092 eb/jump $emit-hex:loop/disp8 +3093 $emit-hex:end: +3094 # . restore registers +3095 5f/pop-to-EDI +3096 5b/pop-to-EBX +3097 5a/pop-to-EDX +3098 59/pop-to-ECX +3099 58/pop-to-EAX +3100 # . epilog +3101 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3102 5d/pop-to-EBP +3103 c3/return +3104 +3105 test-emit-hex-single-byte: +3106 # setup +3107 # . clear-stream(_test-stream) +3108 # . . push args +3109 68/push _test-stream/imm32 +3110 # . . call +3111 e8/call clear-stream/disp32 +3112 # . . discard args +3113 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3114 # . clear-stream(_test-buffered-file+4) +3115 # . . push args +3116 b8/copy-to-EAX _test-buffered-file/imm32 +3117 05/add-to-EAX 4/imm32 +3118 50/push-EAX +3119 # . . call +3120 e8/call clear-stream/disp32 +3121 # . . discard args +3122 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3123 # emit-hex(_test-buffered-file, 0xab, 1) +3124 # . . push args +3125 68/push 1/imm32 +3126 68/push 0xab/imm32 +3127 68/push _test-buffered-file/imm32 +3128 # . . call +3129 e8/call emit-hex/disp32 +3130 # . . discard args +3131 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3132 # flush(_test-buffered-file) +3133 # . . push args +3134 68/push _test-buffered-file/imm32 +3135 # . . call +3136 e8/call flush/disp32 +3137 # . . discard args +3138 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3139 # check-ints-equal(*_test-stream->data, 'ab ', msg) +3140 # . . push args +3141 68/push "F - test-emit-hex-single-byte"/imm32 +3142 68/push 0x206261/imm32 +3143 # . . push *_test-stream->data +3144 b8/copy-to-EAX _test-stream/imm32 +3145 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) +3146 # . . call +3147 e8/call check-ints-equal/disp32 +3148 # . . discard args +3149 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3150 # . end +3151 c3/return +3152 +3153 test-emit-hex-multiple-byte: +3154 # setup +3155 # . clear-stream(_test-stream) +3156 # . . push args +3157 68/push _test-stream/imm32 +3158 # . . call +3159 e8/call clear-stream/disp32 +3160 # . . discard args +3161 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3162 # . clear-stream(_test-buffered-file+4) +3163 # . . push args +3164 b8/copy-to-EAX _test-buffered-file/imm32 +3165 05/add-to-EAX 4/imm32 +3166 50/push-EAX +3167 # . . call +3168 e8/call clear-stream/disp32 +3169 # . . discard args +3170 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3171 # emit-hex(_test-buffered-file, 0x1234, 2) +3172 # . . push args +3173 68/push 2/imm32 +3174 68/push 0x1234/imm32 +3175 68/push _test-buffered-file/imm32 +3176 # . . call +3177 e8/call emit-hex/disp32 +3178 # . . discard args +3179 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3180 # flush(_test-buffered-file) +3181 # . . push args +3182 68/push _test-buffered-file/imm32 +3183 # . . call +3184 e8/call flush/disp32 +3185 # . . discard args +3186 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3187 # check-stream-equal(_test-stream, "34 12 ", msg) +3188 # . . push args +3189 68/push "F - test-emit-hex-multiple-byte/1"/imm32 +3190 68/push "34 12 "/imm32 +3191 68/push _test-stream/imm32 +3192 # . . call +3193 e8/call check-stream-equal/disp32 +3194 # . . discard args +3195 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3196 # . end +3197 c3/return +3198 +3199 test-emit-hex-zero-pad: +3200 # setup +3201 # . clear-stream(_test-stream) +3202 # . . push args +3203 68/push _test-stream/imm32 +3204 # . . call +3205 e8/call clear-stream/disp32 +3206 # . . discard args +3207 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3208 # . clear-stream(_test-buffered-file+4) +3209 # . . push args +3210 b8/copy-to-EAX _test-buffered-file/imm32 +3211 05/add-to-EAX 4/imm32 +3212 50/push-EAX +3213 # . . call +3214 e8/call clear-stream/disp32 +3215 # . . discard args +3216 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3217 # emit-hex(_test-buffered-file, 0xab, 2) +3218 # . . push args +3219 68/push 2/imm32 +3220 68/push 0xab/imm32 +3221 68/push _test-buffered-file/imm32 +3222 # . . call +3223 e8/call emit-hex/disp32 +3224 # . . discard args +3225 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3226 # flush(_test-buffered-file) +3227 # . . push args +3228 68/push _test-buffered-file/imm32 +3229 # . . call +3230 e8/call flush/disp32 +3231 # . . discard args +3232 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3233 # check(_test-stream->data == 'ab 00 ') +3234 # . . push args +3235 68/push "F - test-emit-hex-zero-pad/1"/imm32 +3236 68/push "ab 00 "/imm32 +3237 68/push _test-stream/imm32 +3238 # . . call +3239 e8/call check-stream-equal/disp32 +3240 # . . discard args +3241 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3242 # . end +3243 c3/return +3244 +3245 test-emit-hex-negative: +3246 # setup +3247 # . clear-stream(_test-stream) +3248 # . . push args +3249 68/push _test-stream/imm32 +3250 # . . call +3251 e8/call clear-stream/disp32 +3252 # . . discard args +3253 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3254 # . clear-stream(_test-buffered-file+4) +3255 # . . push args +3256 b8/copy-to-EAX _test-buffered-file/imm32 +3257 05/add-to-EAX 4/imm32 +3258 50/push-EAX +3259 # . . call +3260 e8/call clear-stream/disp32 +3261 # . . discard args +3262 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3263 # emit-hex(_test-buffered-file, -1, 2) +3264 # . . push args +3265 68/push 2/imm32 +3266 68/push -1/imm32 +3267 68/push _test-buffered-file/imm32 +3268 # . . call +3269 e8/call emit-hex/disp32 +3270 # . . discard args +3271 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3272 # flush(_test-buffered-file) +3273 # . . push args +3274 68/push _test-buffered-file/imm32 +3275 # . . call +3276 e8/call flush/disp32 +3277 # . . discard args +3278 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3279 # check-stream-equal(_test-stream == "ff ff ") +3280 # . . push args +3281 68/push "F - test-emit-hex-negative/1"/imm32 +3282 68/push "ff ff "/imm32 +3283 68/push _test-stream/imm32 +3284 # . . call +3285 e8/call check-stream-equal/disp32 +3286 # . . discard args +3287 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3288 # . end +3289 c3/return +3290 +3291 == data +3292 +3293 _test-slice-negative-two: +3294 2d/- 32/2 +3295 _test-slice-negative-two-end: +3296 2f/slash 66/f 6f/o 6f/o +3297 _test-slice-negative-two-metadata-end: +3298 +3299 _test-slice-three-zero: +3300 33/3 30/0 +3301 _test-slice-three-zero-end: +3302 +3303 _test-slice-non-number-word: +3304 78/x 79/y 7a/z +3305 _test-slice-non-number-word-end: +3306 2f/slash +3307 _test-slice-non-number-word-metadata-end: +3308 +3309 _test-input-stream: +3310 # current write index +3311 0/imm32 +3312 # current read index +3313 0/imm32 +3314 # length +3315 0x20/imm32 +3316 # data +3317 00 00 00 00 00 00 00 00 # 8 bytes +3318 00 00 00 00 00 00 00 00 # 8 bytes +3319 00 00 00 00 00 00 00 00 # 8 bytes +3320 00 00 00 00 00 00 00 00 # 8 bytes +3321 +3322 # a test buffered file for _test-input-stream +3323 _test-input-buffered-file: +3324 # file descriptor or (address stream) +3325 _test-input-stream/imm32 +3326 # current write index +3327 0/imm32 +3328 # current read index +3329 0/imm32 +3330 # length +3331 6/imm32 +3332 # data +3333 00 00 00 00 00 00 # 6 bytes +3334 +3335 _test-output-stream: +3336 # current write index +3337 0/imm32 +3338 # current read index +3339 0/imm32 +3340 # length +3341 0x20/imm32 +3342 # data +3343 00 00 00 00 00 00 00 00 # 8 bytes +3344 00 00 00 00 00 00 00 00 # 8 bytes +3345 00 00 00 00 00 00 00 00 # 8 bytes +3346 00 00 00 00 00 00 00 00 # 8 bytes +3347 +3348 # a test buffered file for _test-output-stream +3349 _test-output-buffered-file: +3350 # file descriptor or (address stream) +3351 _test-output-stream/imm32 +3352 # current write index +3353 0/imm32 +3354 # current read index +3355 0/imm32 +3356 # length +3357 6/imm32 +3358 # data +3359 00 00 00 00 00 00 # 6 bytes +3360 +3361 _test-slice-hexlike-non-number-word: +3362 61/a 62/b 63/c 64/d +3363 _test-slice-hexlike-non-number-word-end: +3364 2f/slash +3365 78/x 79/y 7a/z +3366 _test-slice-hexlike-non-number-word-metadata-end: +3367 +3368 _test-slice-with-slash-prefix: +3369 2f/slash 30/0 33/3 +3370 _test-slice-with-slash-prefix-end: +3371 +3372 # . . vim:nowrap:textwidth=0 -- cgit 1.4.1-2-gfad0