From e99038ea514a8703b170689d5a0730c8d2e542e7 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Mon, 18 Feb 2019 22:43:01 -0800 Subject: 4982 --- html/subx/apps/hex.subx.html | 3037 +++++++++++++++++++++--------------------- 1 file changed, 1519 insertions(+), 1518 deletions(-) (limited to 'html/subx/apps/hex.subx.html') diff --git a/html/subx/apps/hex.subx.html b/html/subx/apps/hex.subx.html index 44caac4b..90e08318 100644 --- a/html/subx/apps/hex.subx.html +++ b/html/subx/apps/hex.subx.html @@ -18,13 +18,13 @@ a { color:inherit; } .subxS2Comment { color: #8a8a8a; } .LineNr { } .subxS1Comment { color: #0000af; } -.CommentedCode { color: #8a8a8a; } +.SpecialChar { color: #d70000; } .Constant { color: #008787; } .subxFunction { color: #af5f00; text-decoration: underline; } .subxMinorFunction { color: #875f5f; } .Normal { color: #000000; background-color: #c6c6c6; padding-bottom: 1px; } .subxTest { color: #5f8700; } -.SpecialChar { color: #d70000; } +.CommentedCode { color: #8a8a8a; } .subxH1Comment { color: #005faf; text-decoration: underline; } --> @@ -80,1522 +80,1523 @@ if ('onhashchange' in window) { 17 # . op subop mod rm32 base index scale r32 18 # . 1-3 bytes 3 bits 2 bits 3 bits 3 bits 3 bits 2 bits 2 bits 0/1/2/4 bytes 0/1/2/4 bytes 19 - 20 # for debugging: run a single test - 21 #? e8/call test-skip-until-newline/disp32 - 22 #? 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX - 23 #? eb/jump $main:end/disp8 - 24 - 25 # main: run tests if necessary, convert stdin if not - 26 # . prolog - 27 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 28 # - if argc > 1 and argv[1] == "test", then return run_tests() - 29 # . argc > 1 - 30 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP - 31 7e/jump-if-lesser-or-equal $run-main/disp8 - 32 # . argv[1] == "test" - 33 # . . push args - 34 68/push "test"/imm32 - 35 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 36 # . . call - 37 e8/call kernel-string-equal?/disp32 - 38 # . . discard args - 39 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 40 # . check result - 41 3d/compare-EAX 1/imm32 - 42 75/jump-if-not-equal $run-main/disp8 - 43 # . run-tests() - 44 e8/call run-tests/disp32 - 45 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX - 46 eb/jump $main:end/disp8 - 47 $run-main: - 48 # - otherwise convert stdin - 49 # var ed/EAX : exit-descriptor - 50 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 51 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX - 52 # configure ed to really exit() - 53 # . ed->target = 0 - 54 c7 0/subop/copy 0/mod/direct 0/rm32/EAX . . . . . 0/imm32 # copy to *EAX - 55 # return convert(Stdin, 1/stdout, 2/stderr, ed) - 56 # . . push args - 57 50/push-EAX/ed - 58 68/push Stderr/imm32 - 59 68/push Stdout/imm32 - 60 68/push Stdin/imm32 - 61 # . . call - 62 e8/call convert/disp32 - 63 # . . discard args - 64 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP - 65 # . syscall(exit, 0) - 66 bb/copy-to-EBX 0/imm32 - 67 $main:end: - 68 b8/copy-to-EAX 1/imm32/exit - 69 cd/syscall 0x80/imm8 - 70 - 71 # the main entry point - 72 convert: # in : (address buffered-file), out : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> <void> - 73 # pseudocode: - 74 # repeatedly - 75 # EAX = convert-next-octet(in, err, ed) - 76 # if (EAX == 0xffffffff) break # eof - 77 # write-byte(out, AL) - 78 # flush(out) - 79 # - 80 # . prolog - 81 55/push-EBP - 82 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 83 # . save registers - 84 50/push-EAX - 85 $convert:loop: - 86 # EAX = convert-next-octet(in, err, ed) - 87 # . . push args - 88 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x14/disp8 . # push *(EBP+20) - 89 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) - 90 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 91 # . . call - 92 e8/call convert-next-octet/disp32 - 93 # . . discard first 2 args - 94 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 95 # if (EAX == 0xffffffff) break - 96 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX - 97 74/jump-if-equal $convert:loop-end/disp8 - 98 # write-byte(out, AL) - 99 # . . push args - 100 50/push-EAX - 101 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 102 # . . call - 103 e8/call write-byte/disp32 - 104 # . . discard args - 105 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 106 # loop - 107 eb/jump $convert:loop/disp8 - 108 $convert:loop-end: - 109 # flush(out) - 110 # . . push args - 111 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 112 # . . call - 113 e8/call flush/disp32 - 114 # . . discard args - 115 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 116 $convert:end: - 117 # . restore registers - 118 58/pop-to-EAX - 119 # . epilog - 120 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 121 5d/pop-to-EBP - 122 c3/return - 123 - 124 # read bytes from 'in' until a sequence of two lowercase hex (0-9, a-f) bytes - 125 # skip spaces and newlines - 126 # on '#' skip bytes until newline - 127 # raise an error and abort on all other unexpected bytes - 128 # return in EAX an _octet_ containing the binary value of the two hex characters - 129 # return 0xffffffff on end of file - 130 convert-next-octet: # in : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> byte-or-eof/EAX - 131 # pseudocode: - 132 # EAX = scan-next-byte(in, err, ed) - 133 # if (EAX == 0xffffffff) return - 134 # ECX = from-hex-char(EAX) - 135 # EAX = scan-next-byte(in, err, ed) - 136 # if (EAX == 0xffffffff) error("partial byte found.") - 137 # EAX = from-hex-char(EAX) - 138 # EAX = (ECX << 4) | EAX - 139 # return - 140 # - 141 # . prolog - 142 55/push-EBP - 143 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 144 # . save registers - 145 51/push-ECX - 146 # EAX = scan-next-byte(in, err, ed) - 147 # . . push args - 148 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) - 149 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 150 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 151 # . . call - 152 e8/call scan-next-byte/disp32 - 153 # . . discard args - 154 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 155 # if (EAX == 0xffffffff) return - 156 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX - 157 74/jump-if-equal $convert-next-octet:end/disp8 - 158 # EAX = from-hex-char(EAX) - 159 e8/call from-hex-char/disp32 - 160 # ECX = EAX - 161 89/copy 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # copy EAX to ECX - 162 # EAX = scan-next-byte(in, err, ed) - 163 # . . push args - 164 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) - 165 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 166 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 167 # . . call - 168 e8/call scan-next-byte/disp32 - 169 # . . discard args - 170 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 171 # if (EAX == 0xffffffff) error(ed, err, "partial byte found.") - 172 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX - 173 75/jump-if-not-equal $convert-next-octet:convert/disp8 - 174 # . error-byte(ed, err, msg, '.') # reusing error-byte to avoid creating _yet_ another helper - 175 # . . push args - 176 68/push 0x2e/imm32/period/dummy - 177 68/push "convert-next-octet: partial byte found"/imm32 - 178 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 179 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) - 180 # . . call - 181 e8/call error-byte/disp32 # never returns - 182 $convert-next-octet:convert: - 183 # EAX = from-hex-char(EAX) - 184 e8/call from-hex-char/disp32 - 185 # EAX = (ECX << 4) | EAX - 186 # . ECX <<= 4 - 187 c1/shift 4/subop/left 3/mod/direct 1/rm32/ECX . . . . . 4/imm8 # shift ECX left by 4 bits - 188 # . EAX |= ECX - 189 09/or 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # EAX = bitwise OR with ECX - 190 $convert-next-octet:end: - 191 # . restore registers - 192 59/pop-to-ECX - 193 # . epilog - 194 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 195 5d/pop-to-EBP - 196 c3/return - 197 - 198 test-convert-next-octet: - 199 # - check that the first two bytes of the input are assembled into the resulting octet - 200 # This test uses exit-descriptors. Use EBP for setting up local variables. - 201 55/push-EBP - 202 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 203 # clear all streams - 204 # . clear-stream(_test-stream) - 205 # . . push args - 206 68/push _test-stream/imm32 - 207 # . . call - 208 e8/call clear-stream/disp32 - 209 # . . discard args - 210 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 211 # . clear-stream(_test-buffered-file+4) - 212 # . . push args - 213 b8/copy-to-EAX _test-buffered-file/imm32 - 214 05/add-to-EAX 4/imm32 - 215 50/push-EAX - 216 # . . call - 217 e8/call clear-stream/disp32 - 218 # . . discard args - 219 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 220 # . clear-stream(_test-error-stream) - 221 # . . push args - 222 68/push _test-error-stream/imm32 - 223 # . . call - 224 e8/call clear-stream/disp32 - 225 # . . discard args - 226 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 227 # . clear-stream(_test-error-buffered-file+4) - 228 # . . push args - 229 b8/copy-to-EAX _test-error-buffered-file/imm32 - 230 05/add-to-EAX 4/imm32 - 231 50/push-EAX - 232 # . . call - 233 e8/call clear-stream/disp32 - 234 # . . discard args - 235 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 236 # initialize '_test-stream' to "abc" - 237 # . write(_test-stream, "abc") - 238 # . . push args - 239 68/push "abc"/imm32 - 240 68/push _test-stream/imm32 - 241 # . . call - 242 e8/call write/disp32 - 243 # . . discard args - 244 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 245 # initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below - 246 # . var ed/ECX : exit-descriptor - 247 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 248 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 249 # . tailor-exit-descriptor(ed, 12) - 250 # . . push args - 251 68/push 0xc/imm32/nbytes-of-args-for-convert-next-octet - 252 51/push-ECX/ed - 253 # . . call - 254 e8/call tailor-exit-descriptor/disp32 - 255 # . . discard args - 256 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 257 # EAX = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed) - 258 # . . push args - 259 51/push-ECX/ed - 260 68/push _test-error-buffered-file/imm32 - 261 68/push _test-buffered-file/imm32 - 262 # . . call - 263 e8/call convert-next-octet/disp32 - 264 # registers except ESP may be clobbered at this point - 265 # pop args to convert-next-octet - 266 # . . discard first 2 args - 267 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 268 # . . restore ed - 269 59/pop-to-ECX - 270 # check that convert-next-octet didn't abort - 271 # . check-ints-equal(ed->value, 0, msg) - 272 # . . push args - 273 68/push "F - test-convert-next-octet: unexpected abort"/imm32 - 274 68/push 0/imm32 - 275 # . . push ed->value - 276 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) - 277 # . . call - 278 e8/call check-ints-equal/disp32 - 279 # . . discard args - 280 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 281 # return if abort - 282 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) - 283 75/jump-if-not-equal $test-convert-next-octet:end/disp8 - 284 # check-ints-equal(EAX, 0xab, msg) - 285 # . . push args - 286 68/push "F - test-convert-next-octet"/imm32 - 287 68/push 0xab/imm32/ab - 288 50/push-EAX - 289 # . . call - 290 e8/call check-ints-equal/disp32 - 291 # . . discard args - 292 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 293 $test-convert-next-octet:end: - 294 # . epilog - 295 # don't restore ESP from EBP; manually reclaim locals - 296 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 297 5d/pop-to-EBP - 298 c3/return - 299 - 300 test-convert-next-octet-handles-eof: - 301 # - check that eof returns the sentinel octet - 302 # This test uses exit-descriptors. Use EBP for setting up local variables. - 303 55/push-EBP - 304 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 305 # clear all streams - 306 # . clear-stream(_test-stream) - 307 # . . push args - 308 68/push _test-stream/imm32 - 309 # . . call - 310 e8/call clear-stream/disp32 - 311 # . . discard args - 312 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 313 # . clear-stream(_test-buffered-file+4) - 314 # . . push args - 315 b8/copy-to-EAX _test-buffered-file/imm32 - 316 05/add-to-EAX 4/imm32 - 317 50/push-EAX - 318 # . . call - 319 e8/call clear-stream/disp32 - 320 # . . discard args - 321 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 322 # . clear-stream(_test-error-stream) - 323 # . . push args - 324 68/push _test-error-stream/imm32 - 325 # . . call - 326 e8/call clear-stream/disp32 - 327 # . . discard args - 328 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 329 # . clear-stream(_test-error-buffered-file+4) - 330 # . . push args - 331 b8/copy-to-EAX _test-error-buffered-file/imm32 - 332 05/add-to-EAX 4/imm32 - 333 50/push-EAX - 334 # . . call - 335 e8/call clear-stream/disp32 - 336 # . . discard args - 337 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 338 # don't initialize '_test-stream' - 339 # initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below - 340 # . var ed/ECX : exit-descriptor - 341 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 342 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 343 # . tailor-exit-descriptor(ed, 12) - 344 # . . push args - 345 68/push 0xc/imm32/nbytes-of-args-for-convert-next-octet - 346 51/push-ECX/ed - 347 # . . call - 348 e8/call tailor-exit-descriptor/disp32 - 349 # . . discard args - 350 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 351 # EAX = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed) - 352 # . . push args - 353 51/push-ECX/ed - 354 68/push _test-error-buffered-file/imm32 - 355 68/push _test-buffered-file/imm32 - 356 # . . call - 357 e8/call convert-next-octet/disp32 - 358 # registers except ESP may be clobbered at this point - 359 # pop args to convert-next-octet - 360 # . . discard first 2 args - 361 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 362 # . . restore ed - 363 59/pop-to-ECX - 364 # check that convert-next-octet didn't abort - 365 # . check-ints-equal(ed->value, 0, msg) - 366 # . . push args - 367 68/push "F - test-convert-next-octet: unexpected abort"/imm32 - 368 68/push 0/imm32 - 369 # . . push ed->value - 370 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) - 371 # . . call - 372 e8/call check-ints-equal/disp32 - 373 # . . discard args - 374 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 375 # return if abort - 376 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) - 377 75/jump-if-not-equal $test-convert-next-octet-handles-eof:end/disp8 - 378 # check-ints-equal(EAX, 0xffffffff, msg) - 379 # . . push args - 380 68/push "F - test-convert-next-octet-handles-eof"/imm32 - 381 68/push 0xffffffff/imm32/eof - 382 50/push-EAX - 383 # . . call - 384 e8/call check-ints-equal/disp32 - 385 # . . discard args - 386 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 387 $test-convert-next-octet-handles-eof:end: - 388 # . epilog - 389 # don't restore ESP from EBP; manually reclaim locals - 390 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 391 5d/pop-to-EBP - 392 c3/return - 393 - 394 test-convert-next-octet-aborts-on-single-hex-byte: - 395 # - check that a single unaccompanied hex byte aborts - 396 # This test uses exit-descriptors. Use EBP for setting up local variables. - 397 55/push-EBP - 398 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 399 # clear all streams - 400 # . clear-stream(_test-stream) - 401 # . . push args - 402 68/push _test-stream/imm32 - 403 # . . call - 404 e8/call clear-stream/disp32 - 405 # . . discard args - 406 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 407 # . clear-stream(_test-buffered-file+4) - 408 # . . push args - 409 b8/copy-to-EAX _test-buffered-file/imm32 - 410 05/add-to-EAX 4/imm32 - 411 50/push-EAX - 412 # . . call - 413 e8/call clear-stream/disp32 - 414 # . . discard args - 415 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 416 # . clear-stream(_test-error-stream) - 417 # . . push args - 418 68/push _test-error-stream/imm32 - 419 # . . call - 420 e8/call clear-stream/disp32 - 421 # . . discard args - 422 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 423 # . clear-stream(_test-error-buffered-file+4) - 424 # . . push args - 425 b8/copy-to-EAX _test-error-buffered-file/imm32 - 426 05/add-to-EAX 4/imm32 - 427 50/push-EAX - 428 # . . call - 429 e8/call clear-stream/disp32 - 430 # . . discard args - 431 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 432 # initialize '_test-stream' to "a" - 433 # . write(_test-stream, "a") - 434 # . . push args - 435 68/push "a"/imm32 - 436 68/push _test-stream/imm32 - 437 # . . call - 438 e8/call write/disp32 - 439 # . . discard args - 440 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 441 # initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below - 442 # . var ed/ECX : exit-descriptor - 443 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 444 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 445 # . tailor-exit-descriptor(ed, 12) - 446 # . . push args - 447 68/push 0xc/imm32/nbytes-of-args-for-convert-next-octet - 448 51/push-ECX/ed - 449 # . . call - 450 e8/call tailor-exit-descriptor/disp32 - 451 # . . discard args - 452 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 453 # EAX = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed) - 454 # . . push args - 455 51/push-ECX/ed - 456 68/push _test-error-buffered-file/imm32 - 457 68/push _test-buffered-file/imm32 - 458 # . . call - 459 e8/call convert-next-octet/disp32 - 460 # registers except ESP may be clobbered at this point - 461 # pop args to convert-next-octet - 462 # . . discard first 2 args - 463 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 464 # . . restore ed - 465 59/pop-to-ECX - 466 # check that convert-next-octet aborted - 467 # . check-ints-equal(ed->value, 2, msg) - 468 # . . push args - 469 68/push "F - test-convert-next-octet-aborts-on-single-hex-byte: unexpected abort"/imm32 - 470 68/push 2/imm32 - 471 # . . push ed->value - 472 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) - 473 # . . call - 474 e8/call check-ints-equal/disp32 - 475 # . . discard args - 476 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 477 $test-convert-next-octet-aborts-on-single-hex-byte:end: - 478 # . epilog - 479 # don't restore ESP from EBP; manually reclaim locals - 480 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 481 5d/pop-to-EBP - 482 c3/return - 483 - 484 # read whitespace until a hex byte, and return it - 485 # return 0xffffffff if file ends without finding a hex byte - 486 # on '#' skip all bytes until newline - 487 # abort on any other byte - 488 scan-next-byte: # in : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> byte-or-eof/EAX - 489 # pseudocode: - 490 # repeatedly - 491 # EAX = read-byte(in) - 492 # if (EAX == 0xffffffff) return EAX - 493 # if (is-hex-digit?(EAX)) return EAX - 494 # if (EAX == ' ' or '\t' or '\n') continue - 495 # if (EAX == '#') skip-until-newline(in) - 496 # else error-byte(ed, err, "invalid byte: " EAX) - 497 # - 498 # . prolog - 499 55/push-EBP - 500 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 501 # . save registers - 502 $scan-next-byte:loop: - 503 # EAX = read-byte(in) - 504 # . . push args - 505 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 506 # . . call - 507 e8/call read-byte/disp32 - 508 # . . discard args - 509 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 510 # if (EAX == 0xffffffff) return EAX - 511 3d/compare-with-EAX 0xffffffff/imm32 - 512 74/jump-if-equal $scan-next-byte:end/disp8 - 513 # if (is-hex-digit?(EAX)) return EAX - 514 # . save EAX for now - 515 50/push-EAX - 516 # . is-hex-digit?(EAX) - 517 # . . push args - 518 50/push-EAX - 519 # . . call - 520 e8/call is-hex-digit?/disp32 - 521 # . . discard args - 522 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 523 # . compare with 'false' - 524 3d/compare-with-EAX 0/imm32 - 525 # . restore EAX (does not affect flags) - 526 58/pop-to-EAX - 527 # . check whether to return - 528 75/jump-if-not-equal $scan-next-byte:end/disp8 - 529 $scan-next-byte:check1: - 530 # if (EAX == ' ') continue - 531 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0x20/imm32 # compare EAX - 532 74/jump-if-equal $scan-next-byte:loop/disp8 - 533 # if (EAX == '\t') continue - 534 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0x9/imm32 # compare EAX - 535 74/jump-if-equal $scan-next-byte:loop/disp8 - 536 # if (EAX == '\n') continue - 537 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xa/imm32 # compare EAX - 538 74/jump-if-equal $scan-next-byte:loop/disp8 - 539 $scan-next-byte:check2: - 540 # if (EAX == '#') skip-until-newline(in) - 541 3d/compare-with-EAX 0x23/imm32 - 542 75/jump-if-not-equal $scan-next-byte:check3/disp8 - 543 # . skip-until-newline(in) - 544 # . . push args - 545 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 546 # . . call - 547 e8/call skip-until-newline/disp32 - 548 # . . discard args - 549 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 550 eb/jump $scan-next-byte:loop/disp8 - 551 $scan-next-byte:check3: - 552 # otherwise error-byte(ed, err, msg, EAX) - 553 # . . push args - 554 50/push-EAX - 555 68/push "scan-next-byte: invalid byte"/imm32 - 556 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 557 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) - 558 # . . call - 559 e8/call error-byte/disp32 # never returns - 560 $scan-next-byte:end: - 561 # . restore registers - 562 # . epilog - 563 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 564 5d/pop-to-EBP - 565 c3/return - 566 - 567 test-scan-next-byte: - 568 # - check that the first byte of the input is returned - 569 # This test uses exit-descriptors. Use EBP for setting up local variables. - 570 55/push-EBP - 571 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 572 # clear all streams - 573 # . clear-stream(_test-stream) - 574 # . . push args - 575 68/push _test-stream/imm32 - 576 # . . call - 577 e8/call clear-stream/disp32 - 578 # . . discard args - 579 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 580 # . clear-stream(_test-buffered-file+4) - 581 # . . push args - 582 b8/copy-to-EAX _test-buffered-file/imm32 - 583 05/add-to-EAX 4/imm32 - 584 50/push-EAX - 585 # . . call - 586 e8/call clear-stream/disp32 - 587 # . . discard args - 588 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 589 # . clear-stream(_test-error-stream) - 590 # . . push args - 591 68/push _test-error-stream/imm32 - 592 # . . call - 593 e8/call clear-stream/disp32 - 594 # . . discard args - 595 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 596 # . clear-stream(_test-error-buffered-file+4) - 597 # . . push args - 598 b8/copy-to-EAX _test-error-buffered-file/imm32 - 599 05/add-to-EAX 4/imm32 - 600 50/push-EAX - 601 # . . call - 602 e8/call clear-stream/disp32 - 603 # . . discard args - 604 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 605 # initialize '_test-stream' to "abc" - 606 # . write(_test-stream, "abc") - 607 # . . push args - 608 68/push "abc"/imm32 - 609 68/push _test-stream/imm32 - 610 # . . call - 611 e8/call write/disp32 - 612 # . . discard args - 613 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 614 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below - 615 # . var ed/ECX : exit-descriptor - 616 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 617 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 618 # . tailor-exit-descriptor(ed, 12) - 619 # . . push args - 620 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte - 621 51/push-ECX/ed - 622 # . . call - 623 e8/call tailor-exit-descriptor/disp32 - 624 # . . discard args - 625 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 626 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) - 627 # . . push args - 628 51/push-ECX/ed - 629 68/push _test-error-buffered-file/imm32 - 630 68/push _test-buffered-file/imm32 - 631 # . . call - 632 e8/call scan-next-byte/disp32 - 633 # registers except ESP may be clobbered at this point - 634 # pop args to scan-next-byte - 635 # . . discard first 2 args - 636 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 637 # . . restore ed - 638 59/pop-to-ECX - 639 # check that scan-next-byte didn't abort - 640 # . check-ints-equal(ed->value, 0, msg) - 641 # . . push args - 642 68/push "F - test-scan-next-byte: unexpected abort"/imm32 - 643 68/push 0/imm32 - 644 # . . push ed->value - 645 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) - 646 # . . call - 647 e8/call check-ints-equal/disp32 - 648 # . . discard args - 649 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 650 # return if abort - 651 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) - 652 75/jump-if-not-equal $test-scan-next-byte:end/disp8 - 653 # check-ints-equal(EAX, 0x61/a, msg) - 654 # . . push args - 655 68/push "F - test-scan-next-byte"/imm32 - 656 68/push 0x61/imm32/a - 657 50/push-EAX - 658 # . . call - 659 e8/call check-ints-equal/disp32 - 660 # . . discard args - 661 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 662 $test-scan-next-byte:end: - 663 # . epilog - 664 # don't restore ESP from EBP; manually reclaim locals - 665 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 666 5d/pop-to-EBP - 667 c3/return - 668 - 669 test-scan-next-byte-skips-whitespace: - 670 # - check that the first byte after whitespace is returned - 671 # This test uses exit-descriptors. Use EBP for setting up local variables. - 672 55/push-EBP - 673 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 674 # clear all streams - 675 # . clear-stream(_test-stream) - 676 # . . push args - 677 68/push _test-stream/imm32 - 678 # . . call - 679 e8/call clear-stream/disp32 - 680 # . . discard args - 681 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 682 # . clear-stream(_test-buffered-file+4) - 683 # . . push args - 684 b8/copy-to-EAX _test-buffered-file/imm32 - 685 05/add-to-EAX 4/imm32 - 686 50/push-EAX - 687 # . . call - 688 e8/call clear-stream/disp32 - 689 # . . discard args - 690 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 691 # . clear-stream(_test-error-stream) - 692 # . . push args - 693 68/push _test-error-stream/imm32 - 694 # . . call - 695 e8/call clear-stream/disp32 - 696 # . . discard args - 697 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 698 # . clear-stream(_test-error-buffered-file+4) - 699 # . . push args - 700 b8/copy-to-EAX _test-error-buffered-file/imm32 - 701 05/add-to-EAX 4/imm32 - 702 50/push-EAX - 703 # . . call - 704 e8/call clear-stream/disp32 - 705 # . . discard args - 706 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 707 # initialize '_test-stream' to input with leading whitespace - 708 # . write(_test-stream, text) - 709 # . . push args - 710 68/push " abc"/imm32 - 711 68/push _test-stream/imm32 - 712 # . . call - 713 e8/call write/disp32 - 714 # . . discard args - 715 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 716 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below - 717 # . var ed/ECX : exit-descriptor - 718 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 719 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 720 # . tailor-exit-descriptor(ed, 12) - 721 # . . push args - 722 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte - 723 51/push-ECX/ed - 724 # . . call - 725 e8/call tailor-exit-descriptor/disp32 - 726 # . . discard args - 727 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 728 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) - 729 # . . push args - 730 51/push-ECX/ed - 731 68/push _test-error-buffered-file/imm32 - 732 68/push _test-buffered-file/imm32 - 733 # . . call - 734 e8/call scan-next-byte/disp32 - 735 # registers except ESP may be clobbered at this point - 736 # pop args to scan-next-byte - 737 # . . discard first 2 args - 738 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 739 # . . restore ed - 740 59/pop-to-ECX - 741 # check that scan-next-byte didn't abort - 742 # . check-ints-equal(ed->value, 0, msg) - 743 # . . push args - 744 68/push "F - test-scan-next-byte-skips-whitespace: unexpected abort"/imm32 - 745 68/push 0/imm32 - 746 # . . push ed->value - 747 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) - 748 # . . call - 749 e8/call check-ints-equal/disp32 - 750 # . . discard args - 751 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 752 # return if abort - 753 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) - 754 75/jump-if-not-equal $test-scan-next-byte-skips-whitespace:end/disp8 - 755 # check-ints-equal(EAX, 0x61/a, msg) - 756 # . . push args - 757 68/push "F - test-scan-next-byte-skips-whitespace"/imm32 - 758 68/push 0x61/imm32/a - 759 50/push-EAX - 760 # . . call - 761 e8/call check-ints-equal/disp32 - 762 # . . discard args - 763 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 764 $test-scan-next-byte-skips-whitespace:end: - 765 # . epilog - 766 # don't restore ESP from EBP; manually reclaim locals - 767 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 768 5d/pop-to-EBP - 769 c3/return - 770 - 771 test-scan-next-byte-skips-comment: - 772 # - check that the first byte after a comment (and newline) is returned - 773 # This test uses exit-descriptors. Use EBP for setting up local variables. - 774 55/push-EBP - 775 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 776 # clear all streams - 777 # . clear-stream(_test-stream) - 778 # . . push args - 779 68/push _test-stream/imm32 - 780 # . . call - 781 e8/call clear-stream/disp32 - 782 # . . discard args - 783 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 784 # . clear-stream(_test-buffered-file+4) - 785 # . . push args - 786 b8/copy-to-EAX _test-buffered-file/imm32 - 787 05/add-to-EAX 4/imm32 - 788 50/push-EAX - 789 # . . call - 790 e8/call clear-stream/disp32 - 791 # . . discard args - 792 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 793 # . clear-stream(_test-error-stream) - 794 # . . push args - 795 68/push _test-error-stream/imm32 - 796 # . . call - 797 e8/call clear-stream/disp32 - 798 # . . discard args - 799 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 800 # . clear-stream(_test-error-buffered-file+4) - 801 # . . push args - 802 b8/copy-to-EAX _test-error-buffered-file/imm32 - 803 05/add-to-EAX 4/imm32 - 804 50/push-EAX - 805 # . . call - 806 e8/call clear-stream/disp32 - 807 # . . discard args - 808 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 809 # initialize '_test-stream' to input with leading comment - 810 # . write(_test-stream, comment) - 811 # . . push args - 812 68/push "#x"/imm32 - 813 68/push _test-stream/imm32 - 814 # . . call - 815 e8/call write/disp32 - 816 # . . discard args - 817 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 818 # . write(_test-stream, Newline) - 819 # . . push args - 820 68/push Newline/imm32 - 821 68/push _test-stream/imm32 - 822 # . . call - 823 e8/call write/disp32 - 824 # . . discard args - 825 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 826 # . write(_test-stream, real text) - 827 # . . push args - 828 68/push "ab"/imm32 - 829 68/push _test-stream/imm32 - 830 # . . call - 831 e8/call write/disp32 - 832 # . . discard args - 833 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 834 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below - 835 # . var ed/ECX : exit-descriptor - 836 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 837 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 838 # . tailor-exit-descriptor(ed, 12) - 839 # . . push args - 840 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte - 841 51/push-ECX/ed - 842 # . . call - 843 e8/call tailor-exit-descriptor/disp32 - 844 # . . discard args - 845 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 846 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) - 847 # . . push args - 848 51/push-ECX/ed - 849 68/push _test-error-buffered-file/imm32 - 850 68/push _test-buffered-file/imm32 - 851 # . . call - 852 e8/call scan-next-byte/disp32 - 853 # registers except ESP may be clobbered at this point - 854 # pop args to scan-next-byte - 855 # . . discard first 2 args - 856 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 857 # . . restore ed - 858 59/pop-to-ECX - 859 # check that scan-next-byte didn't abort - 860 # . check-ints-equal(ed->value, 0, msg) - 861 # . . push args - 862 68/push "F - test-scan-next-byte-skips-comment: unexpected abort"/imm32 - 863 68/push 0/imm32 - 864 # . . push ed->value - 865 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) - 866 # . . call - 867 e8/call check-ints-equal/disp32 - 868 # . . discard args - 869 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 870 # return if abort - 871 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) - 872 75/jump-if-not-equal $test-scan-next-byte-skips-comment:end/disp8 - 873 # check-ints-equal(EAX, 0x61/a, msg) - 874 # . . push args - 875 68/push "F - test-scan-next-byte-skips-comment"/imm32 - 876 68/push 0x61/imm32/a - 877 50/push-EAX - 878 # . . call - 879 e8/call check-ints-equal/disp32 - 880 # . . discard args - 881 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 882 $test-scan-next-byte-skips-comment:end: - 883 # . epilog - 884 # don't restore ESP from EBP; manually reclaim locals - 885 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 886 5d/pop-to-EBP - 887 c3/return - 888 - 889 test-scan-next-byte-skips-comment-and-whitespace: - 890 # - check that the first byte after a comment and any further whitespace is returned - 891 # This test uses exit-descriptors. Use EBP for setting up local variables. - 892 55/push-EBP - 893 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 894 # clear all streams - 895 # . clear-stream(_test-stream) - 896 # . . push args - 897 68/push _test-stream/imm32 - 898 # . . call - 899 e8/call clear-stream/disp32 - 900 # . . discard args - 901 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 902 # . clear-stream(_test-buffered-file+4) - 903 # . . push args - 904 b8/copy-to-EAX _test-buffered-file/imm32 - 905 05/add-to-EAX 4/imm32 - 906 50/push-EAX - 907 # . . call - 908 e8/call clear-stream/disp32 - 909 # . . discard args - 910 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 911 # . clear-stream(_test-error-stream) - 912 # . . push args - 913 68/push _test-error-stream/imm32 - 914 # . . call - 915 e8/call clear-stream/disp32 - 916 # . . discard args - 917 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 918 # . clear-stream(_test-error-buffered-file+4) - 919 # . . push args - 920 b8/copy-to-EAX _test-error-buffered-file/imm32 - 921 05/add-to-EAX 4/imm32 - 922 50/push-EAX - 923 # . . call - 924 e8/call clear-stream/disp32 - 925 # . . discard args - 926 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 927 # initialize '_test-stream' to input with leading comment and more whitespace after newline - 928 # . write(_test-stream, comment) - 929 # . . push args - 930 68/push "#x"/imm32 - 931 68/push _test-stream/imm32 - 932 # . . call - 933 e8/call write/disp32 - 934 # . . discard args - 935 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 936 # . write(_test-stream, Newline) - 937 # . . push args - 938 68/push Newline/imm32 - 939 68/push _test-stream/imm32 - 940 # . . call - 941 e8/call write/disp32 - 942 # . . discard args - 943 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 944 # . write(_test-stream, real text) - 945 # . . push args - 946 68/push " ab"/imm32 - 947 68/push _test-stream/imm32 - 948 # . . call - 949 e8/call write/disp32 - 950 # . . discard args - 951 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 952 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below - 953 # . var ed/ECX : exit-descriptor - 954 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP - 955 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 956 # . tailor-exit-descriptor(ed, 12) - 957 # . . push args - 958 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte - 959 51/push-ECX/ed - 960 # . . call - 961 e8/call tailor-exit-descriptor/disp32 - 962 # . . discard args - 963 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 964 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) - 965 # . . push args - 966 51/push-ECX/ed - 967 68/push _test-error-buffered-file/imm32 - 968 68/push _test-buffered-file/imm32 - 969 # . . call - 970 e8/call scan-next-byte/disp32 - 971 # registers except ESP may be clobbered at this point - 972 # pop args to scan-next-byte - 973 # . . discard first 2 args - 974 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 975 # . . restore ed - 976 59/pop-to-ECX - 977 # check that scan-next-byte didn't abort - 978 # . check-ints-equal(ed->value, 0, msg) - 979 # . . push args - 980 68/push "F - test-scan-next-byte-skips-comment-and-whitespace: unexpected abort"/imm32 - 981 68/push 0/imm32 - 982 # . . push ed->value - 983 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) - 984 # . . call - 985 e8/call check-ints-equal/disp32 - 986 # . . discard args - 987 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 988 # return if abort - 989 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) - 990 75/jump-if-not-equal $test-scan-next-byte-skips-comment-and-whitespace:end/disp8 - 991 # check-ints-equal(EAX, 0x61/a, msg) - 992 # . . push args - 993 68/push "F - test-scan-next-byte-skips-comment-and-whitespace"/imm32 - 994 68/push 0x61/imm32/a - 995 50/push-EAX - 996 # . . call - 997 e8/call check-ints-equal/disp32 - 998 # . . discard args - 999 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1000 $test-scan-next-byte-skips-comment-and-whitespace:end: -1001 # . epilog -1002 # don't restore ESP from EBP; manually reclaim locals -1003 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1004 5d/pop-to-EBP -1005 c3/return -1006 -1007 test-scan-next-byte-skips-whitespace-and-comment: -1008 # - check that the first byte after any whitespace and comments is returned -1009 # This test uses exit-descriptors. Use EBP for setting up local variables. -1010 55/push-EBP -1011 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1012 # clear all streams -1013 # . clear-stream(_test-stream) -1014 # . . push args -1015 68/push _test-stream/imm32 -1016 # . . call -1017 e8/call clear-stream/disp32 -1018 # . . discard args -1019 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1020 # . clear-stream(_test-buffered-file+4) -1021 # . . push args -1022 b8/copy-to-EAX _test-buffered-file/imm32 -1023 05/add-to-EAX 4/imm32 -1024 50/push-EAX -1025 # . . call -1026 e8/call clear-stream/disp32 -1027 # . . discard args -1028 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1029 # . clear-stream(_test-error-stream) -1030 # . . push args -1031 68/push _test-error-stream/imm32 -1032 # . . call -1033 e8/call clear-stream/disp32 -1034 # . . discard args -1035 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1036 # . clear-stream(_test-error-buffered-file+4) -1037 # . . push args -1038 b8/copy-to-EAX _test-error-buffered-file/imm32 -1039 05/add-to-EAX 4/imm32 -1040 50/push-EAX -1041 # . . call -1042 e8/call clear-stream/disp32 -1043 # . . discard args -1044 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1045 # initialize '_test-stream' to input with leading whitespace and comment -1046 # . write(_test-stream, comment) -1047 # . . push args -1048 68/push " #x"/imm32 -1049 68/push _test-stream/imm32 -1050 # . . call -1051 e8/call write/disp32 -1052 # . . discard args -1053 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1054 # . write(_test-stream, Newline) -1055 # . . push args -1056 68/push Newline/imm32 -1057 68/push _test-stream/imm32 -1058 # . . call -1059 e8/call write/disp32 -1060 # . . discard args -1061 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1062 # . write(_test-stream, real text) -1063 # . . push args -1064 68/push "ab"/imm32 -1065 68/push _test-stream/imm32 -1066 # . . call -1067 e8/call write/disp32 -1068 # . . discard args -1069 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1070 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below -1071 # . var ed/ECX : exit-descriptor -1072 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP -1073 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1074 # . tailor-exit-descriptor(ed, 12) -1075 # . . push args -1076 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte -1077 51/push-ECX/ed -1078 # . . call -1079 e8/call tailor-exit-descriptor/disp32 -1080 # . . discard args -1081 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1082 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) -1083 # . . push args -1084 51/push-ECX/ed -1085 68/push _test-error-buffered-file/imm32 -1086 68/push _test-buffered-file/imm32 -1087 # . . call -1088 e8/call scan-next-byte/disp32 -1089 # registers except ESP may be clobbered at this point -1090 # pop args to scan-next-byte -1091 # . . discard first 2 args -1092 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1093 # . . restore ed -1094 59/pop-to-ECX -1095 # check that scan-next-byte didn't abort -1096 # . check-ints-equal(ed->value, 0, msg) -1097 # . . push args -1098 68/push "F - test-scan-next-byte-skips-whitespace-and-comment: unexpected abort"/imm32 -1099 68/push 0/imm32 -1100 # . . push ed->value -1101 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) -1102 # . . call -1103 e8/call check-ints-equal/disp32 -1104 # . . discard args -1105 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1106 # return if abort -1107 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) -1108 75/jump-if-not-equal $test-scan-next-byte-skips-whitespace-and-comment:end/disp8 -1109 # check-ints-equal(EAX, 0x61/a, msg) -1110 # . . push args -1111 68/push "F - test-scan-next-byte-skips-whitespace-and-comment"/imm32 -1112 68/push 0x61/imm32/a -1113 50/push-EAX -1114 # . . call -1115 e8/call check-ints-equal/disp32 -1116 # . . discard args -1117 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1118 $test-scan-next-byte-skips-whitespace-and-comment:end: -1119 # . epilog -1120 # don't restore ESP from EBP; manually reclaim locals -1121 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1122 5d/pop-to-EBP -1123 c3/return -1124 -1125 test-scan-next-byte-reads-final-byte: -1126 # - check that the final byte in input is returned -1127 # This test uses exit-descriptors. Use EBP for setting up local variables. -1128 55/push-EBP -1129 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1130 # clear all streams -1131 # . clear-stream(_test-stream) -1132 # . . push args -1133 68/push _test-stream/imm32 -1134 # . . call -1135 e8/call clear-stream/disp32 -1136 # . . discard args -1137 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1138 # . clear-stream(_test-buffered-file+4) -1139 # . . push args -1140 b8/copy-to-EAX _test-buffered-file/imm32 -1141 05/add-to-EAX 4/imm32 -1142 50/push-EAX -1143 # . . call -1144 e8/call clear-stream/disp32 -1145 # . . discard args -1146 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1147 # . clear-stream(_test-error-stream) -1148 # . . push args -1149 68/push _test-error-stream/imm32 -1150 # . . call -1151 e8/call clear-stream/disp32 -1152 # . . discard args -1153 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1154 # . clear-stream(_test-error-buffered-file+4) -1155 # . . push args -1156 b8/copy-to-EAX _test-error-buffered-file/imm32 -1157 05/add-to-EAX 4/imm32 -1158 50/push-EAX -1159 # . . call -1160 e8/call clear-stream/disp32 -1161 # . . discard args -1162 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1163 # initialize '_test-stream' to input with single character -1164 # . write(_test-stream, character) -1165 # . . push args -1166 68/push "a"/imm32 -1167 68/push _test-stream/imm32 -1168 # . . call -1169 e8/call write/disp32 -1170 # . . discard args -1171 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1172 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below -1173 # . var ed/ECX : exit-descriptor -1174 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP -1175 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1176 # . tailor-exit-descriptor(ed, 12) -1177 # . . push args -1178 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte -1179 51/push-ECX/ed -1180 # . . call -1181 e8/call tailor-exit-descriptor/disp32 -1182 # . . discard args -1183 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1184 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) -1185 # . . push args -1186 51/push-ECX/ed -1187 68/push _test-error-buffered-file/imm32 -1188 68/push _test-buffered-file/imm32 -1189 # . . call -1190 e8/call scan-next-byte/disp32 -1191 # registers except ESP may be clobbered at this point -1192 # pop args to scan-next-byte -1193 # . . discard first 2 args -1194 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1195 # . . restore ed -1196 59/pop-to-ECX -1197 # check that scan-next-byte didn't abort -1198 # . check-ints-equal(ed->value, 0, msg) -1199 # . . push args -1200 68/push "F - test-scan-next-byte-reads-final-byte: unexpected abort"/imm32 -1201 68/push 0/imm32 -1202 # . . push ed->value -1203 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) -1204 # . . call -1205 e8/call check-ints-equal/disp32 -1206 # . . discard args -1207 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1208 # return if abort -1209 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) -1210 75/jump-if-not-equal $test-scan-next-byte-reads-final-byte:end/disp8 -1211 # check-ints-equal(EAX, 0x61/a, msg) -1212 # . . push args -1213 68/push "F - test-scan-next-byte-reads-final-byte"/imm32 -1214 68/push 0x61/imm32/a -1215 50/push-EAX -1216 # . . call -1217 e8/call check-ints-equal/disp32 -1218 # . . discard args -1219 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1220 $test-scan-next-byte-reads-final-byte:end: -1221 # . epilog -1222 # don't restore ESP from EBP; manually reclaim locals -1223 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1224 5d/pop-to-EBP -1225 c3/return -1226 -1227 test-scan-next-byte-handles-eof: -1228 # - check that the right sentinel value is returned when there's no data remaining to be read -1229 # This test uses exit-descriptors. Use EBP for setting up local variables. -1230 55/push-EBP -1231 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1232 # clear all streams -1233 # . clear-stream(_test-stream) -1234 # . . push args -1235 68/push _test-stream/imm32 -1236 # . . call -1237 e8/call clear-stream/disp32 -1238 # . . discard args -1239 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1240 # . clear-stream(_test-buffered-file+4) -1241 # . . push args -1242 b8/copy-to-EAX _test-buffered-file/imm32 -1243 05/add-to-EAX 4/imm32 -1244 50/push-EAX -1245 # . . call -1246 e8/call clear-stream/disp32 -1247 # . . discard args -1248 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1249 # . clear-stream(_test-error-stream) -1250 # . . push args -1251 68/push _test-error-stream/imm32 -1252 # . . call -1253 e8/call clear-stream/disp32 -1254 # . . discard args -1255 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1256 # . clear-stream(_test-error-buffered-file+4) -1257 # . . push args -1258 b8/copy-to-EAX _test-error-buffered-file/imm32 -1259 05/add-to-EAX 4/imm32 -1260 50/push-EAX -1261 # . . call -1262 e8/call clear-stream/disp32 -1263 # . . discard args -1264 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1265 # leave '_test-stream' empty -1266 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below -1267 # . var ed/ECX : exit-descriptor -1268 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP -1269 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1270 # . tailor-exit-descriptor(ed, 12) -1271 # . . push args -1272 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte -1273 51/push-ECX/ed -1274 # . . call -1275 e8/call tailor-exit-descriptor/disp32 -1276 # . . discard args -1277 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1278 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) -1279 # . . push args -1280 51/push-ECX/ed -1281 68/push _test-error-buffered-file/imm32 -1282 68/push _test-buffered-file/imm32 -1283 # . . call -1284 e8/call scan-next-byte/disp32 -1285 # registers except ESP may be clobbered at this point -1286 # pop args to scan-next-byte -1287 # . . discard first 2 args -1288 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1289 # . . restore ed -1290 59/pop-to-ECX -1291 # check that scan-next-byte didn't abort -1292 # . check-ints-equal(ed->value, 0, msg) -1293 # . . push args -1294 68/push "F - test-scan-next-byte-handles-eof: unexpected abort"/imm32 -1295 68/push 0/imm32 -1296 # . . push ed->value -1297 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) -1298 # . . call -1299 e8/call check-ints-equal/disp32 -1300 # . . discard args -1301 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1302 # return if abort -1303 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) -1304 75/jump-if-not-equal $test-scan-next-byte-handles-eof:end/disp8 -1305 # check-ints-equal(EAX, 0xffffffff/eof, msg) -1306 # . . push args -1307 68/push "F - test-scan-next-byte-handles-eof"/imm32 -1308 68/push 0xffffffff/imm32/eof -1309 50/push-EAX -1310 # . . call -1311 e8/call check-ints-equal/disp32 -1312 # . . discard args -1313 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1314 $test-scan-next-byte-handles-eof:end: -1315 # . epilog -1316 # don't restore ESP from EBP; manually reclaim locals -1317 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1318 5d/pop-to-EBP -1319 c3/return -1320 -1321 test-scan-next-byte-aborts-on-invalid-byte: -1322 # - check that the a bad byte immediately aborts -1323 # This test uses exit-descriptors. Use EBP for setting up local variables. -1324 55/push-EBP -1325 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1326 # clear all streams -1327 # . clear-stream(_test-stream) -1328 # . . push args -1329 68/push _test-stream/imm32 -1330 # . . call -1331 e8/call clear-stream/disp32 -1332 # . . discard args -1333 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1334 # . clear-stream(_test-buffered-file+4) -1335 # . . push args -1336 b8/copy-to-EAX _test-buffered-file/imm32 -1337 05/add-to-EAX 4/imm32 -1338 50/push-EAX -1339 # . . call -1340 e8/call clear-stream/disp32 -1341 # . . discard args -1342 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1343 # . clear-stream(_test-error-stream) -1344 # . . push args -1345 68/push _test-error-stream/imm32 -1346 # . . call -1347 e8/call clear-stream/disp32 -1348 # . . discard args -1349 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1350 # . clear-stream(_test-error-buffered-file+4) -1351 # . . push args -1352 b8/copy-to-EAX _test-error-buffered-file/imm32 -1353 05/add-to-EAX 4/imm32 -1354 50/push-EAX -1355 # . . call -1356 e8/call clear-stream/disp32 -1357 # . . discard args -1358 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1359 # initialize '_test-stream' to "x" -1360 # . write(_test-stream, "x") -1361 # . . push args -1362 68/push "x"/imm32 -1363 68/push _test-stream/imm32 -1364 # . . call -1365 e8/call write/disp32 -1366 # . . discard args -1367 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1368 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below -1369 # . var ed/ECX : exit-descriptor -1370 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP -1371 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1372 # . tailor-exit-descriptor(ed, 12) -1373 # . . push args -1374 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte -1375 51/push-ECX/ed -1376 # . . call -1377 e8/call tailor-exit-descriptor/disp32 -1378 # . . discard args -1379 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1380 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) -1381 # . . push args -1382 51/push-ECX/ed -1383 68/push _test-error-buffered-file/imm32 -1384 68/push _test-buffered-file/imm32 -1385 # . . call -1386 e8/call scan-next-byte/disp32 -1387 # registers except ESP may be clobbered at this point -1388 # pop args to scan-next-byte -1389 # . . discard first 2 args -1390 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1391 # . . restore ed -1392 59/pop-to-ECX -1393 # check that scan-next-byte aborted -1394 # . check-ints-equal(ed->value, 2, msg) -1395 # . . push args -1396 68/push "F - test-scan-next-byte-aborts-on-invalid-byte"/imm32 -1397 68/push 2/imm32 -1398 # . . push ed->value -1399 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) -1400 # . . call -1401 e8/call check-ints-equal/disp32 -1402 # . . discard args -1403 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1404 $test-scan-next-byte-aborts-on-invalid-byte:end: -1405 # . epilog -1406 # don't restore ESP from EBP; manually reclaim locals -1407 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1408 5d/pop-to-EBP -1409 c3/return -1410 -1411 skip-until-newline: # in : (address buffered-file) -> <void> -1412 # pseudocode: -1413 # push EAX -1414 # repeatedly: -1415 # EAX = read-byte(in) -1416 # if (EAX == 0xffffffff) break -1417 # if (EAX == 0x0a) break -1418 # pop EAX -1419 # . prolog -1420 55/push-EBP -1421 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1422 # . save registers -1423 50/push-EAX -1424 $skip-until-newline:loop: -1425 # . EAX = read-byte(in) -1426 # . . push args -1427 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -1428 # . . call -1429 e8/call read-byte/disp32 -1430 # . . discard args -1431 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1432 # . if (EAX == 0xffffffff) break -1433 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX -1434 74/jump-if-equal $skip-until-newline:end/disp8 -1435 # . if (EAX != 0xa/newline) loop -1436 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xa/imm32 # compare EAX -1437 75/jump-if-not-equal $skip-until-newline:loop/disp8 -1438 $skip-until-newline:end: -1439 # . restore registers -1440 58/pop-to-EAX -1441 # . epilog -1442 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1443 5d/pop-to-EBP -1444 c3/return -1445 -1446 test-skip-until-newline: -1447 # - check that the read pointer points after the newline -1448 # setup -1449 # . clear-stream(_test-stream) -1450 # . . push args -1451 68/push _test-stream/imm32 -1452 # . . call -1453 e8/call clear-stream/disp32 -1454 # . . discard args -1455 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1456 # . clear-stream(_test-buffered-file+4) -1457 # . . push args -1458 b8/copy-to-EAX _test-buffered-file/imm32 -1459 05/add-to-EAX 4/imm32 -1460 50/push-EAX -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 # initialize '_test-stream' to "abc\nde" -1466 # . write(_test-stream, "abc") -1467 # . . push args -1468 68/push "abc"/imm32 -1469 68/push _test-stream/imm32 -1470 # . . call -1471 e8/call write/disp32 -1472 # . . discard args -1473 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1474 # . write(_test-stream, Newline) -1475 # . . push args -1476 68/push Newline/imm32 -1477 68/push _test-stream/imm32 -1478 # . . call -1479 e8/call write/disp32 -1480 # . . discard args -1481 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1482 # . write(_test-stream, "de") -1483 # . . push args -1484 68/push "de"/imm32 -1485 68/push _test-stream/imm32 -1486 # . . call -1487 e8/call write/disp32 -1488 # . . discard args -1489 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1490 # skip-until-newline(_test-buffered-file) -1491 # . . push args -1492 68/push _test-buffered-file/imm32 -1493 # . . call -1494 e8/call skip-until-newline/disp32 -1495 # . . discard args -1496 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1497 # check-ints-equal(_test-buffered-file->read, 4, msg) -1498 # . . push args -1499 68/push "F - test-skip-until-newline"/imm32 -1500 68/push 4/imm32 -1501 b8/copy-to-EAX _test-buffered-file/imm32 -1502 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 8/disp8 . # push *(EAX+8) -1503 # . . call -1504 e8/call check-ints-equal/disp32 -1505 # . . discard args -1506 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1507 # . end -1508 c3/return -1509 -1510 == data -1511 -1512 _test-error-stream: -1513 # current write index -1514 00 00 00 00 -1515 # current read index -1516 00 00 00 00 -1517 # length (= 8) -1518 08 00 00 00 -1519 # data -1520 00 00 00 00 00 00 00 00 # 8 bytes -1521 -1522 # a test buffered file for _test-stream -1523 _test-error-buffered-file: -1524 # file descriptor or (address stream) -1525 _test-error-stream/imm32 -1526 # current write index -1527 00 00 00 00 -1528 # current read index -1529 00 00 00 00 -1530 # length (6) -1531 06 00 00 00 -1532 # data -1533 00 00 00 00 00 00 # 6 bytes -1534 -1535 # . . vim:nowrap:textwidth=0 + 20 Entry: # run tests if necessary, convert stdin if not + 21 + 22 #? # for debugging: run a single test + 23 #? e8/call test-skip-until-newline/disp32 + 24 #? 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX + 25 #? eb/jump $main:end/disp8 + 26 + 27 # . prolog + 28 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 29 # - if argc > 1 and argv[1] == "test", then return run_tests() + 30 # . argc > 1 + 31 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 0/disp8 1/imm32 # compare *EBP + 32 7e/jump-if-lesser-or-equal $run-main/disp8 + 33 # . argv[1] == "test" + 34 # . . push args + 35 68/push "test"/imm32 + 36 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 37 # . . call + 38 e8/call kernel-string-equal?/disp32 + 39 # . . discard args + 40 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 41 # . check result + 42 3d/compare-EAX 1/imm32 + 43 75/jump-if-not-equal $run-main/disp8 + 44 # . run-tests() + 45 e8/call run-tests/disp32 + 46 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX + 47 eb/jump $main:end/disp8 + 48 $run-main: + 49 # - otherwise convert stdin + 50 # var ed/EAX : exit-descriptor + 51 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 52 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX + 53 # configure ed to really exit() + 54 # . ed->target = 0 + 55 c7 0/subop/copy 0/mod/direct 0/rm32/EAX . . . . . 0/imm32 # copy to *EAX + 56 # return convert(Stdin, 1/stdout, 2/stderr, ed) + 57 # . . push args + 58 50/push-EAX/ed + 59 68/push Stderr/imm32 + 60 68/push Stdout/imm32 + 61 68/push Stdin/imm32 + 62 # . . call + 63 e8/call convert/disp32 + 64 # . . discard args + 65 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP + 66 # . syscall(exit, 0) + 67 bb/copy-to-EBX 0/imm32 + 68 $main:end: + 69 b8/copy-to-EAX 1/imm32/exit + 70 cd/syscall 0x80/imm8 + 71 + 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 + 76 # EAX = convert-next-octet(in, err, ed) + 77 # if (EAX == 0xffffffff) break # eof + 78 # write-byte(out, AL) + 79 # flush(out) + 80 # + 81 # . prolog + 82 55/push-EBP + 83 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 84 # . save registers + 85 50/push-EAX + 86 $convert:loop: + 87 # EAX = convert-next-octet(in, err, ed) + 88 # . . push args + 89 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x14/disp8 . # push *(EBP+20) + 90 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 91 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 92 # . . call + 93 e8/call convert-next-octet/disp32 + 94 # . . discard first 2 args + 95 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 96 # if (EAX == 0xffffffff) break + 97 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX + 98 74/jump-if-equal $convert:loop-end/disp8 + 99 # write-byte(out, AL) + 100 # . . push args + 101 50/push-EAX + 102 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 103 # . . call + 104 e8/call write-byte/disp32 + 105 # . . discard args + 106 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 107 # loop + 108 eb/jump $convert:loop/disp8 + 109 $convert:loop-end: + 110 # flush(out) + 111 # . . push args + 112 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 113 # . . call + 114 e8/call flush/disp32 + 115 # . . discard args + 116 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 117 $convert:end: + 118 # . restore registers + 119 58/pop-to-EAX + 120 # . epilog + 121 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 122 5d/pop-to-EBP + 123 c3/return + 124 + 125 # read bytes from 'in' until a sequence of two lowercase hex (0-9, a-f) bytes + 126 # skip spaces and newlines + 127 # on '#' skip bytes until newline + 128 # raise an error and abort on all other unexpected bytes + 129 # return in EAX an _octet_ containing the binary value of the two hex characters + 130 # return 0xffffffff on end of file + 131 convert-next-octet: # in : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> byte-or-eof/EAX + 132 # pseudocode: + 133 # EAX = scan-next-byte(in, err, ed) + 134 # if (EAX == 0xffffffff) return + 135 # ECX = from-hex-char(EAX) + 136 # EAX = scan-next-byte(in, err, ed) + 137 # if (EAX == 0xffffffff) error("partial byte found.") + 138 # EAX = from-hex-char(EAX) + 139 # EAX = (ECX << 4) | EAX + 140 # return + 141 # + 142 # . prolog + 143 55/push-EBP + 144 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 145 # . save registers + 146 51/push-ECX + 147 # EAX = scan-next-byte(in, err, ed) + 148 # . . push args + 149 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 150 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 151 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 152 # . . call + 153 e8/call scan-next-byte/disp32 + 154 # . . discard args + 155 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 156 # if (EAX == 0xffffffff) return + 157 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX + 158 74/jump-if-equal $convert-next-octet:end/disp8 + 159 # EAX = from-hex-char(EAX) + 160 e8/call from-hex-char/disp32 + 161 # ECX = EAX + 162 89/copy 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # copy EAX to ECX + 163 # EAX = scan-next-byte(in, err, ed) + 164 # . . push args + 165 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 166 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 167 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 168 # . . call + 169 e8/call scan-next-byte/disp32 + 170 # . . discard args + 171 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 172 # if (EAX == 0xffffffff) error(ed, err, "partial byte found.") + 173 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX + 174 75/jump-if-not-equal $convert-next-octet:convert/disp8 + 175 # . error-byte(ed, err, msg, '.') # reusing error-byte to avoid creating _yet_ another helper + 176 # . . push args + 177 68/push 0x2e/imm32/period/dummy + 178 68/push "convert-next-octet: partial byte found"/imm32 + 179 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 180 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 181 # . . call + 182 e8/call error-byte/disp32 # never returns + 183 $convert-next-octet:convert: + 184 # EAX = from-hex-char(EAX) + 185 e8/call from-hex-char/disp32 + 186 # EAX = (ECX << 4) | EAX + 187 # . ECX <<= 4 + 188 c1/shift 4/subop/left 3/mod/direct 1/rm32/ECX . . . . . 4/imm8 # shift ECX left by 4 bits + 189 # . EAX |= ECX + 190 09/or 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # EAX = bitwise OR with ECX + 191 $convert-next-octet:end: + 192 # . restore registers + 193 59/pop-to-ECX + 194 # . epilog + 195 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 196 5d/pop-to-EBP + 197 c3/return + 198 + 199 test-convert-next-octet: + 200 # - check that the first two bytes of the input are assembled into the resulting octet + 201 # This test uses exit-descriptors. Use EBP for setting up local variables. + 202 55/push-EBP + 203 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 204 # clear all streams + 205 # . clear-stream(_test-stream) + 206 # . . push args + 207 68/push _test-stream/imm32 + 208 # . . call + 209 e8/call clear-stream/disp32 + 210 # . . discard args + 211 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 212 # . clear-stream(_test-buffered-file+4) + 213 # . . push args + 214 b8/copy-to-EAX _test-buffered-file/imm32 + 215 05/add-to-EAX 4/imm32 + 216 50/push-EAX + 217 # . . call + 218 e8/call clear-stream/disp32 + 219 # . . discard args + 220 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 221 # . clear-stream(_test-error-stream) + 222 # . . push args + 223 68/push _test-error-stream/imm32 + 224 # . . call + 225 e8/call clear-stream/disp32 + 226 # . . discard args + 227 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 228 # . clear-stream(_test-error-buffered-file+4) + 229 # . . push args + 230 b8/copy-to-EAX _test-error-buffered-file/imm32 + 231 05/add-to-EAX 4/imm32 + 232 50/push-EAX + 233 # . . call + 234 e8/call clear-stream/disp32 + 235 # . . discard args + 236 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 237 # initialize '_test-stream' to "abc" + 238 # . write(_test-stream, "abc") + 239 # . . push args + 240 68/push "abc"/imm32 + 241 68/push _test-stream/imm32 + 242 # . . call + 243 e8/call write/disp32 + 244 # . . discard args + 245 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 246 # initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below + 247 # . var ed/ECX : exit-descriptor + 248 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 249 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 250 # . tailor-exit-descriptor(ed, 12) + 251 # . . push args + 252 68/push 0xc/imm32/nbytes-of-args-for-convert-next-octet + 253 51/push-ECX/ed + 254 # . . call + 255 e8/call tailor-exit-descriptor/disp32 + 256 # . . discard args + 257 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 258 # EAX = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed) + 259 # . . push args + 260 51/push-ECX/ed + 261 68/push _test-error-buffered-file/imm32 + 262 68/push _test-buffered-file/imm32 + 263 # . . call + 264 e8/call convert-next-octet/disp32 + 265 # registers except ESP may be clobbered at this point + 266 # pop args to convert-next-octet + 267 # . . discard first 2 args + 268 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 269 # . . restore ed + 270 59/pop-to-ECX + 271 # check that convert-next-octet didn't abort + 272 # . check-ints-equal(ed->value, 0, msg) + 273 # . . push args + 274 68/push "F - test-convert-next-octet: unexpected abort"/imm32 + 275 68/push 0/imm32 + 276 # . . push ed->value + 277 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) + 278 # . . call + 279 e8/call check-ints-equal/disp32 + 280 # . . discard args + 281 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 282 # return if abort + 283 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) + 284 75/jump-if-not-equal $test-convert-next-octet:end/disp8 + 285 # check-ints-equal(EAX, 0xab, msg) + 286 # . . push args + 287 68/push "F - test-convert-next-octet"/imm32 + 288 68/push 0xab/imm32/ab + 289 50/push-EAX + 290 # . . call + 291 e8/call check-ints-equal/disp32 + 292 # . . discard args + 293 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 294 $test-convert-next-octet:end: + 295 # . epilog + 296 # don't restore ESP from EBP; manually reclaim locals + 297 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 298 5d/pop-to-EBP + 299 c3/return + 300 + 301 test-convert-next-octet-handles-eof: + 302 # - check that eof returns the sentinel octet + 303 # This test uses exit-descriptors. Use EBP for setting up local variables. + 304 55/push-EBP + 305 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 306 # clear all streams + 307 # . clear-stream(_test-stream) + 308 # . . push args + 309 68/push _test-stream/imm32 + 310 # . . call + 311 e8/call clear-stream/disp32 + 312 # . . discard args + 313 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 314 # . clear-stream(_test-buffered-file+4) + 315 # . . push args + 316 b8/copy-to-EAX _test-buffered-file/imm32 + 317 05/add-to-EAX 4/imm32 + 318 50/push-EAX + 319 # . . call + 320 e8/call clear-stream/disp32 + 321 # . . discard args + 322 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 323 # . clear-stream(_test-error-stream) + 324 # . . push args + 325 68/push _test-error-stream/imm32 + 326 # . . call + 327 e8/call clear-stream/disp32 + 328 # . . discard args + 329 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 330 # . clear-stream(_test-error-buffered-file+4) + 331 # . . push args + 332 b8/copy-to-EAX _test-error-buffered-file/imm32 + 333 05/add-to-EAX 4/imm32 + 334 50/push-EAX + 335 # . . call + 336 e8/call clear-stream/disp32 + 337 # . . discard args + 338 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 339 # don't initialize '_test-stream' + 340 # initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below + 341 # . var ed/ECX : exit-descriptor + 342 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 343 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 344 # . tailor-exit-descriptor(ed, 12) + 345 # . . push args + 346 68/push 0xc/imm32/nbytes-of-args-for-convert-next-octet + 347 51/push-ECX/ed + 348 # . . call + 349 e8/call tailor-exit-descriptor/disp32 + 350 # . . discard args + 351 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 352 # EAX = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed) + 353 # . . push args + 354 51/push-ECX/ed + 355 68/push _test-error-buffered-file/imm32 + 356 68/push _test-buffered-file/imm32 + 357 # . . call + 358 e8/call convert-next-octet/disp32 + 359 # registers except ESP may be clobbered at this point + 360 # pop args to convert-next-octet + 361 # . . discard first 2 args + 362 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 363 # . . restore ed + 364 59/pop-to-ECX + 365 # check that convert-next-octet didn't abort + 366 # . check-ints-equal(ed->value, 0, msg) + 367 # . . push args + 368 68/push "F - test-convert-next-octet: unexpected abort"/imm32 + 369 68/push 0/imm32 + 370 # . . push ed->value + 371 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) + 372 # . . call + 373 e8/call check-ints-equal/disp32 + 374 # . . discard args + 375 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 376 # return if abort + 377 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) + 378 75/jump-if-not-equal $test-convert-next-octet-handles-eof:end/disp8 + 379 # check-ints-equal(EAX, 0xffffffff, msg) + 380 # . . push args + 381 68/push "F - test-convert-next-octet-handles-eof"/imm32 + 382 68/push 0xffffffff/imm32/eof + 383 50/push-EAX + 384 # . . call + 385 e8/call check-ints-equal/disp32 + 386 # . . discard args + 387 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 388 $test-convert-next-octet-handles-eof:end: + 389 # . epilog + 390 # don't restore ESP from EBP; manually reclaim locals + 391 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 392 5d/pop-to-EBP + 393 c3/return + 394 + 395 test-convert-next-octet-aborts-on-single-hex-byte: + 396 # - check that a single unaccompanied hex byte aborts + 397 # This test uses exit-descriptors. Use EBP for setting up local variables. + 398 55/push-EBP + 399 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 400 # clear all streams + 401 # . clear-stream(_test-stream) + 402 # . . push args + 403 68/push _test-stream/imm32 + 404 # . . call + 405 e8/call clear-stream/disp32 + 406 # . . discard args + 407 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 408 # . clear-stream(_test-buffered-file+4) + 409 # . . push args + 410 b8/copy-to-EAX _test-buffered-file/imm32 + 411 05/add-to-EAX 4/imm32 + 412 50/push-EAX + 413 # . . call + 414 e8/call clear-stream/disp32 + 415 # . . discard args + 416 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 417 # . clear-stream(_test-error-stream) + 418 # . . push args + 419 68/push _test-error-stream/imm32 + 420 # . . call + 421 e8/call clear-stream/disp32 + 422 # . . discard args + 423 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 424 # . clear-stream(_test-error-buffered-file+4) + 425 # . . push args + 426 b8/copy-to-EAX _test-error-buffered-file/imm32 + 427 05/add-to-EAX 4/imm32 + 428 50/push-EAX + 429 # . . call + 430 e8/call clear-stream/disp32 + 431 # . . discard args + 432 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 433 # initialize '_test-stream' to "a" + 434 # . write(_test-stream, "a") + 435 # . . push args + 436 68/push "a"/imm32 + 437 68/push _test-stream/imm32 + 438 # . . call + 439 e8/call write/disp32 + 440 # . . discard args + 441 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 442 # initialize exit-descriptor 'ed' for the call to 'convert-next-octet' below + 443 # . var ed/ECX : exit-descriptor + 444 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 445 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 446 # . tailor-exit-descriptor(ed, 12) + 447 # . . push args + 448 68/push 0xc/imm32/nbytes-of-args-for-convert-next-octet + 449 51/push-ECX/ed + 450 # . . call + 451 e8/call tailor-exit-descriptor/disp32 + 452 # . . discard args + 453 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 454 # EAX = convert-next-octet(_test-buffered-file, _test-error-buffered-file, ed) + 455 # . . push args + 456 51/push-ECX/ed + 457 68/push _test-error-buffered-file/imm32 + 458 68/push _test-buffered-file/imm32 + 459 # . . call + 460 e8/call convert-next-octet/disp32 + 461 # registers except ESP may be clobbered at this point + 462 # pop args to convert-next-octet + 463 # . . discard first 2 args + 464 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 465 # . . restore ed + 466 59/pop-to-ECX + 467 # check that convert-next-octet aborted + 468 # . check-ints-equal(ed->value, 2, msg) + 469 # . . push args + 470 68/push "F - test-convert-next-octet-aborts-on-single-hex-byte: unexpected abort"/imm32 + 471 68/push 2/imm32 + 472 # . . push ed->value + 473 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) + 474 # . . call + 475 e8/call check-ints-equal/disp32 + 476 # . . discard args + 477 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 478 $test-convert-next-octet-aborts-on-single-hex-byte:end: + 479 # . epilog + 480 # don't restore ESP from EBP; manually reclaim locals + 481 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 482 5d/pop-to-EBP + 483 c3/return + 484 + 485 # read whitespace until a hex byte, and return it + 486 # return 0xffffffff if file ends without finding a hex byte + 487 # on '#' skip all bytes until newline + 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 + 492 # EAX = read-byte(in) + 493 # if (EAX == 0xffffffff) return EAX + 494 # if (is-hex-digit?(EAX)) return EAX + 495 # if (EAX == ' ' or '\t' or '\n') continue + 496 # if (EAX == '#') skip-until-newline(in) + 497 # else error-byte(ed, err, "invalid byte: " EAX) + 498 # + 499 # . prolog + 500 55/push-EBP + 501 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 502 # . save registers + 503 $scan-next-byte:loop: + 504 # EAX = read-byte(in) + 505 # . . push args + 506 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 507 # . . call + 508 e8/call read-byte/disp32 + 509 # . . discard args + 510 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 511 # if (EAX == 0xffffffff) return EAX + 512 3d/compare-with-EAX 0xffffffff/imm32 + 513 74/jump-if-equal $scan-next-byte:end/disp8 + 514 # if (is-hex-digit?(EAX)) return EAX + 515 # . save EAX for now + 516 50/push-EAX + 517 # . is-hex-digit?(EAX) + 518 # . . push args + 519 50/push-EAX + 520 # . . call + 521 e8/call is-hex-digit?/disp32 + 522 # . . discard args + 523 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 524 # . compare with 'false' + 525 3d/compare-with-EAX 0/imm32 + 526 # . restore EAX (does not affect flags) + 527 58/pop-to-EAX + 528 # . check whether to return + 529 75/jump-if-not-equal $scan-next-byte:end/disp8 + 530 $scan-next-byte:check1: + 531 # if (EAX == ' ') continue + 532 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0x20/imm32 # compare EAX + 533 74/jump-if-equal $scan-next-byte:loop/disp8 + 534 # if (EAX == '\t') continue + 535 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0x9/imm32 # compare EAX + 536 74/jump-if-equal $scan-next-byte:loop/disp8 + 537 # if (EAX == '\n') continue + 538 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xa/imm32 # compare EAX + 539 74/jump-if-equal $scan-next-byte:loop/disp8 + 540 $scan-next-byte:check2: + 541 # if (EAX == '#') skip-until-newline(in) + 542 3d/compare-with-EAX 0x23/imm32 + 543 75/jump-if-not-equal $scan-next-byte:check3/disp8 + 544 # . skip-until-newline(in) + 545 # . . push args + 546 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 547 # . . call + 548 e8/call skip-until-newline/disp32 + 549 # . . discard args + 550 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 551 eb/jump $scan-next-byte:loop/disp8 + 552 $scan-next-byte:check3: + 553 # otherwise error-byte(ed, err, msg, EAX) + 554 # . . push args + 555 50/push-EAX + 556 68/push "scan-next-byte: invalid byte"/imm32 + 557 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 558 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 559 # . . call + 560 e8/call error-byte/disp32 # never returns + 561 $scan-next-byte:end: + 562 # . restore registers + 563 # . epilog + 564 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 565 5d/pop-to-EBP + 566 c3/return + 567 + 568 test-scan-next-byte: + 569 # - check that the first byte of the input is returned + 570 # This test uses exit-descriptors. Use EBP for setting up local variables. + 571 55/push-EBP + 572 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 573 # clear all streams + 574 # . clear-stream(_test-stream) + 575 # . . push args + 576 68/push _test-stream/imm32 + 577 # . . call + 578 e8/call clear-stream/disp32 + 579 # . . discard args + 580 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 581 # . clear-stream(_test-buffered-file+4) + 582 # . . push args + 583 b8/copy-to-EAX _test-buffered-file/imm32 + 584 05/add-to-EAX 4/imm32 + 585 50/push-EAX + 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-error-stream) + 591 # . . push args + 592 68/push _test-error-stream/imm32 + 593 # . . call + 594 e8/call clear-stream/disp32 + 595 # . . discard args + 596 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 597 # . clear-stream(_test-error-buffered-file+4) + 598 # . . push args + 599 b8/copy-to-EAX _test-error-buffered-file/imm32 + 600 05/add-to-EAX 4/imm32 + 601 50/push-EAX + 602 # . . call + 603 e8/call clear-stream/disp32 + 604 # . . discard args + 605 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 606 # initialize '_test-stream' to "abc" + 607 # . write(_test-stream, "abc") + 608 # . . push args + 609 68/push "abc"/imm32 + 610 68/push _test-stream/imm32 + 611 # . . call + 612 e8/call write/disp32 + 613 # . . discard args + 614 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 615 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below + 616 # . var ed/ECX : exit-descriptor + 617 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 618 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 619 # . tailor-exit-descriptor(ed, 12) + 620 # . . push args + 621 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte + 622 51/push-ECX/ed + 623 # . . call + 624 e8/call tailor-exit-descriptor/disp32 + 625 # . . discard args + 626 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 627 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) + 628 # . . push args + 629 51/push-ECX/ed + 630 68/push _test-error-buffered-file/imm32 + 631 68/push _test-buffered-file/imm32 + 632 # . . call + 633 e8/call scan-next-byte/disp32 + 634 # registers except ESP may be clobbered at this point + 635 # pop args to scan-next-byte + 636 # . . discard first 2 args + 637 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 638 # . . restore ed + 639 59/pop-to-ECX + 640 # check that scan-next-byte didn't abort + 641 # . check-ints-equal(ed->value, 0, msg) + 642 # . . push args + 643 68/push "F - test-scan-next-byte: unexpected abort"/imm32 + 644 68/push 0/imm32 + 645 # . . push ed->value + 646 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) + 647 # . . call + 648 e8/call check-ints-equal/disp32 + 649 # . . discard args + 650 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 651 # return if abort + 652 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) + 653 75/jump-if-not-equal $test-scan-next-byte:end/disp8 + 654 # check-ints-equal(EAX, 0x61/a, msg) + 655 # . . push args + 656 68/push "F - test-scan-next-byte"/imm32 + 657 68/push 0x61/imm32/a + 658 50/push-EAX + 659 # . . call + 660 e8/call check-ints-equal/disp32 + 661 # . . discard args + 662 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 663 $test-scan-next-byte:end: + 664 # . epilog + 665 # don't restore ESP from EBP; manually reclaim locals + 666 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 667 5d/pop-to-EBP + 668 c3/return + 669 + 670 test-scan-next-byte-skips-whitespace: + 671 # - check that the first byte after whitespace is returned + 672 # This test uses exit-descriptors. Use EBP for setting up local variables. + 673 55/push-EBP + 674 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 675 # clear all streams + 676 # . clear-stream(_test-stream) + 677 # . . push args + 678 68/push _test-stream/imm32 + 679 # . . call + 680 e8/call clear-stream/disp32 + 681 # . . discard args + 682 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 683 # . clear-stream(_test-buffered-file+4) + 684 # . . push args + 685 b8/copy-to-EAX _test-buffered-file/imm32 + 686 05/add-to-EAX 4/imm32 + 687 50/push-EAX + 688 # . . call + 689 e8/call clear-stream/disp32 + 690 # . . discard args + 691 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 692 # . clear-stream(_test-error-stream) + 693 # . . push args + 694 68/push _test-error-stream/imm32 + 695 # . . call + 696 e8/call clear-stream/disp32 + 697 # . . discard args + 698 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 699 # . clear-stream(_test-error-buffered-file+4) + 700 # . . push args + 701 b8/copy-to-EAX _test-error-buffered-file/imm32 + 702 05/add-to-EAX 4/imm32 + 703 50/push-EAX + 704 # . . call + 705 e8/call clear-stream/disp32 + 706 # . . discard args + 707 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 708 # initialize '_test-stream' to input with leading whitespace + 709 # . write(_test-stream, text) + 710 # . . push args + 711 68/push " abc"/imm32 + 712 68/push _test-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 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below + 718 # . var ed/ECX : exit-descriptor + 719 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 720 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 721 # . tailor-exit-descriptor(ed, 12) + 722 # . . push args + 723 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte + 724 51/push-ECX/ed + 725 # . . call + 726 e8/call tailor-exit-descriptor/disp32 + 727 # . . discard args + 728 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 729 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) + 730 # . . push args + 731 51/push-ECX/ed + 732 68/push _test-error-buffered-file/imm32 + 733 68/push _test-buffered-file/imm32 + 734 # . . call + 735 e8/call scan-next-byte/disp32 + 736 # registers except ESP may be clobbered at this point + 737 # pop args to scan-next-byte + 738 # . . discard first 2 args + 739 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 740 # . . restore ed + 741 59/pop-to-ECX + 742 # check that scan-next-byte didn't abort + 743 # . check-ints-equal(ed->value, 0, msg) + 744 # . . push args + 745 68/push "F - test-scan-next-byte-skips-whitespace: unexpected abort"/imm32 + 746 68/push 0/imm32 + 747 # . . push ed->value + 748 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) + 749 # . . call + 750 e8/call check-ints-equal/disp32 + 751 # . . discard args + 752 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 753 # return if abort + 754 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) + 755 75/jump-if-not-equal $test-scan-next-byte-skips-whitespace:end/disp8 + 756 # check-ints-equal(EAX, 0x61/a, msg) + 757 # . . push args + 758 68/push "F - test-scan-next-byte-skips-whitespace"/imm32 + 759 68/push 0x61/imm32/a + 760 50/push-EAX + 761 # . . call + 762 e8/call check-ints-equal/disp32 + 763 # . . discard args + 764 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 765 $test-scan-next-byte-skips-whitespace:end: + 766 # . epilog + 767 # don't restore ESP from EBP; manually reclaim locals + 768 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 769 5d/pop-to-EBP + 770 c3/return + 771 + 772 test-scan-next-byte-skips-comment: + 773 # - check that the first byte after a comment (and newline) is returned + 774 # This test uses exit-descriptors. Use EBP for setting up local variables. + 775 55/push-EBP + 776 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 777 # clear all streams + 778 # . clear-stream(_test-stream) + 779 # . . push args + 780 68/push _test-stream/imm32 + 781 # . . call + 782 e8/call clear-stream/disp32 + 783 # . . discard args + 784 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 785 # . clear-stream(_test-buffered-file+4) + 786 # . . push args + 787 b8/copy-to-EAX _test-buffered-file/imm32 + 788 05/add-to-EAX 4/imm32 + 789 50/push-EAX + 790 # . . call + 791 e8/call clear-stream/disp32 + 792 # . . discard args + 793 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 794 # . clear-stream(_test-error-stream) + 795 # . . push args + 796 68/push _test-error-stream/imm32 + 797 # . . call + 798 e8/call clear-stream/disp32 + 799 # . . discard args + 800 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 801 # . clear-stream(_test-error-buffered-file+4) + 802 # . . push args + 803 b8/copy-to-EAX _test-error-buffered-file/imm32 + 804 05/add-to-EAX 4/imm32 + 805 50/push-EAX + 806 # . . call + 807 e8/call clear-stream/disp32 + 808 # . . discard args + 809 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 810 # initialize '_test-stream' to input with leading comment + 811 # . write(_test-stream, comment) + 812 # . . push args + 813 68/push "#x"/imm32 + 814 68/push _test-stream/imm32 + 815 # . . call + 816 e8/call write/disp32 + 817 # . . discard args + 818 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 819 # . write(_test-stream, Newline) + 820 # . . push args + 821 68/push Newline/imm32 + 822 68/push _test-stream/imm32 + 823 # . . call + 824 e8/call write/disp32 + 825 # . . discard args + 826 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 827 # . write(_test-stream, real text) + 828 # . . push args + 829 68/push "ab"/imm32 + 830 68/push _test-stream/imm32 + 831 # . . call + 832 e8/call write/disp32 + 833 # . . discard args + 834 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 835 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below + 836 # . var ed/ECX : exit-descriptor + 837 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 838 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 839 # . tailor-exit-descriptor(ed, 12) + 840 # . . push args + 841 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte + 842 51/push-ECX/ed + 843 # . . call + 844 e8/call tailor-exit-descriptor/disp32 + 845 # . . discard args + 846 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 847 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) + 848 # . . push args + 849 51/push-ECX/ed + 850 68/push _test-error-buffered-file/imm32 + 851 68/push _test-buffered-file/imm32 + 852 # . . call + 853 e8/call scan-next-byte/disp32 + 854 # registers except ESP may be clobbered at this point + 855 # pop args to scan-next-byte + 856 # . . discard first 2 args + 857 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 858 # . . restore ed + 859 59/pop-to-ECX + 860 # check that scan-next-byte didn't abort + 861 # . check-ints-equal(ed->value, 0, msg) + 862 # . . push args + 863 68/push "F - test-scan-next-byte-skips-comment: unexpected abort"/imm32 + 864 68/push 0/imm32 + 865 # . . push ed->value + 866 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) + 867 # . . call + 868 e8/call check-ints-equal/disp32 + 869 # . . discard args + 870 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 871 # return if abort + 872 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) + 873 75/jump-if-not-equal $test-scan-next-byte-skips-comment:end/disp8 + 874 # check-ints-equal(EAX, 0x61/a, msg) + 875 # . . push args + 876 68/push "F - test-scan-next-byte-skips-comment"/imm32 + 877 68/push 0x61/imm32/a + 878 50/push-EAX + 879 # . . call + 880 e8/call check-ints-equal/disp32 + 881 # . . discard args + 882 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 883 $test-scan-next-byte-skips-comment:end: + 884 # . epilog + 885 # don't restore ESP from EBP; manually reclaim locals + 886 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 887 5d/pop-to-EBP + 888 c3/return + 889 + 890 test-scan-next-byte-skips-comment-and-whitespace: + 891 # - check that the first byte after a comment and any further whitespace is returned + 892 # This test uses exit-descriptors. Use EBP for setting up local variables. + 893 55/push-EBP + 894 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 895 # clear all streams + 896 # . clear-stream(_test-stream) + 897 # . . push args + 898 68/push _test-stream/imm32 + 899 # . . call + 900 e8/call clear-stream/disp32 + 901 # . . discard args + 902 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 903 # . clear-stream(_test-buffered-file+4) + 904 # . . push args + 905 b8/copy-to-EAX _test-buffered-file/imm32 + 906 05/add-to-EAX 4/imm32 + 907 50/push-EAX + 908 # . . call + 909 e8/call clear-stream/disp32 + 910 # . . discard args + 911 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 912 # . clear-stream(_test-error-stream) + 913 # . . push args + 914 68/push _test-error-stream/imm32 + 915 # . . call + 916 e8/call clear-stream/disp32 + 917 # . . discard args + 918 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 919 # . clear-stream(_test-error-buffered-file+4) + 920 # . . push args + 921 b8/copy-to-EAX _test-error-buffered-file/imm32 + 922 05/add-to-EAX 4/imm32 + 923 50/push-EAX + 924 # . . call + 925 e8/call clear-stream/disp32 + 926 # . . discard args + 927 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 928 # initialize '_test-stream' to input with leading comment and more whitespace after newline + 929 # . write(_test-stream, comment) + 930 # . . push args + 931 68/push "#x"/imm32 + 932 68/push _test-stream/imm32 + 933 # . . call + 934 e8/call write/disp32 + 935 # . . discard args + 936 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 937 # . write(_test-stream, Newline) + 938 # . . push args + 939 68/push Newline/imm32 + 940 68/push _test-stream/imm32 + 941 # . . call + 942 e8/call write/disp32 + 943 # . . discard args + 944 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 945 # . write(_test-stream, real text) + 946 # . . push args + 947 68/push " ab"/imm32 + 948 68/push _test-stream/imm32 + 949 # . . call + 950 e8/call write/disp32 + 951 # . . discard args + 952 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 953 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below + 954 # . var ed/ECX : exit-descriptor + 955 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 956 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 957 # . tailor-exit-descriptor(ed, 12) + 958 # . . push args + 959 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte + 960 51/push-ECX/ed + 961 # . . call + 962 e8/call tailor-exit-descriptor/disp32 + 963 # . . discard args + 964 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 965 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) + 966 # . . push args + 967 51/push-ECX/ed + 968 68/push _test-error-buffered-file/imm32 + 969 68/push _test-buffered-file/imm32 + 970 # . . call + 971 e8/call scan-next-byte/disp32 + 972 # registers except ESP may be clobbered at this point + 973 # pop args to scan-next-byte + 974 # . . discard first 2 args + 975 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 976 # . . restore ed + 977 59/pop-to-ECX + 978 # check that scan-next-byte didn't abort + 979 # . check-ints-equal(ed->value, 0, msg) + 980 # . . push args + 981 68/push "F - test-scan-next-byte-skips-comment-and-whitespace: unexpected abort"/imm32 + 982 68/push 0/imm32 + 983 # . . push ed->value + 984 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) + 985 # . . call + 986 e8/call check-ints-equal/disp32 + 987 # . . discard args + 988 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 989 # return if abort + 990 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) + 991 75/jump-if-not-equal $test-scan-next-byte-skips-comment-and-whitespace:end/disp8 + 992 # check-ints-equal(EAX, 0x61/a, msg) + 993 # . . push args + 994 68/push "F - test-scan-next-byte-skips-comment-and-whitespace"/imm32 + 995 68/push 0x61/imm32/a + 996 50/push-EAX + 997 # . . call + 998 e8/call check-ints-equal/disp32 + 999 # . . discard args +1000 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1001 $test-scan-next-byte-skips-comment-and-whitespace:end: +1002 # . epilog +1003 # don't restore ESP from EBP; manually reclaim locals +1004 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1005 5d/pop-to-EBP +1006 c3/return +1007 +1008 test-scan-next-byte-skips-whitespace-and-comment: +1009 # - check that the first byte after any whitespace and comments is returned +1010 # This test uses exit-descriptors. Use EBP for setting up local variables. +1011 55/push-EBP +1012 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1013 # clear all streams +1014 # . clear-stream(_test-stream) +1015 # . . push args +1016 68/push _test-stream/imm32 +1017 # . . call +1018 e8/call clear-stream/disp32 +1019 # . . discard args +1020 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1021 # . clear-stream(_test-buffered-file+4) +1022 # . . push args +1023 b8/copy-to-EAX _test-buffered-file/imm32 +1024 05/add-to-EAX 4/imm32 +1025 50/push-EAX +1026 # . . call +1027 e8/call clear-stream/disp32 +1028 # . . discard args +1029 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1030 # . clear-stream(_test-error-stream) +1031 # . . push args +1032 68/push _test-error-stream/imm32 +1033 # . . call +1034 e8/call clear-stream/disp32 +1035 # . . discard args +1036 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1037 # . clear-stream(_test-error-buffered-file+4) +1038 # . . push args +1039 b8/copy-to-EAX _test-error-buffered-file/imm32 +1040 05/add-to-EAX 4/imm32 +1041 50/push-EAX +1042 # . . call +1043 e8/call clear-stream/disp32 +1044 # . . discard args +1045 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1046 # initialize '_test-stream' to input with leading whitespace and comment +1047 # . write(_test-stream, comment) +1048 # . . push args +1049 68/push " #x"/imm32 +1050 68/push _test-stream/imm32 +1051 # . . call +1052 e8/call write/disp32 +1053 # . . discard args +1054 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1055 # . write(_test-stream, Newline) +1056 # . . push args +1057 68/push Newline/imm32 +1058 68/push _test-stream/imm32 +1059 # . . call +1060 e8/call write/disp32 +1061 # . . discard args +1062 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1063 # . write(_test-stream, real text) +1064 # . . push args +1065 68/push "ab"/imm32 +1066 68/push _test-stream/imm32 +1067 # . . call +1068 e8/call write/disp32 +1069 # . . discard args +1070 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1071 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below +1072 # . var ed/ECX : exit-descriptor +1073 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +1074 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1075 # . tailor-exit-descriptor(ed, 12) +1076 # . . push args +1077 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte +1078 51/push-ECX/ed +1079 # . . call +1080 e8/call tailor-exit-descriptor/disp32 +1081 # . . discard args +1082 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1083 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) +1084 # . . push args +1085 51/push-ECX/ed +1086 68/push _test-error-buffered-file/imm32 +1087 68/push _test-buffered-file/imm32 +1088 # . . call +1089 e8/call scan-next-byte/disp32 +1090 # registers except ESP may be clobbered at this point +1091 # pop args to scan-next-byte +1092 # . . discard first 2 args +1093 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1094 # . . restore ed +1095 59/pop-to-ECX +1096 # check that scan-next-byte didn't abort +1097 # . check-ints-equal(ed->value, 0, msg) +1098 # . . push args +1099 68/push "F - test-scan-next-byte-skips-whitespace-and-comment: unexpected abort"/imm32 +1100 68/push 0/imm32 +1101 # . . push ed->value +1102 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) +1103 # . . call +1104 e8/call check-ints-equal/disp32 +1105 # . . discard args +1106 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1107 # return if abort +1108 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) +1109 75/jump-if-not-equal $test-scan-next-byte-skips-whitespace-and-comment:end/disp8 +1110 # check-ints-equal(EAX, 0x61/a, msg) +1111 # . . push args +1112 68/push "F - test-scan-next-byte-skips-whitespace-and-comment"/imm32 +1113 68/push 0x61/imm32/a +1114 50/push-EAX +1115 # . . call +1116 e8/call check-ints-equal/disp32 +1117 # . . discard args +1118 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1119 $test-scan-next-byte-skips-whitespace-and-comment:end: +1120 # . epilog +1121 # don't restore ESP from EBP; manually reclaim locals +1122 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1123 5d/pop-to-EBP +1124 c3/return +1125 +1126 test-scan-next-byte-reads-final-byte: +1127 # - check that the final byte in input is returned +1128 # This test uses exit-descriptors. Use EBP for setting up local variables. +1129 55/push-EBP +1130 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1131 # clear all streams +1132 # . clear-stream(_test-stream) +1133 # . . push args +1134 68/push _test-stream/imm32 +1135 # . . call +1136 e8/call clear-stream/disp32 +1137 # . . discard args +1138 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1139 # . clear-stream(_test-buffered-file+4) +1140 # . . push args +1141 b8/copy-to-EAX _test-buffered-file/imm32 +1142 05/add-to-EAX 4/imm32 +1143 50/push-EAX +1144 # . . call +1145 e8/call clear-stream/disp32 +1146 # . . discard args +1147 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1148 # . clear-stream(_test-error-stream) +1149 # . . push args +1150 68/push _test-error-stream/imm32 +1151 # . . call +1152 e8/call clear-stream/disp32 +1153 # . . discard args +1154 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1155 # . clear-stream(_test-error-buffered-file+4) +1156 # . . push args +1157 b8/copy-to-EAX _test-error-buffered-file/imm32 +1158 05/add-to-EAX 4/imm32 +1159 50/push-EAX +1160 # . . call +1161 e8/call clear-stream/disp32 +1162 # . . discard args +1163 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1164 # initialize '_test-stream' to input with single character +1165 # . write(_test-stream, character) +1166 # . . push args +1167 68/push "a"/imm32 +1168 68/push _test-stream/imm32 +1169 # . . call +1170 e8/call write/disp32 +1171 # . . discard args +1172 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1173 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below +1174 # . var ed/ECX : exit-descriptor +1175 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +1176 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1177 # . tailor-exit-descriptor(ed, 12) +1178 # . . push args +1179 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte +1180 51/push-ECX/ed +1181 # . . call +1182 e8/call tailor-exit-descriptor/disp32 +1183 # . . discard args +1184 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1185 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) +1186 # . . push args +1187 51/push-ECX/ed +1188 68/push _test-error-buffered-file/imm32 +1189 68/push _test-buffered-file/imm32 +1190 # . . call +1191 e8/call scan-next-byte/disp32 +1192 # registers except ESP may be clobbered at this point +1193 # pop args to scan-next-byte +1194 # . . discard first 2 args +1195 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1196 # . . restore ed +1197 59/pop-to-ECX +1198 # check that scan-next-byte didn't abort +1199 # . check-ints-equal(ed->value, 0, msg) +1200 # . . push args +1201 68/push "F - test-scan-next-byte-reads-final-byte: unexpected abort"/imm32 +1202 68/push 0/imm32 +1203 # . . push ed->value +1204 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) +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 # return if abort +1210 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) +1211 75/jump-if-not-equal $test-scan-next-byte-reads-final-byte:end/disp8 +1212 # check-ints-equal(EAX, 0x61/a, msg) +1213 # . . push args +1214 68/push "F - test-scan-next-byte-reads-final-byte"/imm32 +1215 68/push 0x61/imm32/a +1216 50/push-EAX +1217 # . . call +1218 e8/call check-ints-equal/disp32 +1219 # . . discard args +1220 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1221 $test-scan-next-byte-reads-final-byte:end: +1222 # . epilog +1223 # don't restore ESP from EBP; manually reclaim locals +1224 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1225 5d/pop-to-EBP +1226 c3/return +1227 +1228 test-scan-next-byte-handles-eof: +1229 # - check that the right sentinel value is returned when there's no data remaining to be read +1230 # This test uses exit-descriptors. Use EBP for setting up local variables. +1231 55/push-EBP +1232 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1233 # clear all streams +1234 # . clear-stream(_test-stream) +1235 # . . push args +1236 68/push _test-stream/imm32 +1237 # . . call +1238 e8/call clear-stream/disp32 +1239 # . . discard args +1240 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1241 # . clear-stream(_test-buffered-file+4) +1242 # . . push args +1243 b8/copy-to-EAX _test-buffered-file/imm32 +1244 05/add-to-EAX 4/imm32 +1245 50/push-EAX +1246 # . . call +1247 e8/call clear-stream/disp32 +1248 # . . discard args +1249 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1250 # . clear-stream(_test-error-stream) +1251 # . . push args +1252 68/push _test-error-stream/imm32 +1253 # . . call +1254 e8/call clear-stream/disp32 +1255 # . . discard args +1256 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1257 # . clear-stream(_test-error-buffered-file+4) +1258 # . . push args +1259 b8/copy-to-EAX _test-error-buffered-file/imm32 +1260 05/add-to-EAX 4/imm32 +1261 50/push-EAX +1262 # . . call +1263 e8/call clear-stream/disp32 +1264 # . . discard args +1265 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1266 # leave '_test-stream' empty +1267 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below +1268 # . var ed/ECX : exit-descriptor +1269 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +1270 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1271 # . tailor-exit-descriptor(ed, 12) +1272 # . . push args +1273 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte +1274 51/push-ECX/ed +1275 # . . call +1276 e8/call tailor-exit-descriptor/disp32 +1277 # . . discard args +1278 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1279 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) +1280 # . . push args +1281 51/push-ECX/ed +1282 68/push _test-error-buffered-file/imm32 +1283 68/push _test-buffered-file/imm32 +1284 # . . call +1285 e8/call scan-next-byte/disp32 +1286 # registers except ESP may be clobbered at this point +1287 # pop args to scan-next-byte +1288 # . . discard first 2 args +1289 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1290 # . . restore ed +1291 59/pop-to-ECX +1292 # check that scan-next-byte didn't abort +1293 # . check-ints-equal(ed->value, 0, msg) +1294 # . . push args +1295 68/push "F - test-scan-next-byte-handles-eof: unexpected abort"/imm32 +1296 68/push 0/imm32 +1297 # . . push ed->value +1298 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) +1299 # . . call +1300 e8/call check-ints-equal/disp32 +1301 # . . discard args +1302 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1303 # return if abort +1304 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) +1305 75/jump-if-not-equal $test-scan-next-byte-handles-eof:end/disp8 +1306 # check-ints-equal(EAX, 0xffffffff/eof, msg) +1307 # . . push args +1308 68/push "F - test-scan-next-byte-handles-eof"/imm32 +1309 68/push 0xffffffff/imm32/eof +1310 50/push-EAX +1311 # . . call +1312 e8/call check-ints-equal/disp32 +1313 # . . discard args +1314 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1315 $test-scan-next-byte-handles-eof:end: +1316 # . epilog +1317 # don't restore ESP from EBP; manually reclaim locals +1318 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1319 5d/pop-to-EBP +1320 c3/return +1321 +1322 test-scan-next-byte-aborts-on-invalid-byte: +1323 # - check that the a bad byte immediately aborts +1324 # This test uses exit-descriptors. Use EBP for setting up local variables. +1325 55/push-EBP +1326 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1327 # clear all streams +1328 # . clear-stream(_test-stream) +1329 # . . push args +1330 68/push _test-stream/imm32 +1331 # . . call +1332 e8/call clear-stream/disp32 +1333 # . . discard args +1334 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1335 # . clear-stream(_test-buffered-file+4) +1336 # . . push args +1337 b8/copy-to-EAX _test-buffered-file/imm32 +1338 05/add-to-EAX 4/imm32 +1339 50/push-EAX +1340 # . . call +1341 e8/call clear-stream/disp32 +1342 # . . discard args +1343 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1344 # . clear-stream(_test-error-stream) +1345 # . . push args +1346 68/push _test-error-stream/imm32 +1347 # . . call +1348 e8/call clear-stream/disp32 +1349 # . . discard args +1350 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1351 # . clear-stream(_test-error-buffered-file+4) +1352 # . . push args +1353 b8/copy-to-EAX _test-error-buffered-file/imm32 +1354 05/add-to-EAX 4/imm32 +1355 50/push-EAX +1356 # . . call +1357 e8/call clear-stream/disp32 +1358 # . . discard args +1359 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1360 # initialize '_test-stream' to "x" +1361 # . write(_test-stream, "x") +1362 # . . push args +1363 68/push "x"/imm32 +1364 68/push _test-stream/imm32 +1365 # . . call +1366 e8/call write/disp32 +1367 # . . discard args +1368 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1369 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below +1370 # . var ed/ECX : exit-descriptor +1371 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +1372 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1373 # . tailor-exit-descriptor(ed, 12) +1374 # . . push args +1375 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte +1376 51/push-ECX/ed +1377 # . . call +1378 e8/call tailor-exit-descriptor/disp32 +1379 # . . discard args +1380 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1381 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) +1382 # . . push args +1383 51/push-ECX/ed +1384 68/push _test-error-buffered-file/imm32 +1385 68/push _test-buffered-file/imm32 +1386 # . . call +1387 e8/call scan-next-byte/disp32 +1388 # registers except ESP may be clobbered at this point +1389 # pop args to scan-next-byte +1390 # . . discard first 2 args +1391 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1392 # . . restore ed +1393 59/pop-to-ECX +1394 # check that scan-next-byte aborted +1395 # . check-ints-equal(ed->value, 2, msg) +1396 # . . push args +1397 68/push "F - test-scan-next-byte-aborts-on-invalid-byte"/imm32 +1398 68/push 2/imm32 +1399 # . . push ed->value +1400 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) +1401 # . . call +1402 e8/call check-ints-equal/disp32 +1403 # . . discard args +1404 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1405 $test-scan-next-byte-aborts-on-invalid-byte:end: +1406 # . epilog +1407 # don't restore ESP from EBP; manually reclaim locals +1408 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1409 5d/pop-to-EBP +1410 c3/return +1411 +1412 skip-until-newline: # in : (address buffered-file) -> <void> +1413 # pseudocode: +1414 # push EAX +1415 # repeatedly: +1416 # EAX = read-byte(in) +1417 # if (EAX == 0xffffffff) break +1418 # if (EAX == 0x0a) break +1419 # pop EAX +1420 # . prolog +1421 55/push-EBP +1422 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1423 # . save registers +1424 50/push-EAX +1425 $skip-until-newline:loop: +1426 # . EAX = read-byte(in) +1427 # . . push args +1428 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1429 # . . call +1430 e8/call read-byte/disp32 +1431 # . . discard args +1432 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1433 # . if (EAX == 0xffffffff) break +1434 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xffffffff/imm32 # compare EAX +1435 74/jump-if-equal $skip-until-newline:end/disp8 +1436 # . if (EAX != 0xa/newline) loop +1437 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0xa/imm32 # compare EAX +1438 75/jump-if-not-equal $skip-until-newline:loop/disp8 +1439 $skip-until-newline:end: +1440 # . restore registers +1441 58/pop-to-EAX +1442 # . epilog +1443 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1444 5d/pop-to-EBP +1445 c3/return +1446 +1447 test-skip-until-newline: +1448 # - check that the read pointer points after the newline +1449 # setup +1450 # . clear-stream(_test-stream) +1451 # . . push args +1452 68/push _test-stream/imm32 +1453 # . . call +1454 e8/call clear-stream/disp32 +1455 # . . discard args +1456 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1457 # . clear-stream(_test-buffered-file+4) +1458 # . . push args +1459 b8/copy-to-EAX _test-buffered-file/imm32 +1460 05/add-to-EAX 4/imm32 +1461 50/push-EAX +1462 # . . call +1463 e8/call clear-stream/disp32 +1464 # . . discard args +1465 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1466 # initialize '_test-stream' to "abc\nde" +1467 # . write(_test-stream, "abc") +1468 # . . push args +1469 68/push "abc"/imm32 +1470 68/push _test-stream/imm32 +1471 # . . call +1472 e8/call write/disp32 +1473 # . . discard args +1474 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1475 # . write(_test-stream, Newline) +1476 # . . push args +1477 68/push Newline/imm32 +1478 68/push _test-stream/imm32 +1479 # . . call +1480 e8/call write/disp32 +1481 # . . discard args +1482 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1483 # . write(_test-stream, "de") +1484 # . . push args +1485 68/push "de"/imm32 +1486 68/push _test-stream/imm32 +1487 # . . call +1488 e8/call write/disp32 +1489 # . . discard args +1490 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1491 # skip-until-newline(_test-buffered-file) +1492 # . . push args +1493 68/push _test-buffered-file/imm32 +1494 # . . call +1495 e8/call skip-until-newline/disp32 +1496 # . . discard args +1497 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1498 # check-ints-equal(_test-buffered-file->read, 4, msg) +1499 # . . push args +1500 68/push "F - test-skip-until-newline"/imm32 +1501 68/push 4/imm32 +1502 b8/copy-to-EAX _test-buffered-file/imm32 +1503 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 8/disp8 . # push *(EAX+8) +1504 # . . call +1505 e8/call check-ints-equal/disp32 +1506 # . . discard args +1507 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1508 # . end +1509 c3/return +1510 +1511 == data +1512 +1513 _test-error-stream: +1514 # current write index +1515 0/imm32 +1516 # current read index +1517 0/imm32 +1518 # length +1519 8/imm32 +1520 # data +1521 00 00 00 00 00 00 00 00 # 8 bytes +1522 +1523 # a test buffered file for _test-stream +1524 _test-error-buffered-file: +1525 # file descriptor or (address stream) +1526 _test-error-stream/imm32 +1527 # current write index +1528 0/imm32 +1529 # current read index +1530 0/imm32 +1531 # length +1532 6/imm32 +1533 # data +1534 00 00 00 00 00 00 # 6 bytes +1535 +1536 # . . vim:nowrap:textwidth=0 -- cgit 1.4.1-2-gfad0