From 0af2ea07b33ac7c810cfb8f5aa124092e626228b Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Tue, 23 Apr 2019 20:51:58 -0700 Subject: 5119 --- html/subx/052kernel-string-equal.subx.html | 6 +- html/subx/054string-equal.subx.html | 6 +- html/subx/058stream-equal.subx.html | 744 +- html/subx/059stop.subx.html | 2 +- html/subx/071read-line.subx.html | 244 +- html/subx/072slice.subx.html | 1934 ++--- html/subx/073next-token.subx.html | 10 +- html/subx/074print-int-decimal.subx.html | 325 + html/subx/apps/assort.subx.html | 2064 ++--- html/subx/apps/crenshaw2-1.subx.html | 790 +- html/subx/apps/crenshaw2-1b.subx.html | 1152 ++- html/subx/apps/dquotes.subx.html | 1103 +++ html/subx/apps/hex.subx.html | 1374 ++-- html/subx/apps/pack.subx.html | 11664 ++++++++++++++------------- html/subx/apps/subx-common.subx.html | 438 +- 15 files changed, 11549 insertions(+), 10307 deletions(-) create mode 100644 html/subx/074print-int-decimal.subx.html create mode 100644 html/subx/apps/dquotes.subx.html (limited to 'html') diff --git a/html/subx/052kernel-string-equal.subx.html b/html/subx/052kernel-string-equal.subx.html index 01a65cd8..f26b805e 100644 --- a/html/subx/052kernel-string-equal.subx.html +++ b/html/subx/052kernel-string-equal.subx.html @@ -148,11 +148,11 @@ if ('onhashchange' in window) { 86 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX 87 75/jump-if-not-equal $kernel-string-equal?:false/disp8 88 # ++i - 89 41/inc-ECX + 89 41/increment-ECX 90 # ++s1 - 91 47/inc-EDI + 91 47/increment-EDI 92 # ++s2 - 93 46/inc-ESI + 93 46/increment-ESI 94 eb/jump $kernel-string-equal?:loop/disp8 95 $kernel-string-equal?:break: 96 # return *s1 == 0 diff --git a/html/subx/054string-equal.subx.html b/html/subx/054string-equal.subx.html index a4f8919c..4eb247f4 100644 --- a/html/subx/054string-equal.subx.html +++ b/html/subx/054string-equal.subx.html @@ -136,11 +136,11 @@ if ('onhashchange' in window) { 74 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX 75 75/jump-if-not-equal $string-equal?:false/disp8 76 # ++i - 77 41/inc-ECX + 77 41/increment-ECX 78 # ++currs - 79 46/inc-ESI + 79 46/increment-ESI 80 # ++currb - 81 47/inc-EDI + 81 47/increment-EDI 82 eb/jump $string-equal?:loop/disp8 83 $string-equal?:true: 84 b8/copy-to-EAX 1/imm32 diff --git a/html/subx/058stream-equal.subx.html b/html/subx/058stream-equal.subx.html index e947be92..0f44395a 100644 --- a/html/subx/058stream-equal.subx.html +++ b/html/subx/058stream-equal.subx.html @@ -23,7 +23,6 @@ a { color:inherit; } .subxTest { color: #5f8700; } .Normal { color: #000000; background-color: #c6c6c6; padding-bottom: 1px; } .subxS2Comment { color: #8a8a8a; } -.SpecialChar { color: #d70000; } --> @@ -280,459 +279,384 @@ if ('onhashchange' in window) { 219 e8/call check-ints-equal/disp32 220 # . . discard args 221 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -222 # . restore registers -223 58/pop-to-EAX -224 # . epilog -225 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -226 5d/pop-to-EBP -227 c3/return -228 -229 # scan the next line until newline starting from f->read and compare it with -230 # 's' (ignoring the trailing newline) -231 # on success, set f->read to after the next newline -232 # on failure, leave f->read unmodified -233 # this function is usually used only in tests, so we repeatedly write f->read -234 next-stream-line-equal?: # f : (address stream), s : (address string) -> EAX : boolean -235 # pseudocode: -236 # currf = f->read # bound: f->write -237 # currs = 0 # bound : s->length -238 # while true -239 # if currf >= f->write -240 # return currs >= s->length -241 # if f[currf] == '\n' -242 # ++currf -243 # return currs >= s->length -244 # if (currs >= s->length) return false # the current line of f still has data to match -245 # if (f[currf] != s[currs]) return false -246 # ++currf -247 # ++currs -248 # -249 # collapsing the two branches that can return true: -250 # currf = f->read # bound: f->write -251 # currs = 0 # bound : s->length -252 # while true -253 # if (currf >= f->write) break -254 # if (f[currf] == '\n') break -255 # if (currs >= s->length) return false # the current line of f still has data to match -256 # if (f[currf] != s[currs]) return false -257 # ++currf -258 # ++currs -259 # ++currf # skip '\n' -260 # return currs >= s->length -261 # Here the final `++currf` is sometimes unnecessary (if we're already at the end of the stream) -262 # -263 # registers: -264 # f: ESI -265 # s: EDI -266 # currf: ECX -267 # currs: EDX -268 # f[currf]: EAX -269 # s[currs]: EBX -270 # -271 # . prolog -272 55/push-EBP -273 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -274 # . save registers -275 51/push-ECX -276 52/push-EDX -277 56/push-ESI -278 57/push-EDI -279 # ESI = f -280 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI -281 # currf/ECX = f->read -282 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX -283 # EDI = s -284 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI -285 # currs/EDX = 0 -286 31/xor 3/mod/direct 2/rm32/EDX . . . 2/r32/EDX . . # clear EDX -287 # EAX = EBX = 0 -288 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -289 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX -290 $next-stream-line-equal?:loop: -291 # if (currf >= f->write) break -292 3b/compare 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # compare ECX with *ESI -293 7d/jump-if-greater-or-equal $next-stream-line-equal?:break/disp8 -294 # AL = *(f->data + f->read) -295 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/ESI 1/index/ECX . 0/r32/AL 0xc/disp8 . # copy byte at *(ESI+ECX+12) to AL -296 # if (EAX == '\n') break -297 3d/compare-EAX-and 0xa/imm32/newline -298 74/jump-if-equal $next-stream-line-equal?:break/disp8 -299 # if (currs >= s->length) return false -300 3b/compare 0/mod/indirect 7/rm32/EDI . . . 2/r32/EDX . . # compare EDX with *EDI -301 7d/jump-if-greater-or-equal $next-stream-line-equal?:false/disp8 -302 # BL = *(s->data + currs) -303 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 7/base/EDI 2/index/EDX . 3/r32/BL 4/disp8 . # copy byte at *(EDI+EDX+4) to BL -304 # if (EAX != EBX) return false -305 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX -306 75/jump-if-not-equal $next-stream-line-equal?:false/disp8 -307 # ++currf -308 41/increment-ECX -309 # ++currs -310 42/increment-EDX -311 eb/jump $next-stream-line-equal?:loop/disp8 -312 $next-stream-line-equal?:break: -313 # ++currf -314 41/increment-ECX -315 # if (currs >= s->length) return true -316 3b/compare 0/mod/indirect 7/rm32/EDI . . . 2/r32/EDX . . # compare EDX with *EDI -317 7c/jump-if-lesser $next-stream-line-equal?:false/disp8 -318 $next-stream-line-equal?:true: -319 b8/copy-to-EAX 1/imm32 -320 # persist f->read on success -321 89/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy ECX to *(ESI+4) -322 eb/jump $next-stream-line-equal?:end/disp8 -323 $next-stream-line-equal?:false: -324 b8/copy-to-EAX 0/imm32 -325 $next-stream-line-equal?:end: -326 # . restore registers -327 5f/pop-to-EDI -328 5e/pop-to-ESI -329 5a/pop-to-EDX -330 59/pop-to-ECX -331 # . epilog -332 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -333 5d/pop-to-EBP -334 c3/return -335 -336 test-next-stream-line-equal-stops-at-newline: -337 # . prolog -338 55/push-EBP -339 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -340 # clear-stream(_test-stream) -341 # . . push args -342 68/push _test-stream/imm32 -343 # . . call -344 e8/call clear-stream/disp32 -345 # . . discard args -346 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -347 # write(_test-stream, "Abc\ndef") -348 # . write(_test-stream, "Abc") +222 $check-stream-equal:end: +223 # . restore registers +224 58/pop-to-EAX +225 # . epilog +226 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +227 5d/pop-to-EBP +228 c3/return +229 +230 # scan the next line until newline starting from f->read and compare it with +231 # 's' (ignoring the trailing newline) +232 # on success, set f->read to after the next newline +233 # on failure, leave f->read unmodified +234 # this function is usually used only in tests, so we repeatedly write f->read +235 next-stream-line-equal?: # f : (address stream), s : (address string) -> EAX : boolean +236 # pseudocode: +237 # currf = f->read # bound: f->write +238 # currs = 0 # bound : s->length +239 # while true +240 # if currf >= f->write +241 # return currs >= s->length +242 # if f[currf] == '\n' +243 # ++currf +244 # return currs >= s->length +245 # if (currs >= s->length) return false # the current line of f still has data to match +246 # if (f[currf] != s[currs]) return false +247 # ++currf +248 # ++currs +249 # +250 # collapsing the two branches that can return true: +251 # currf = f->read # bound: f->write +252 # currs = 0 # bound : s->length +253 # while true +254 # if (currf >= f->write) break +255 # if (f[currf] == '\n') break +256 # if (currs >= s->length) return false # the current line of f still has data to match +257 # if (f[currf] != s[currs]) return false +258 # ++currf +259 # ++currs +260 # ++currf # skip '\n' +261 # return currs >= s->length +262 # Here the final `++currf` is sometimes unnecessary (if we're already at the end of the stream) +263 # +264 # registers: +265 # f: ESI +266 # s: EDI +267 # currf: ECX +268 # currs: EDX +269 # f[currf]: EAX +270 # s[currs]: EBX +271 # +272 # . prolog +273 55/push-EBP +274 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +275 # . save registers +276 51/push-ECX +277 52/push-EDX +278 56/push-ESI +279 57/push-EDI +280 # ESI = f +281 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +282 # currf/ECX = f->read +283 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX +284 # EDI = s +285 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI +286 # currs/EDX = 0 +287 31/xor 3/mod/direct 2/rm32/EDX . . . 2/r32/EDX . . # clear EDX +288 # EAX = EBX = 0 +289 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +290 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX +291 $next-stream-line-equal?:loop: +292 # if (currf >= f->write) break +293 3b/compare 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # compare ECX with *ESI +294 7d/jump-if-greater-or-equal $next-stream-line-equal?:break/disp8 +295 # AL = *(f->data + f->read) +296 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/ESI 1/index/ECX . 0/r32/AL 0xc/disp8 . # copy byte at *(ESI+ECX+12) to AL +297 # if (EAX == '\n') break +298 3d/compare-EAX-and 0xa/imm32/newline +299 74/jump-if-equal $next-stream-line-equal?:break/disp8 +300 # if (currs >= s->length) return false +301 3b/compare 0/mod/indirect 7/rm32/EDI . . . 2/r32/EDX . . # compare EDX with *EDI +302 7d/jump-if-greater-or-equal $next-stream-line-equal?:false/disp8 +303 # BL = *(s->data + currs) +304 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 7/base/EDI 2/index/EDX . 3/r32/BL 4/disp8 . # copy byte at *(EDI+EDX+4) to BL +305 # if (EAX != EBX) return false +306 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX +307 75/jump-if-not-equal $next-stream-line-equal?:false/disp8 +308 # ++currf +309 41/increment-ECX +310 # ++currs +311 42/increment-EDX +312 eb/jump $next-stream-line-equal?:loop/disp8 +313 $next-stream-line-equal?:break: +314 # ++currf +315 41/increment-ECX +316 # if (currs >= s->length) return true +317 3b/compare 0/mod/indirect 7/rm32/EDI . . . 2/r32/EDX . . # compare EDX with *EDI +318 7c/jump-if-lesser $next-stream-line-equal?:false/disp8 +319 $next-stream-line-equal?:true: +320 b8/copy-to-EAX 1/imm32 +321 # persist f->read on success +322 89/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy ECX to *(ESI+4) +323 eb/jump $next-stream-line-equal?:end/disp8 +324 $next-stream-line-equal?:false: +325 b8/copy-to-EAX 0/imm32 +326 $next-stream-line-equal?:end: +327 # . restore registers +328 5f/pop-to-EDI +329 5e/pop-to-ESI +330 5a/pop-to-EDX +331 59/pop-to-ECX +332 # . epilog +333 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +334 5d/pop-to-EBP +335 c3/return +336 +337 test-next-stream-line-equal-stops-at-newline: +338 # . prolog +339 55/push-EBP +340 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +341 # clear-stream(_test-stream) +342 # . . push args +343 68/push _test-stream/imm32 +344 # . . call +345 e8/call clear-stream/disp32 +346 # . . discard args +347 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +348 # write(_test-stream, "Abc\ndef") 349 # . . push args -350 68/push "Abc"/imm32 +350 68/push "Abc\ndef"/imm32 351 68/push _test-stream/imm32 352 # . . call 353 e8/call write/disp32 354 # . . discard args 355 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -356 # . write(_test-stream, Newline) +356 # EAX = next-stream-line-equal?(_test-stream, "Abc") 357 # . . push args -358 68/push Newline/imm32 +358 68/push "Abc"/imm32 359 68/push _test-stream/imm32 360 # . . call -361 e8/call write/disp32 +361 e8/call next-stream-line-equal?/disp32 362 # . . discard args 363 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -364 # . write(_test-stream, "def") +364 # check-ints-equal(EAX, 1, msg) 365 # . . push args -366 68/push "def"/imm32 -367 68/push _test-stream/imm32 -368 # . . call -369 e8/call write/disp32 -370 # . . discard args -371 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -372 # EAX = next-stream-line-equal?(_test-stream, "Abc") -373 # . . push args -374 68/push "Abc"/imm32 -375 68/push _test-stream/imm32 -376 # . . call -377 e8/call next-stream-line-equal?/disp32 -378 # . . discard args -379 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -380 # check-ints-equal(EAX, 1, msg) -381 # . . push args -382 68/push "F - test-next-stream-line-equal-stops-at-newline"/imm32 -383 68/push 1/imm32 -384 50/push-EAX +366 68/push "F - test-next-stream-line-equal-stops-at-newline"/imm32 +367 68/push 1/imm32 +368 50/push-EAX +369 # . . call +370 e8/call check-ints-equal/disp32 +371 # . . discard args +372 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +373 # . epilog +374 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +375 5d/pop-to-EBP +376 c3/return +377 +378 test-next-stream-line-equal-stops-at-newline-2: +379 # . prolog +380 55/push-EBP +381 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +382 # clear-stream(_test-stream) +383 # . . push args +384 68/push _test-stream/imm32 385 # . . call -386 e8/call check-ints-equal/disp32 +386 e8/call clear-stream/disp32 387 # . . discard args -388 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -389 # . epilog -390 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -391 5d/pop-to-EBP -392 c3/return -393 -394 test-next-stream-line-equal-stops-at-newline-2: -395 # . prolog -396 55/push-EBP -397 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -398 # clear-stream(_test-stream) -399 # . . push args +388 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +389 # write(_test-stream, "Abc\ndef") +390 # . . push args +391 68/push "Abc\ndef"/imm32 +392 68/push _test-stream/imm32 +393 # . . call +394 e8/call write/disp32 +395 # . . discard args +396 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +397 # EAX = next-stream-line-equal?(_test-stream, "def") +398 # . . push args +399 68/push "def"/imm32 400 68/push _test-stream/imm32 401 # . . call -402 e8/call clear-stream/disp32 +402 e8/call next-stream-line-equal?/disp32 403 # . . discard args -404 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -405 # write(_test-stream, "Abc\ndef") -406 # . write(_test-stream, "Abc") -407 # . . push args -408 68/push "Abc"/imm32 -409 68/push _test-stream/imm32 +404 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +405 # check-ints-equal(EAX, 0, msg) +406 # . . push args +407 68/push "F - test-next-stream-line-equal-stops-at-newline-2"/imm32 +408 68/push 0/imm32 +409 50/push-EAX 410 # . . call -411 e8/call write/disp32 +411 e8/call check-ints-equal/disp32 412 # . . discard args -413 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -414 # . write(_test-stream, Newline) -415 # . . push args -416 68/push Newline/imm32 -417 68/push _test-stream/imm32 -418 # . . call -419 e8/call write/disp32 -420 # . . discard args -421 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -422 # . write(_test-stream, "def") -423 # . . push args -424 68/push "def"/imm32 +413 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +414 # . epilog +415 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +416 5d/pop-to-EBP +417 c3/return +418 +419 test-next-stream-line-equal-skips-newline: +420 # . prolog +421 55/push-EBP +422 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +423 # clear-stream(_test-stream) +424 # . . push args 425 68/push _test-stream/imm32 426 # . . call -427 e8/call write/disp32 +427 e8/call clear-stream/disp32 428 # . . discard args -429 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -430 # EAX = next-stream-line-equal?(_test-stream, "def") +429 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +430 # write(_test-stream, "Abc\ndef\n") 431 # . . push args -432 68/push "def"/imm32 +432 68/push "Abc\ndef\n"/imm32 433 68/push _test-stream/imm32 434 # . . call -435 e8/call next-stream-line-equal?/disp32 +435 e8/call write/disp32 436 # . . discard args 437 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -438 # check-ints-equal(EAX, 0, msg) +438 # next-stream-line-equal?(_test-stream, "Abc") 439 # . . push args -440 68/push "F - test-next-stream-line-equal-stops-at-newline-2"/imm32 -441 68/push 0/imm32 -442 50/push-EAX -443 # . . call -444 e8/call check-ints-equal/disp32 -445 # . . discard args -446 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -447 # . epilog -448 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -449 5d/pop-to-EBP -450 c3/return -451 -452 test-next-stream-line-equal-skips-newline: -453 # . prolog -454 55/push-EBP -455 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -456 # clear-stream(_test-stream) -457 # . . push args -458 68/push _test-stream/imm32 +440 68/push "Abc"/imm32 +441 68/push _test-stream/imm32 +442 # . . call +443 e8/call next-stream-line-equal?/disp32 +444 # . . discard args +445 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +446 # EAX = next-stream-line-equal?(_test-stream, "def") +447 # . . push args +448 68/push "def"/imm32 +449 68/push _test-stream/imm32 +450 # . . call +451 e8/call next-stream-line-equal?/disp32 +452 # . . discard args +453 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +454 # check-ints-equal(EAX, 1, msg) +455 # . . push args +456 68/push "F - test-next-stream-line-equal-skips-newline"/imm32 +457 68/push 1/imm32 +458 50/push-EAX 459 # . . call -460 e8/call clear-stream/disp32 +460 e8/call check-ints-equal/disp32 461 # . . discard args -462 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -463 # write(_test-stream, "Abc\ndef\n") -464 # . write(_test-stream, "Abc") -465 # . . push args -466 68/push "Abc"/imm32 -467 68/push _test-stream/imm32 -468 # . . call -469 e8/call write/disp32 -470 # . . discard args -471 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -472 # . write(_test-stream, Newline) +462 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +463 # . epilog +464 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +465 5d/pop-to-EBP +466 c3/return +467 +468 test-next-stream-line-equal-handles-final-line: +469 # . prolog +470 55/push-EBP +471 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +472 # clear-stream(_test-stream) 473 # . . push args -474 68/push Newline/imm32 -475 68/push _test-stream/imm32 -476 # . . call -477 e8/call write/disp32 -478 # . . discard args -479 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -480 # . write(_test-stream, "def") -481 # . . push args -482 68/push "def"/imm32 -483 68/push _test-stream/imm32 -484 # . . call -485 e8/call write/disp32 -486 # . . discard args -487 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -488 # . write(_test-stream, Newline) -489 # . . push args -490 68/push Newline/imm32 -491 68/push _test-stream/imm32 -492 # . . call -493 e8/call write/disp32 -494 # . . discard args -495 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -496 # next-stream-line-equal?(_test-stream, "Abc") -497 # . . push args -498 68/push "Abc"/imm32 -499 68/push _test-stream/imm32 -500 # . . call -501 e8/call next-stream-line-equal?/disp32 -502 # . . discard args -503 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -504 # EAX = next-stream-line-equal?(_test-stream, "def") -505 # . . push args -506 68/push "def"/imm32 -507 68/push _test-stream/imm32 +474 68/push _test-stream/imm32 +475 # . . call +476 e8/call clear-stream/disp32 +477 # . . discard args +478 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +479 # write(_test-stream, "Abc\ndef") +480 # . . push args +481 68/push "Abc\ndef"/imm32 +482 68/push _test-stream/imm32 +483 # . . call +484 e8/call write/disp32 +485 # . . discard args +486 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +487 # next-stream-line-equal?(_test-stream, "Abc") +488 # . . push args +489 68/push "Abc"/imm32 +490 68/push _test-stream/imm32 +491 # . . call +492 e8/call next-stream-line-equal?/disp32 +493 # . . discard args +494 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +495 # EAX = next-stream-line-equal?(_test-stream, "def") +496 # . . push args +497 68/push "def"/imm32 +498 68/push _test-stream/imm32 +499 # . . call +500 e8/call next-stream-line-equal?/disp32 +501 # . . discard args +502 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +503 # check-ints-equal(EAX, 1, msg) +504 # . . push args +505 68/push "F - test-next-stream-line-equal-skips-newline"/imm32 +506 68/push 1/imm32 +507 50/push-EAX 508 # . . call -509 e8/call next-stream-line-equal?/disp32 +509 e8/call check-ints-equal/disp32 510 # . . discard args -511 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -512 # check-ints-equal(EAX, 1, msg) -513 # . . push args -514 68/push "F - test-next-stream-line-equal-skips-newline"/imm32 -515 68/push 1/imm32 -516 50/push-EAX -517 # . . call -518 e8/call check-ints-equal/disp32 -519 # . . discard args -520 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -521 # . epilog -522 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -523 5d/pop-to-EBP -524 c3/return -525 -526 test-next-stream-line-equal-handles-final-line: -527 # . prolog -528 55/push-EBP -529 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -530 # clear-stream(_test-stream) -531 # . . push args +511 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +512 # . epilog +513 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +514 5d/pop-to-EBP +515 c3/return +516 +517 test-next-stream-line-equal-always-fails-after-Eof: +518 # . prolog +519 55/push-EBP +520 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +521 # clear-stream(_test-stream) +522 # . . push args +523 68/push _test-stream/imm32 +524 # . . call +525 e8/call clear-stream/disp32 +526 # . . discard args +527 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +528 # write nothing +529 # EAX = next-stream-line-equal?(_test-stream, "") +530 # . . push args +531 68/push ""/imm32 532 68/push _test-stream/imm32 533 # . . call -534 e8/call clear-stream/disp32 +534 e8/call next-stream-line-equal?/disp32 535 # . . discard args -536 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -537 # write(_test-stream, "Abc\ndef") -538 # . write(_test-stream, "Abc") -539 # . . push args -540 68/push "Abc"/imm32 -541 68/push _test-stream/imm32 +536 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +537 # check-ints-equal(EAX, 0, msg) +538 # . . push args +539 68/push "F - test-next-stream-line-equal-always-fails-after-Eof"/imm32 +540 68/push 1/imm32 +541 50/push-EAX 542 # . . call -543 e8/call write/disp32 +543 e8/call check-ints-equal/disp32 544 # . . discard args -545 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -546 # . write(_test-stream, Newline) +545 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +546 # EAX = next-stream-line-equal?(_test-stream, "") 547 # . . push args -548 68/push Newline/imm32 +548 68/push ""/imm32 549 68/push _test-stream/imm32 550 # . . call -551 e8/call write/disp32 +551 e8/call next-stream-line-equal?/disp32 552 # . . discard args 553 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -554 # . write(_test-stream, "def") +554 # check-ints-equal(EAX, 0, msg) 555 # . . push args -556 68/push "def"/imm32 -557 68/push _test-stream/imm32 -558 # . . call -559 e8/call write/disp32 -560 # . . discard args -561 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -562 # next-stream-line-equal?(_test-stream, "Abc") -563 # . . push args -564 68/push "Abc"/imm32 -565 68/push _test-stream/imm32 -566 # . . call -567 e8/call next-stream-line-equal?/disp32 -568 # . . discard args -569 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -570 # EAX = next-stream-line-equal?(_test-stream, "def") -571 # . . push args -572 68/push "def"/imm32 -573 68/push _test-stream/imm32 -574 # . . call -575 e8/call next-stream-line-equal?/disp32 -576 # . . discard args -577 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -578 # check-ints-equal(EAX, 1, msg) -579 # . . push args -580 68/push "F - test-next-stream-line-equal-skips-newline"/imm32 -581 68/push 1/imm32 -582 50/push-EAX -583 # . . call -584 e8/call check-ints-equal/disp32 -585 # . . discard args -586 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -587 # . epilog -588 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -589 5d/pop-to-EBP -590 c3/return -591 -592 test-next-stream-line-equal-always-fails-after-Eof: -593 # . prolog -594 55/push-EBP -595 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -596 # clear-stream(_test-stream) -597 # . . push args -598 68/push _test-stream/imm32 -599 # . . call -600 e8/call clear-stream/disp32 -601 # . . discard args -602 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -603 # write nothing -604 # EAX = next-stream-line-equal?(_test-stream, "") -605 # . . push args -606 68/push ""/imm32 -607 68/push _test-stream/imm32 -608 # . . call -609 e8/call next-stream-line-equal?/disp32 -610 # . . discard args -611 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -612 # check-ints-equal(EAX, 0, msg) -613 # . . push args -614 68/push "F - test-next-stream-line-equal-always-fails-after-Eof"/imm32 -615 68/push 1/imm32 -616 50/push-EAX -617 # . . call -618 e8/call check-ints-equal/disp32 -619 # . . discard args -620 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -621 # EAX = next-stream-line-equal?(_test-stream, "") -622 # . . push args -623 68/push ""/imm32 -624 68/push _test-stream/imm32 -625 # . . call -626 e8/call next-stream-line-equal?/disp32 -627 # . . discard args -628 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -629 # check-ints-equal(EAX, 0, msg) -630 # . . push args -631 68/push "F - test-next-stream-line-equal-always-fails-after-Eof/2"/imm32 -632 68/push 1/imm32 -633 50/push-EAX -634 # . . call -635 e8/call check-ints-equal/disp32 -636 # . . discard args -637 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -638 # . epilog -639 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -640 5d/pop-to-EBP -641 c3/return -642 -643 # helper for later tests -644 check-next-stream-line-equal: -645 # . prolog -646 55/push-EBP -647 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -648 # . save registers -649 50/push-EAX -650 # EAX = next-stream-line-equal?(f, s) -651 # . . push args -652 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -653 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -654 # . . call -655 e8/call next-stream-line-equal?/disp32 -656 # . . discard args -657 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -658 # check-ints-equal(EAX, 1, msg) -659 # . . push args -660 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) -661 68/push 1/imm32 -662 50/push-EAX -663 # . . call -664 e8/call check-ints-equal/disp32 -665 # . . discard args -666 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -667 # . restore registers -668 58/pop-to-EAX -669 # . epilog -670 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -671 5d/pop-to-EBP -672 c3/return -673 -674 # . . vim:nowrap:textwidth=0 +556 68/push "F - test-next-stream-line-equal-always-fails-after-Eof/2"/imm32 +557 68/push 1/imm32 +558 50/push-EAX +559 # . . call +560 e8/call check-ints-equal/disp32 +561 # . . discard args +562 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +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 # helper for later tests +569 check-next-stream-line-equal: +570 # . prolog +571 55/push-EBP +572 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +573 # . save registers +574 50/push-EAX +575 # EAX = next-stream-line-equal?(f, s) +576 # . . push args +577 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +578 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +579 # . . call +580 e8/call next-stream-line-equal?/disp32 +581 # . . discard args +582 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +583 # check-ints-equal(EAX, 1, msg) +584 # . . push args +585 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) +586 68/push 1/imm32 +587 50/push-EAX +588 # . . call +589 e8/call check-ints-equal/disp32 +590 # . . discard args +591 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +592 # . restore registers +593 58/pop-to-EAX +594 # . epilog +595 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +596 5d/pop-to-EBP +597 c3/return +598 +599 # . . vim:nowrap:textwidth=0 diff --git a/html/subx/059stop.subx.html b/html/subx/059stop.subx.html index cebc1975..83fddf7d 100644 --- a/html/subx/059stop.subx.html +++ b/html/subx/059stop.subx.html @@ -171,7 +171,7 @@ if ('onhashchange' in window) { 110 # otherwise: 111 # ed->value = value+1 112 8b/copy 1/mod/*+disp8 4/rm32/sib 4/base/ESP 4/index/none . 1/r32/ECX 8/disp8 . # copy *(ESP+8) to ECX -113 41/inc-ECX +113 41/increment-ECX 114 89/copy 1/mod/*+disp8 0/rm32/EAX . . . 1/r32/ECX 4/disp8 . # copy ECX to *(EAX+4) 115 # perform a non-local jump to ed->target 116 8b/copy 0/mod/indirect 0/rm32/EAX . . . 4/r32/ESP . . # copy *EAX to ESP diff --git a/html/subx/071read-line.subx.html b/html/subx/071read-line.subx.html index 8d334d9c..37050313 100644 --- a/html/subx/071read-line.subx.html +++ b/html/subx/071read-line.subx.html @@ -23,7 +23,6 @@ a { color:inherit; } .subxTest { color: #5f8700; } .Normal { color: #000000; background-color: #c6c6c6; padding-bottom: 1px; } .subxS2Comment { color: #8a8a8a; } -.SpecialChar { color: #d70000; } .subxH1Comment { color: #005faf; text-decoration: underline; } --> @@ -165,153 +164,128 @@ if ('onhashchange' in window) { 103 $read-line:abort: 104 # . _write(2/stderr, error) 105 # . . push args -106 68/push "read-line: line too long"/imm32 +106 68/push "read-line: line too long\n"/imm32 107 68/push 2/imm32/stderr 108 # . . call 109 e8/call _write/disp32 110 # . . discard args 111 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -112 # . _write(2/stderr, Newline) -113 # . . push args -114 68/push Newline/imm32 -115 68/push 2/imm32/stderr -116 # . . call -117 e8/call _write/disp32 -118 # . . discard args -119 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -120 # . syscall(exit, 1) -121 bb/copy-to-EBX 1/imm32 -122 b8/copy-to-EAX 1/imm32/exit -123 cd/syscall 0x80/imm8 -124 # never gets here -125 -126 test-read-line: -127 # - check that read-line stops at a newline -128 # setup -129 # . clear-stream(_test-stream) -130 # . . push args -131 68/push _test-stream/imm32 -132 # . . call -133 e8/call clear-stream/disp32 -134 # . . discard args -135 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -136 # . clear-stream(_test-buffered-file+4) -137 # . . push args -138 b8/copy-to-EAX _test-buffered-file/imm32 -139 05/add-to-EAX 4/imm32 -140 50/push-EAX -141 # . . call -142 e8/call clear-stream/disp32 -143 # . . discard args -144 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -145 # . clear-stream(_test-tmp-stream) -146 # . . push args -147 68/push _test-tmp-stream/imm32 +112 # . syscall(exit, 1) +113 bb/copy-to-EBX 1/imm32 +114 b8/copy-to-EAX 1/imm32/exit +115 cd/syscall 0x80/imm8 +116 # never gets here +117 +118 test-read-line: +119 # - check that read-line stops at a newline +120 # setup +121 # . clear-stream(_test-stream) +122 # . . push args +123 68/push _test-stream/imm32 +124 # . . call +125 e8/call clear-stream/disp32 +126 # . . discard args +127 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +128 # . clear-stream(_test-buffered-file+4) +129 # . . push args +130 b8/copy-to-EAX _test-buffered-file/imm32 +131 05/add-to-EAX 4/imm32 +132 50/push-EAX +133 # . . call +134 e8/call clear-stream/disp32 +135 # . . discard args +136 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +137 # . clear-stream(_test-tmp-stream) +138 # . . push args +139 68/push _test-tmp-stream/imm32 +140 # . . call +141 e8/call clear-stream/disp32 +142 # . . discard args +143 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +144 # write(_test-stream, "ab\ncd") +145 # . . push args +146 68/push "ab\ncd"/imm32 +147 68/push _test-stream/imm32 148 # . . call -149 e8/call clear-stream/disp32 +149 e8/call write/disp32 150 # . . discard args -151 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -152 # write(_test-stream, "ab\ncd") -153 # . write(_test-stream, "ab") +151 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +152 # read a line from _test-stream (buffered by _test-buffered-file) into _test-tmp-stream +153 # . EAX = read-line(_test-buffered-file, _test-tmp-stream) 154 # . . push args -155 68/push "ab"/imm32 -156 68/push _test-stream/imm32 +155 68/push _test-tmp-stream/imm32 +156 68/push _test-buffered-file/imm32 157 # . . call -158 e8/call write/disp32 +158 e8/call read-line/disp32 159 # . . discard args 160 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -161 # . write(_test-stream, "\n") +161 # check-next-stream-line-equal(_test-tmp-stream, "ab", msg) 162 # . . push args -163 68/push Newline/imm32 -164 68/push _test-stream/imm32 -165 # . . call -166 e8/call write/disp32 -167 # . . discard args -168 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -169 # . write(_test-stream, "cd") -170 # . . push args -171 68/push "cd"/imm32 -172 68/push _test-stream/imm32 -173 # . . call -174 e8/call write/disp32 -175 # . . discard args -176 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -177 # read a line from _test-stream (buffered by _test-buffered-file) into _test-tmp-stream -178 # . EAX = read-line(_test-buffered-file, _test-tmp-stream) -179 # . . push args -180 68/push _test-tmp-stream/imm32 -181 68/push _test-buffered-file/imm32 -182 # . . call -183 e8/call read-line/disp32 -184 # . . discard args -185 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -186 # check-next-stream-line-equal(_test-tmp-stream, "ab", msg) -187 # . . push args -188 68/push "F - test-read-line"/imm32 -189 68/push "ab"/imm32 -190 68/push _test-tmp-stream/imm32 -191 # . . call -192 e8/call check-next-stream-line-equal/disp32 -193 # . . discard args -194 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -195 # end -196 c3/return -197 -198 test-read-line-reads-final-line-until-Eof: -199 # setup -200 # . clear-stream(_test-stream) -201 # . . push args -202 68/push _test-stream/imm32 -203 # . . call -204 e8/call clear-stream/disp32 -205 # . . discard args -206 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -207 # . clear-stream(_test-buffered-file+4) +163 68/push "F - test-read-line"/imm32 +164 68/push "ab"/imm32 +165 68/push _test-tmp-stream/imm32 +166 # . . call +167 e8/call check-next-stream-line-equal/disp32 +168 # . . discard args +169 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +170 # end +171 c3/return +172 +173 test-read-line-reads-final-line-until-Eof: +174 # setup +175 # . clear-stream(_test-stream) +176 # . . push args +177 68/push _test-stream/imm32 +178 # . . call +179 e8/call clear-stream/disp32 +180 # . . discard args +181 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +182 # . clear-stream(_test-buffered-file+4) +183 # . . push args +184 b8/copy-to-EAX _test-buffered-file/imm32 +185 05/add-to-EAX 4/imm32 +186 50/push-EAX +187 # . . call +188 e8/call clear-stream/disp32 +189 # . . discard args +190 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +191 # . clear-stream(_test-tmp-stream) +192 # . . push args +193 68/push _test-tmp-stream/imm32 +194 # . . call +195 e8/call clear-stream/disp32 +196 # . . discard args +197 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +198 # write(_test-stream, "cd") +199 # . . push args +200 68/push "cd"/imm32 +201 68/push _test-stream/imm32 +202 # . . call +203 e8/call write/disp32 +204 # . . discard args +205 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +206 # read a line from _test-stream (buffered by _test-buffered-file) into _test-tmp-stream +207 # . EAX = read-line(_test-buffered-file, _test-tmp-stream) 208 # . . push args -209 b8/copy-to-EAX _test-buffered-file/imm32 -210 05/add-to-EAX 4/imm32 -211 50/push-EAX -212 # . . call -213 e8/call clear-stream/disp32 -214 # . . discard args -215 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -216 # . clear-stream(_test-tmp-stream) -217 # . . push args -218 68/push _test-tmp-stream/imm32 -219 # . . call -220 e8/call clear-stream/disp32 -221 # . . discard args -222 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -223 # write(_test-stream, "cd") -224 # . . push args -225 68/push "cd"/imm32 -226 68/push _test-stream/imm32 -227 # . . call -228 e8/call write/disp32 -229 # . . discard args -230 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -231 # read a line from _test-stream (buffered by _test-buffered-file) into _test-tmp-stream -232 # . EAX = read-line(_test-buffered-file, _test-tmp-stream) -233 # . . push args -234 68/push _test-tmp-stream/imm32 -235 68/push _test-buffered-file/imm32 -236 # . . call -237 e8/call read-line/disp32 -238 # . . discard args -239 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -240 # check-stream-equal(_test-tmp-stream, "cd", msg) -241 # . . push args -242 68/push "F - test-read-line-reads-final-line-until-Eof"/imm32 -243 68/push "cd"/imm32 -244 68/push _test-tmp-stream/imm32 -245 # . . call -246 e8/call check-stream-equal/disp32 -247 # . . discard args -248 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -249 # end -250 c3/return -251 -252 # . . vim:nowrap:textwidth=0 +209 68/push _test-tmp-stream/imm32 +210 68/push _test-buffered-file/imm32 +211 # . . call +212 e8/call read-line/disp32 +213 # . . discard args +214 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +215 # check-stream-equal(_test-tmp-stream, "cd", msg) +216 # . . push args +217 68/push "F - test-read-line-reads-final-line-until-Eof"/imm32 +218 68/push "cd"/imm32 +219 68/push _test-tmp-stream/imm32 +220 # . . call +221 e8/call check-stream-equal/disp32 +222 # . . discard args +223 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +224 # end +225 c3/return +226 +227 # . . vim:nowrap:textwidth=0 diff --git a/html/subx/072slice.subx.html b/html/subx/072slice.subx.html index 5bc4ae43..3d5aad7d 100644 --- a/html/subx/072slice.subx.html +++ b/html/subx/072slice.subx.html @@ -62,973 +62,973 @@ if ('onhashchange' in window) { https://github.com/akkartik/mu/blob/master/subx/072slice.subx
-   1 # new data structure: a slice is an open interval of addresses [start, end)
-   2 # that includes 'start' but not 'end'
-   3 
-   4 == code
-   5 #   instruction                     effective address                                                   register    displacement    immediate
-   6 # . op          subop               mod             rm32          base        index         scale       r32
-   7 # . 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
-   8 
-   9 #? Entry:  # run a single test, while debugging
-  10 #?     e8/call test-slice-to-string/disp32
-  11 #?     # syscall(exit, Num-test-failures)
-  12 #?     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
-  13 #?     b8/copy-to-EAX  1/imm32/exit
-  14 #?     cd/syscall  0x80/imm8
-  15 
-  16 slice-empty?:  # s : (address slice) -> EAX : boolean
-  17     # . prolog
-  18     55/push-EBP
-  19     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-  20     # . save registers
-  21     51/push-ECX
-  22     # ECX = s
-  23     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           1/r32/ECX   8/disp8         .                 # copy *(EBP+8) to ECX
-  24     # if (s->start == s->end) return true
-  25     # . EAX = s->start
-  26     8b/copy                         0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # copy *ECX to EAX
-  27     # . compare EAX and s->end
-  28     39/compare                      1/mod/*+disp8   1/rm32/ECX    .           .             .           0/r32/EAX   4/disp8         .                 # compare EAX and *(ECX+4)
-  29     b8/copy-to-EAX  1/imm32/true
-  30     74/jump-if-equal  $slice-empty?:end/disp8
-  31     b8/copy-to-EAX  0/imm32/false
-  32 $slice-empty?:end:
-  33     # . restore registers
-  34     59/pop-to-ECX
-  35     # . epilog
-  36     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
-  37     5d/pop-to-EBP
-  38     c3/return
-  39 
-  40 test-slice-empty-true:
-  41     # . prolog
-  42     55/push-EBP
-  43     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-  44     # var slice/ECX = {34, 34}
-  45     68/push  34/imm32/end
-  46     68/push  34/imm32/start
-  47     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
-  48     # slice-empty?(slice)
-  49     # . . push args
-  50     51/push-ECX
-  51     # . . call
-  52     e8/call  slice-empty?/disp32
-  53     # . . discard args
-  54     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-  55     # check-ints-equal(EAX, 1, msg)
-  56     # . . push args
-  57     68/push  "F - test-slice-empty-true"/imm32
-  58     68/push  1/imm32
-  59     50/push-EAX
-  60     # . . call
-  61     e8/call  check-ints-equal/disp32
-  62     # . . discard args
-  63     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-  64     # . epilog
-  65     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
-  66     5d/pop-to-EBP
-  67     c3/return
-  68 
-  69 test-slice-empty-false:
-  70     # . prolog
-  71     55/push-EBP
-  72     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-  73     # var slice/ECX = {34, 23}
-  74     68/push  23/imm32/end
-  75     68/push  34/imm32/start
-  76     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
-  77     # slice-empty?(slice)
-  78     # . . push args
-  79     51/push-ECX
-  80     # . . call
-  81     e8/call  slice-empty?/disp32
-  82     # . . discard args
-  83     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-  84     # check-ints-equal(EAX, 0, msg)
-  85     # . . push args
-  86     68/push  "F - test-slice-empty-false"/imm32
-  87     68/push  0/imm32
-  88     50/push-EAX
-  89     # . . call
-  90     e8/call  check-ints-equal/disp32
-  91     # . . discard args
-  92     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-  93     # . epilog
-  94     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
-  95     5d/pop-to-EBP
-  96     c3/return
-  97 
-  98 slice-equal?:  # s : (address slice), p : (address string) -> EAX : boolean
-  99     # pseudocode:
- 100     #   if (p == 0) return (s == 0)
- 101     #   currs = s->start
- 102     #   maxs = s->end
- 103     #   if (maxs - currs != p->length) return false
- 104     #   currp = p->data
- 105     #   while currs < maxs
- 106     #     if (*currs != *currp) return false
- 107     #     ++currs
- 108     #     ++currp
- 109     #   return true
- 110     #
- 111     # registers:
- 112     #   currs: EDX
- 113     #   maxs: ESI
- 114     #   currp: EBX
- 115     #   *currs: EAX
- 116     #   *currp: ECX
- 117     #
- 118     # . prolog
- 119     55/push-EBP
- 120     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 121     # . save registers
- 122     51/push-ECX
- 123     52/push-EDX
- 124     53/push-EBX
- 125     56/push-ESI
- 126     # ESI = s
- 127     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
- 128     # currs/EDX = s->start
- 129     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           2/r32/EDX   .               .                 # copy *ESI to EDX
- 130     # maxs/ESI = s->end
- 131     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           6/r32/ESI   4/disp8         .                 # copy *(ESI+4) to ESI
- 132     # EAX = maxs - currs
- 133     89/copy                         3/mod/direct    0/rm32/EAX    .           .             .           6/r32/ESI   .               .                 # copy ESI to EAX
- 134     29/subtract                     3/mod/direct    0/rm32/EAX    .           .             .           2/r32/EDX   .               .                 # subtract EDX from EAX
- 135     # EBX = p
- 136     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           3/r32/EBX   0xc/disp8       .                 # copy *(EBP+12) to EBX
- 137     # if (p != 0) goto next check
- 138     81          7/subop/compare     3/mod/direct    3/rm32/EBX    .           .             .           .           .               0/imm32           # compare EBX
- 139     75/jump-if-not-equal  $slice-equal?:nonnull-string/disp8
- 140 $slice-equal?:null-string:
- 141     # return s->start == s->end
- 142     3d/compare-EAX-and  0/imm32
- 143     74/jump-if-equal  $slice-equal?:true/disp8
- 144     eb/jump  $slice-equal?:false/disp8
- 145 $slice-equal?:nonnull-string:
- 146     # if (EAX != p->length) return false
- 147     39/compare                      0/mod/indirect  3/rm32/EBX    .           .             .           0/r32/EAX   .               .                 # compare *EBX and EAX
- 148     75/jump-if-not-equal  $slice-equal?:false/disp8
- 149     # currp/EBX = p->data
- 150     81          0/subop/add         3/mod/direct    3/rm32/EBX    .           .             .           .           .               4/imm32           # add to EBX
- 151     # EAX = ECX = 0
- 152     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
- 153     31/xor                          3/mod/direct    1/rm32/ECX    .           .             .           1/r32/ECX   .               .                 # clear ECX
- 154 $slice-equal?:loop:
- 155     # if (currs >= maxs) return true
- 156     39/compare                      3/mod/direct    2/rm32/EDX    .           .             .           6/r32/ESI   .               .                 # compare EDX with ESI
- 157     7d/jump-if-greater-or-equal  $slice-equal?:true/disp8
- 158     # AL = *currp
- 159     8a/copy-byte                    0/mod/indirect  3/rm32/EBX    .           .             .           0/r32/AL    .               .                 # copy byte at *EBX to AL
- 160     # CL = *currs
- 161     8a/copy-byte                    0/mod/indirect  2/rm32/EDX    .           .             .           1/r32/CL    .               .                 # copy byte at *EDX to CL
- 162     # if (EAX != ECX) return false
- 163     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # compare EAX and ECX
- 164     75/jump-if-not-equal  $slice-equal?:false/disp8
- 165     # ++currp
- 166     43/increment-EBX
- 167     # ++currs
- 168     42/increment-EDX
- 169     eb/jump $slice-equal?:loop/disp8
- 170 $slice-equal?:false:
- 171     b8/copy-to-EAX  0/imm32
- 172     eb/jump  $slice-equal?:end/disp8
- 173 $slice-equal?:true:
- 174     b8/copy-to-EAX  1/imm32
- 175 $slice-equal?:end:
- 176     # . restore registers
- 177     5e/pop-to-ESI
- 178     5b/pop-to-EBX
- 179     5a/pop-to-EDX
- 180     59/pop-to-ECX
- 181     # . epilog
- 182     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 183     5d/pop-to-EBP
- 184     c3/return
- 185 
- 186 test-slice-equal:
- 187     # - slice-equal?(slice("Abc"), "Abc") == 1
- 188     # . prolog
- 189     55/push-EBP
- 190     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 191     # var slice/ECX
- 192     68/push  _test-slice-data-3/imm32/end
- 193     68/push  _test-slice-data-0/imm32/start
- 194     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
- 195     # EAX = slice-equal?(ECX, "Abc")
- 196     # . . push args
- 197     68/push  "Abc"/imm32
- 198     51/push-ECX
- 199     # . . call
- 200     e8/call  slice-equal?/disp32
- 201     # . . discard args
- 202     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 203     # check-ints-equal(EAX, 1, msg)
- 204     # . . push args
- 205     68/push  "F - test-slice-equal"/imm32
- 206     68/push  1/imm32
- 207     50/push-EAX
- 208     # . . call
- 209     e8/call  check-ints-equal/disp32
- 210     # . . discard args
- 211     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 212     # . epilog
- 213     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 214     5d/pop-to-EBP
- 215     c3/return
- 216 
- 217 test-slice-equal-false:
- 218     # - slice-equal?(slice("bcd"), "Abc") == 0
- 219     # . prolog
- 220     55/push-EBP
- 221     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 222     # var slice/ECX
- 223     68/push  _test-slice-data-4/imm32/end
- 224     68/push  _test-slice-data-1/imm32/start
- 225     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
- 226     # EAX = slice-equal?(ECX, "Abc")
- 227     # . . push args
- 228     68/push  "Abc"/imm32
- 229     51/push-ECX
- 230     # . . call
- 231     e8/call  slice-equal?/disp32
- 232     # . . discard args
- 233     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 234     # check-ints-equal(EAX, 0, msg)
- 235     # . . push args
- 236     68/push  "F - test-slice-equal-false"/imm32
- 237     68/push  0/imm32
- 238     50/push-EAX
- 239     # . . call
- 240     e8/call  check-ints-equal/disp32
- 241     # . . discard args
- 242     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 243     # . epilog
- 244     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 245     5d/pop-to-EBP
- 246     c3/return
- 247 
- 248 test-slice-equal-too-long:
- 249     # - slice-equal?(slice("Abcd"), "Abc") == 0
- 250     # . prolog
- 251     55/push-EBP
- 252     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 253     # var slice/ECX
- 254     68/push  _test-slice-data-4/imm32/end
- 255     68/push  _test-slice-data-0/imm32/start
- 256     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
- 257     # EAX = slice-equal?(ECX, "Abc")
- 258     # . . push args
- 259     68/push  "Abc"/imm32
- 260     51/push-ECX
- 261     # . . call
- 262     e8/call  slice-equal?/disp32
- 263     # . . discard args
- 264     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 265     # check-ints-equal(EAX, 0, msg)
- 266     # . . push args
- 267     68/push  "F - test-slice-equal-too-long"/imm32
- 268     68/push  0/imm32
- 269     50/push-EAX
- 270     # . . call
- 271     e8/call  check-ints-equal/disp32
- 272     # . . discard args
- 273     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 274     # . epilog
- 275     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 276     5d/pop-to-EBP
- 277     c3/return
- 278 
- 279 test-slice-equal-too-short:
- 280     # - slice-equal?(slice("A"), "Abc") == 0
- 281     # . prolog
- 282     55/push-EBP
- 283     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 284     # var slice/ECX
- 285     68/push  _test-slice-data-1/imm32/end
- 286     68/push  _test-slice-data-0/imm32/start
- 287     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
- 288     # EAX = slice-equal?(ECX, "Abc")
- 289     # . . push args
- 290     68/push  "Abc"/imm32
- 291     51/push-ECX
- 292     # . . call
- 293     e8/call  slice-equal?/disp32
- 294     # . . discard args
- 295     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 296     # check-ints-equal(EAX, 0, msg)
- 297     # . . push args
- 298     68/push  "F - test-slice-equal-too-short"/imm32
- 299     68/push  0/imm32
- 300     50/push-EAX
- 301     # . . call
- 302     e8/call  check-ints-equal/disp32
- 303     # . . discard args
- 304     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 305     # . epilog
- 306     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 307     5d/pop-to-EBP
- 308     c3/return
- 309 
- 310 test-slice-equal-empty:
- 311     # - slice-equal?(slice(""), "Abc") == 0
- 312     # . prolog
- 313     55/push-EBP
- 314     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 315     # var slice/ECX
- 316     68/push  _test-slice-data-0/imm32/end
- 317     68/push  _test-slice-data-0/imm32/start
- 318     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
- 319     # EAX = slice-equal?(ECX, "Abc")
- 320     # . . push args
- 321     68/push  "Abc"/imm32
- 322     51/push-ECX
- 323     # . . call
- 324     e8/call  slice-equal?/disp32
- 325     # . . discard args
- 326     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 327     # check-ints-equal(EAX, 0, msg)
- 328     # . . push args
- 329     68/push  "F - test-slice-equal-empty"/imm32
- 330     68/push  0/imm32
- 331     50/push-EAX
- 332     # . . call
- 333     e8/call  check-ints-equal/disp32
- 334     # . . discard args
- 335     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 336     # . epilog
- 337     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 338     5d/pop-to-EBP
- 339     c3/return
- 340 
- 341 test-slice-equal-with-empty:
- 342     # - slice-equal?(slice("Ab"), "") == 0
- 343     # . prolog
- 344     55/push-EBP
- 345     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 346     # var slice/ECX
- 347     68/push  _test-slice-data-2/imm32/end
- 348     68/push  _test-slice-data-0/imm32/start
- 349     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
- 350     # EAX = slice-equal?(ECX, "")
- 351     # . . push args
- 352     68/push  ""/imm32
- 353     51/push-ECX
- 354     # . . call
- 355     e8/call  slice-equal?/disp32
- 356     # . . discard args
- 357     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 358     # check-ints-equal(EAX, 0, msg)
- 359     # . . push args
- 360     68/push  "F - test-slice-equal-with-empty"/imm32
- 361     68/push  0/imm32
- 362     50/push-EAX
- 363     # . . call
- 364     e8/call  check-ints-equal/disp32
- 365     # . . discard args
- 366     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 367     # . epilog
- 368     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 369     5d/pop-to-EBP
- 370     c3/return
- 371 
- 372 test-slice-equal-empty-with-empty:
- 373     # - slice-equal?(slice(""), "") == 1
- 374     # . prolog
- 375     55/push-EBP
- 376     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 377     # var slice/ECX
- 378     68/push  _test-slice-data-0/imm32/end
- 379     68/push  _test-slice-data-0/imm32/start
- 380     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
- 381     # EAX = slice-equal?(ECX, "")
- 382     # . . push args
- 383     68/push  ""/imm32
- 384     51/push-ECX
- 385     # . . call
- 386     e8/call  slice-equal?/disp32
- 387     # . . discard args
- 388     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 389     # check-ints-equal(EAX, 1, msg)
- 390     # . . push args
- 391     68/push  "F - test-slice-equal-empty-with-empty"/imm32
- 392     68/push  1/imm32
- 393     50/push-EAX
- 394     # . . call
- 395     e8/call  check-ints-equal/disp32
- 396     # . . discard args
- 397     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 398     # . epilog
- 399     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 400     5d/pop-to-EBP
- 401     c3/return
- 402 
- 403 test-slice-equal-with-null:
- 404     # - slice-equal?(slice("Ab"), null) == 0
- 405     # . prolog
- 406     55/push-EBP
- 407     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 408     # var slice/ECX
- 409     68/push  _test-slice-data-2/imm32/end
- 410     68/push  _test-slice-data-0/imm32/start
- 411     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
- 412     # EAX = slice-equal?(ECX, 0)
- 413     # . . push args
- 414     68/push  0/imm32
- 415     51/push-ECX
- 416     # . . call
- 417     e8/call  slice-equal?/disp32
- 418     # . . discard args
- 419     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 420     # check-ints-equal(EAX, 0, msg)
- 421     # . . push args
- 422     68/push  "F - test-slice-equal-with-null"/imm32
- 423     68/push  0/imm32
- 424     50/push-EAX
- 425     # . . call
- 426     e8/call  check-ints-equal/disp32
- 427     # . . discard args
- 428     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 429     # . epilog
- 430     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 431     5d/pop-to-EBP
- 432     c3/return
- 433 
- 434 slice-starts-with?:  # s : (address slice), head : (address string) -> EAX : boolean
- 435     # pseudocode
- 436     #   lenh = head->length
- 437     #   if (lenh > s->end - s->start) return false
- 438     #   i = 0
- 439     #   currs = s->start
- 440     #   currp = head->data
- 441     #   while i < lenh
- 442     #     if (*currs != *currh) return false
- 443     #     ++i
- 444     #     ++currs
- 445     #     ++currh
- 446     #   return true
- 447     #
- 448     # registers:
- 449     #   currs: ESI
- 450     #   currh: EDI
- 451     #   *currs: EAX
- 452     #   *currh: EBX
- 453     #   i: ECX
- 454     #   lenh: EDX
- 455     #
- 456     # . prolog
- 457     55/push-EBP
- 458     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 459     # . save registers
- 460     51/push-ECX
- 461     52/push-EDX
- 462     53/push-EBX
- 463     56/push-ESI
- 464     57/push-EDI
- 465     # ESI = s
- 466     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
- 467     # ECX = s->end - s->start
- 468     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
- 469     2b/subtract                     0/mod/indirect  6/rm32/ESI    .           .             .           1/r32/ECX   .               .                 # subtract *ESI from ECX
- 470     # EDI = head
- 471     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   0xc/disp8       .                 # copy *(EBP+12) to EDI
- 472     # lenh/EDX = head->length
- 473     8b/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           2/r32/EDX   .               .                 # copy *EDI to EDX
- 474     # if (lenh > s->end - s->start) return false
- 475     39/compare                      3/mod/direct    2/rm32/EDX    .           .             .           1/r32/ECX   .               .                 # compare EDX with ECX
- 476     7f/jump-if-greater  $slice-starts-with?:false/disp8
- 477     # currs/ESI = s->start
- 478     8b/subtract                     0/mod/indirect  6/rm32/ESI    .           .             .           6/r32/ESI   .               .                 # copy *ESI to ESI
- 479     # currh/EDI = head->data
- 480     81          0/subop/add         3/mod/direct    7/rm32/EDI    .           .             .           .           .               4/imm32           # add to EDI
- 481     # i/ECX = 0
- 482     31/xor                          3/mod/direct    1/rm32/ECX    .           .             .           1/r32/ECX   .               .                 # clear ECX
- 483     # EAX = EBX = 0
- 484     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
- 485     31/xor                          3/mod/direct    3/rm32/EBX    .           .             .           3/r32/EBX   .               .                 # clear EBX
- 486 $slice-starts-with?:loop:
- 487     # if (i >= lenh) return true
- 488     39/compare                      3/mod/direct    1/rm32/ECX    .           .             .           2/r32/EDX   .               .                 # compare ECX with EDX
- 489     7d/jump-if-greater-or-equal  $slice-starts-with?:true/disp8
- 490     # AL = *currs
- 491     8a/copy-byte                    0/mod/indirect  6/rm32/ESI    .           .             .           0/r32/AL    .               .                 # copy byte at *ESI to AL
- 492     # BL = *currh
- 493     8a/copy-byte                    0/mod/indirect  7/rm32/EDI    .           .             .           3/r32/BL    .               .                 # copy byte at *EDI to BL
- 494     # if (*currs != *currh) return false
- 495     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           3/r32/EBX   .               .                 # compare EAX and EBX
- 496     75/jump-if-not-equal  $slice-starts-with?:false/disp8
- 497     # ++i
- 498     41/increment-ECX
- 499     # ++currs
- 500     46/increment-ESI
- 501     # ++currh
- 502     47/increment-EDI
- 503     eb/jump $slice-starts-with?:loop/disp8
- 504 $slice-starts-with?:true:
- 505     b8/copy-to-EAX  1/imm32
- 506     eb/jump  $slice-starts-with?:end/disp8
- 507 $slice-starts-with?:false:
- 508     b8/copy-to-EAX  0/imm32
- 509 $slice-starts-with?:end:
- 510     # . restore registers
- 511     5f/pop-to-EDI
- 512     5e/pop-to-ESI
- 513     5b/pop-to-EBX
- 514     5a/pop-to-EDX
- 515     59/pop-to-ECX
- 516     # . epilog
- 517     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 518     5d/pop-to-EBP
- 519     c3/return
- 520 
- 521 test-slice-starts-with-single-character:
- 522     # - slice-starts-with?(slice("Abc"), "A") == 1
- 523     # . prolog
- 524     55/push-EBP
- 525     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 526     # var slice/ECX
- 527     68/push  _test-slice-data-3/imm32/end
- 528     68/push  _test-slice-data-0/imm32/start
- 529     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
- 530     # EAX = slice-starts-with?(ECX, "A")
- 531     # . . push args
- 532     68/push  "A"/imm32
- 533     51/push-ECX
- 534     # . . call
- 535     e8/call  slice-starts-with?/disp32
- 536     # . . discard args
- 537     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 538     # check-ints-equal(EAX, 1, msg)
- 539     # . . push args
- 540     68/push  "F - test-slice-starts-with-single-character"/imm32
- 541     68/push  1/imm32
- 542     50/push-EAX
- 543     # . . call
- 544     e8/call  check-ints-equal/disp32
- 545     # . . discard args
- 546     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 547     # . epilog
- 548     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 549     5d/pop-to-EBP
- 550     c3/return
- 551 
- 552 test-slice-starts-with-empty-string:
- 553     # - slice-starts-with?(slice("Abc"), "") == 1
- 554     # . prolog
- 555     55/push-EBP
- 556     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 557     # var slice/ECX
- 558     68/push  _test-slice-data-3/imm32/end
- 559     68/push  _test-slice-data-0/imm32/start
- 560     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
- 561     # EAX = slice-starts-with?(ECX, "")
- 562     # . . push args
- 563     68/push  ""/imm32
- 564     51/push-ECX
- 565     # . . call
- 566     e8/call  slice-starts-with?/disp32
- 567     # . . discard args
- 568     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 569     # check-ints-equal(EAX, 1, msg)
- 570     # . . push args
- 571     68/push  "F - test-slice-starts-with-empty-string"/imm32
- 572     68/push  1/imm32
- 573     50/push-EAX
- 574     # . . call
- 575     e8/call  check-ints-equal/disp32
- 576     # . . discard args
- 577     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 578     # . epilog
- 579     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 580     5d/pop-to-EBP
- 581     c3/return
- 582 
- 583 test-slice-starts-with-multiple-characters:
- 584     # - slice-starts-with?(slice("Abc"), "Ab") == 1
- 585     # . prolog
- 586     55/push-EBP
- 587     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 588     # var slice/ECX
- 589     68/push  _test-slice-data-3/imm32/end
- 590     68/push  _test-slice-data-0/imm32/start
- 591     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
- 592     # EAX = slice-starts-with?(ECX, "Ab")
- 593     # . . push args
- 594     68/push  "Ab"/imm32
- 595     51/push-ECX
- 596     # . . call
- 597     e8/call  slice-starts-with?/disp32
- 598     # . . discard args
- 599     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 600     # check-ints-equal(EAX, 1, msg)
- 601     # . . push args
- 602     68/push  "F - test-slice-starts-with-multiple-characters"/imm32
- 603     68/push  1/imm32
- 604     50/push-EAX
- 605     # . . call
- 606     e8/call  check-ints-equal/disp32
- 607     # . . discard args
- 608     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 609     # . epilog
- 610     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 611     5d/pop-to-EBP
- 612     c3/return
- 613 
- 614 test-slice-starts-with-entire-string:
- 615     # - slice-starts-with?(slice("Abc"), "Abc") == 1
- 616     # . prolog
- 617     55/push-EBP
- 618     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 619     # var slice/ECX
- 620     68/push  _test-slice-data-3/imm32/end
- 621     68/push  _test-slice-data-0/imm32/start
- 622     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
- 623     # EAX = slice-starts-with?(ECX, "Abc")
- 624     # . . push args
- 625     68/push  "Abc"/imm32
- 626     51/push-ECX
- 627     # . . call
- 628     e8/call  slice-starts-with?/disp32
- 629     # . . discard args
- 630     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 631     # check-ints-equal(EAX, 1, msg)
- 632     # . . push args
- 633     68/push  "F - test-slice-starts-with-entire-string"/imm32
- 634     68/push  1/imm32
- 635     50/push-EAX
- 636     # . . call
- 637     e8/call  check-ints-equal/disp32
- 638     # . . discard args
- 639     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 640     # . epilog
- 641     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 642     5d/pop-to-EBP
- 643     c3/return
- 644 
- 645 test-slice-starts-with-fails:
- 646     # - slice-starts-with?(slice("Abc"), "Abd") == 1
- 647     # . prolog
- 648     55/push-EBP
- 649     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 650     # var slice/ECX
- 651     68/push  _test-slice-data-3/imm32/end
- 652     68/push  _test-slice-data-0/imm32/start
- 653     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
- 654     # EAX = slice-starts-with?(ECX, "Abd")
- 655     # . . push args
- 656     68/push  "Abd"/imm32
- 657     51/push-ECX
- 658     # . . call
- 659     e8/call  slice-starts-with?/disp32
- 660     # . . discard args
- 661     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 662     # check-ints-equal(EAX, 0, msg)
- 663     # . . push args
- 664     68/push  "F - test-slice-starts-with-fails"/imm32
- 665     68/push  0/imm32
- 666     50/push-EAX
- 667     # . . call
- 668     e8/call  check-ints-equal/disp32
- 669     # . . discard args
- 670     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 671     # . epilog
- 672     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 673     5d/pop-to-EBP
- 674     c3/return
- 675 
- 676 test-slice-starts-with-fails-2:
- 677     # - slice-starts-with?(slice("Abc"), "Ac") == 1
- 678     # . prolog
- 679     55/push-EBP
- 680     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 681     # var slice/ECX
- 682     68/push  _test-slice-data-3/imm32/end
- 683     68/push  _test-slice-data-0/imm32/start
- 684     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
- 685     # EAX = slice-starts-with?(ECX, "Ac")
- 686     # . . push args
- 687     68/push  "Ac"/imm32
- 688     51/push-ECX
- 689     # . . call
- 690     e8/call  slice-starts-with?/disp32
- 691     # . . discard args
- 692     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 693     # check-ints-equal(EAX, 0, msg)
- 694     # . . push args
- 695     68/push  "F - test-slice-starts-with-fails-2"/imm32
- 696     68/push  0/imm32
- 697     50/push-EAX
- 698     # . . call
- 699     e8/call  check-ints-equal/disp32
- 700     # . . discard args
- 701     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 702     # . epilog
- 703     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 704     5d/pop-to-EBP
- 705     c3/return
- 706 
- 707 write-slice:  # out : (address buffered-file), s : (address slice)
- 708     # . prolog
- 709     55/push-EBP
- 710     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 711     # . save registers
- 712     50/push-EAX
- 713     51/push-ECX
- 714     52/push-EDX
- 715     53/push-EBX
- 716     56/push-ESI
- 717     57/push-EDI
- 718     # ESI = s
- 719     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   0xc/disp8       .                 # copy *(EBP+12) to ESI
- 720     # curr/ECX = s->start
- 721     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           1/r32/ECX   .               .                 # copy *ESI to ECX
- 722     # max/ESI = s->end
- 723     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           6/r32/ESI   4/disp8         .                 # copy *(ESI+4) to ESI
- 724     # EDI = out
- 725     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .                         7/r32/EDI   8/disp8         .                 # copy *(EBP+8) to EDI
- 726     # EDX = out->length
- 727     8b/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           2/r32/EDX   0xc/disp8       .                 # copy *(EDI+12) to EDX
- 728     # EBX = out->write
- 729     8b/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           3/r32/EBX   4/disp8         .                 # copy *(EDI+4) to EBX
- 730 $write-slice:loop:
- 731     # if (curr >= max) break
- 732     39/compare                      3/mod/direct    1/rm32/ECX    .           .             .           6/r32/ESI   .               .                 # compare ECX with ESI
- 733     7d/jump-if-greater-or-equal  $write-slice:loop-end/disp8
- 734     # if (out->write >= out->length) flush and clear out's stream
- 735     39/compare                      3/mod/direct    3/rm32/EBX    .           .             .           2/r32/EDX   .               .                 # compare EBX with EDX
- 736     7c/jump-if-lesser  $write-slice:to-stream/disp8
- 737     # . persist out->write
- 738     89/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           3/r32/EBX   4/disp8         .                 # copy EBX to *(EDI+4)
- 739     # . flush(out)
- 740     # . . push args
- 741     57/push-EDI
- 742     # . . call
- 743     e8/call  flush/disp32
- 744     # . . discard args
- 745     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 746     # . clear-stream(stream = out+4)
- 747     # . . push args
- 748     8d/copy-address                 1/mod/*+disp8   7/rm32/EDI    .           .             .           0/r32/EAX   4/disp8         .                 # copy EDI+4 to EAX
- 749     50/push-EAX
- 750     # . . call
- 751     e8/call  clear-stream/disp32
- 752     # . . discard args
- 753     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 754     # . out->write must now be 0; update its cache at EBX
- 755     31/xor                          3/mod/direct    3/rm32/EBX    .           .             .           3/r32/EBX   .               .                 # clear EBX
- 756 $write-slice:to-stream:
- 757     # out->data[out->write] = *in
- 758     # . AL = *in
- 759     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
- 760     8a/copy-byte                    0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/AL    .               .                 # copy byte at *ECX to AL
- 761     # . out->data[out->write] = AL
- 762     88/copy-byte                    1/mod/*+disp8   4/rm32/sib    7/base/EDI  3/index/EBX   .           0/r32/AL    0x10/disp8      .                 # copy AL to *(EDI+EBX+16)
- 763     # ++out->write
- 764     43/increment-EBX
- 765     # ++in
- 766     41/increment-ECX
- 767     eb/jump  $write-slice:loop/disp8
- 768 $write-slice:loop-end:
- 769     # persist necessary variables from registers
- 770     89/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           3/r32/EBX   4/disp8         .                 # copy EBX to *(EDI+4)
- 771 $write-slice:end:
- 772     # . restore registers
- 773     5f/pop-to-EDI
- 774     5e/pop-to-ESI
- 775     5b/pop-to-EBX
- 776     5a/pop-to-EDX
- 777     59/pop-to-ECX
- 778     58/pop-to-EAX
- 779     # . epilog
- 780     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 781     5d/pop-to-EBP
- 782     c3/return
- 783 
- 784 test-write-slice:
- 785     # . prolog
- 786     55/push-EBP
- 787     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 788     # setup
- 789     # . clear-stream(_test-stream)
- 790     # . . push args
- 791     68/push  _test-stream/imm32
- 792     # . . call
- 793     e8/call  clear-stream/disp32
- 794     # . . discard args
- 795     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 796     # . clear-stream(_test-buffered-file+4)
- 797     # . . push args
- 798     b8/copy-to-EAX  _test-buffered-file/imm32
- 799     05/add-to-EAX  4/imm32
- 800     50/push-EAX
- 801     # . . call
- 802     e8/call  clear-stream/disp32
- 803     # . . discard args
- 804     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 805     # var slice/ECX = "Abc"
- 806     68/push  _test-slice-data-3/imm32/end
- 807     68/push  _test-slice-data-0/imm32/start
- 808     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
- 809     # write-slice(_test-buffered-file, slice)
- 810     # . . push args
- 811     51/push-ECX
- 812     68/push  _test-buffered-file/imm32
- 813     # . . call
- 814     e8/call  write-slice/disp32
- 815     # . . discard args
- 816     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 817     # flush(_test-buffered-file)
- 818     # . . push args
- 819     68/push  _test-buffered-file/imm32
- 820     # . . call
- 821     e8/call  flush/disp32
- 822     # . . discard args
- 823     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
- 824     # check-stream-equal(_test-stream, "Abc", msg)
- 825     # . . push args
- 826     68/push  "F - test-write-slice"/imm32
- 827     68/push  "Abc"/imm32
- 828     68/push  _test-stream/imm32
- 829     # . . call
- 830     e8/call  check-stream-equal/disp32
- 831     # . . discard args
- 832     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 833     # . epilog
- 834     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 835     5d/pop-to-EBP
- 836     c3/return
- 837 
- 838 # copy a slice into a new (dynamically allocated) string
- 839 slice-to-string:  # ad : (address allocation-descriptor), in : (address slice) -> out/EAX : (address array)
- 840     # . prolog
- 841     55/push-EBP
- 842     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 843     # . save registers
- 844     51/push-ECX
- 845     52/push-EDX
- 846     53/push-EBX
- 847     56/push-ESI
- 848     # ESI = in
- 849     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   0xc/disp8       .                 # copy *(EBP+12) to ESI
- 850     # curr/EDX = in->start
- 851     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           2/r32/EDX   .               .                 # copy *ESI to EDX
- 852     # max/EBX = in->end
- 853     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           3/r32/EBX   4/disp8         .                 # copy *(ESI+4) to EBX
- 854     # size/ECX = max - curr + 4  # total size of output string (including the initial length)
- 855     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           3/r32/EBX   .               .                 # copy EBX to ECX
- 856     29/subtract                     3/mod/direct    1/rm32/ECX    .           .             .           2/r32/EDX   .               .                 # subtract EDX from ECX
- 857     81          0/subop/add         3/mod/direct    1/rm32/ECX    .           .             .           .           .               4/imm32           # add to ECX
- 858     # out/EAX = allocate(ad, size)
- 859     # . . push args
- 860     51/push-ECX
- 861     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
- 862     # . . call
- 863     e8/call  allocate/disp32
- 864     # . . discard args
- 865     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 866     # if (EAX == 0) abort
- 867     3d/compare-EAX-and  0/imm32
- 868     74/jump-if-equal  $slice-to-string:abort/disp8
- 869     # *out = size-4
- 870     89/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # copy ECX to *EAX
- 871     81          5/subop/subtract    0/mod/indirect  0/rm32/EAX    .           .             .           .           .               4/imm32           # subtract 4 from *EAX
- 872     # save out
- 873     50/push-EAX
- 874     # EAX = _append-4(EAX+4, EAX+size, curr, max)  # clobbering ECX
- 875     # . . push args
- 876     53/push-EBX
- 877     52/push-EDX
- 878     # . . push EAX+size (clobbering ECX)
- 879     01/add                          3/mod/direct    1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # add EAX to ECX
- 880     51/push-ECX
- 881     # . . push EAX+4 (clobbering EAX)
- 882     81          0/subop/add         3/mod/direct    0/rm32/EAX    .           .             .           .           .               4/imm32           # add to EAX
- 883     50/push-EAX
- 884     # . . call
- 885     e8/call  _append-4/disp32
- 886     # . . discard args
- 887     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0x10/imm32        # add to ESP
- 888     # restore out (assumes _append-4 can't error)
- 889     58/pop-to-EAX
- 890 $slice-to-string:end:
- 891     # . restore registers
- 892     5e/pop-to-ESI
- 893     5b/pop-to-EBX
- 894     5a/pop-to-EDX
- 895     59/pop-to-ECX
- 896     # . epilog
- 897     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 898     5d/pop-to-EBP
- 899     c3/return
- 900 
- 901 $slice-to-string:abort:
- 902     # . _write(2/stderr, error)
- 903     # . . push args
- 904     68/push  "slice-to-string: out of space"/imm32
- 905     68/push  2/imm32/stderr
- 906     # . . call
- 907     e8/call  _write/disp32
- 908     # . . discard args
- 909     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 910     # . syscall(exit, 1)
- 911     bb/copy-to-EBX  1/imm32
- 912     b8/copy-to-EAX  1/imm32/exit
- 913     cd/syscall  0x80/imm8
- 914     # never gets here
- 915 
- 916 test-slice-to-string:
- 917     # . prolog
- 918     55/push-EBP
- 919     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
- 920     # var slice/ECX = "Abc"
- 921     68/push  _test-slice-data-3/imm32/end
- 922     68/push  _test-slice-data-0/imm32/start
- 923     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
- 924     # EAX = slice-to-string(Heap, slice)
- 925     # . . push args
- 926     51/push-ECX
- 927     68/push  Heap/imm32
- 928     # . . call
- 929     e8/call  slice-to-string/disp32
- 930     # . . discard args
- 931     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 932 +-- 34 lines: #?     # dump word-slice -----------------------------------------------------------------------------------------------------------------------
- 966     # EAX = string-equal?(EAX, "Abc")
- 967     # . . push args
- 968     68/push  "Abc"/imm32
- 969     50/push-EAX
- 970     # . . call
- 971     e8/call  string-equal?/disp32
- 972     # . . discard args
- 973     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
- 974     # check-ints-equal(EAX, 1, msg)
- 975     # . . push args
- 976     68/push  "F - test-slice-to-string"/imm32
- 977     68/push  1/imm32/true
- 978     50/push-EAX
- 979     # . . call
- 980     e8/call  check-ints-equal/disp32
- 981     # . . discard args
- 982     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
- 983     # . epilog
- 984     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
- 985     5d/pop-to-EBP
- 986     c3/return
- 987 
- 988 == data
- 989 
- 990 _test-slice-data-0:
- 991     41/A
- 992 _test-slice-data-1:
- 993     62/b
- 994 _test-slice-data-2:
- 995     63/c
- 996 _test-slice-data-3:
- 997     64/d
- 998 _test-slice-data-4:
- 999 
-1000 # . _. vim:nowrap:textwidth=0
+  1 # new data structure: a slice is an open interval of addresses [start, end)
+  2 # that includes 'start' but not 'end'
+  3 
+  4 == code
+  5 #   instruction                     effective address                                                   register    displacement    immediate
+  6 # . op          subop               mod             rm32          base        index         scale       r32
+  7 # . 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
+  8 
+  9 #? Entry:  # run a single test, while debugging
+ 10 #?     e8/call test-slice-to-string/disp32
+ 11 #?     # syscall(exit, Num-test-failures)
+ 12 #?     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
+ 13 #?     b8/copy-to-EAX  1/imm32/exit
+ 14 #?     cd/syscall  0x80/imm8
+ 15 
+ 16 slice-empty?:  # s : (address slice) -> EAX : boolean
+ 17     # . prolog
+ 18     55/push-EBP
+ 19     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 20     # . save registers
+ 21     51/push-ECX
+ 22     # ECX = s
+ 23     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           1/r32/ECX   8/disp8         .                 # copy *(EBP+8) to ECX
+ 24     # if (s->start == s->end) return true
+ 25     # . EAX = s->start
+ 26     8b/copy                         0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # copy *ECX to EAX
+ 27     # . compare EAX and s->end
+ 28     39/compare                      1/mod/*+disp8   1/rm32/ECX    .           .             .           0/r32/EAX   4/disp8         .                 # compare EAX and *(ECX+4)
+ 29     b8/copy-to-EAX  1/imm32/true
+ 30     74/jump-if-equal  $slice-empty?:end/disp8
+ 31     b8/copy-to-EAX  0/imm32/false
+ 32 $slice-empty?:end:
+ 33     # . restore registers
+ 34     59/pop-to-ECX
+ 35     # . epilog
+ 36     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 37     5d/pop-to-EBP
+ 38     c3/return
+ 39 
+ 40 test-slice-empty-true:
+ 41     # . prolog
+ 42     55/push-EBP
+ 43     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 44     # var slice/ECX = {34, 34}
+ 45     68/push  34/imm32/end
+ 46     68/push  34/imm32/start
+ 47     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+ 48     # slice-empty?(slice)
+ 49     # . . push args
+ 50     51/push-ECX
+ 51     # . . call
+ 52     e8/call  slice-empty?/disp32
+ 53     # . . discard args
+ 54     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 55     # check-ints-equal(EAX, 1, msg)
+ 56     # . . push args
+ 57     68/push  "F - test-slice-empty-true"/imm32
+ 58     68/push  1/imm32
+ 59     50/push-EAX
+ 60     # . . call
+ 61     e8/call  check-ints-equal/disp32
+ 62     # . . discard args
+ 63     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 64     # . epilog
+ 65     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 66     5d/pop-to-EBP
+ 67     c3/return
+ 68 
+ 69 test-slice-empty-false:
+ 70     # . prolog
+ 71     55/push-EBP
+ 72     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 73     # var slice/ECX = {34, 23}
+ 74     68/push  23/imm32/end
+ 75     68/push  34/imm32/start
+ 76     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+ 77     # slice-empty?(slice)
+ 78     # . . push args
+ 79     51/push-ECX
+ 80     # . . call
+ 81     e8/call  slice-empty?/disp32
+ 82     # . . discard args
+ 83     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 84     # check-ints-equal(EAX, 0, msg)
+ 85     # . . push args
+ 86     68/push  "F - test-slice-empty-false"/imm32
+ 87     68/push  0/imm32
+ 88     50/push-EAX
+ 89     # . . call
+ 90     e8/call  check-ints-equal/disp32
+ 91     # . . discard args
+ 92     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 93     # . epilog
+ 94     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 95     5d/pop-to-EBP
+ 96     c3/return
+ 97 
+ 98 slice-equal?:  # s : (address slice), p : (address string) -> EAX : boolean
+ 99     # pseudocode:
+100     #   if (p == 0) return (s == 0)
+101     #   currs = s->start
+102     #   maxs = s->end
+103     #   if (maxs - currs != p->length) return false
+104     #   currp = p->data
+105     #   while currs < maxs
+106     #     if (*currs != *currp) return false
+107     #     ++currs
+108     #     ++currp
+109     #   return true
+110     #
+111     # registers:
+112     #   currs: EDX
+113     #   maxs: ESI
+114     #   currp: EBX
+115     #   *currs: EAX
+116     #   *currp: ECX
+117     #
+118     # . prolog
+119     55/push-EBP
+120     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+121     # . save registers
+122     51/push-ECX
+123     52/push-EDX
+124     53/push-EBX
+125     56/push-ESI
+126     # ESI = s
+127     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
+128     # currs/EDX = s->start
+129     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           2/r32/EDX   .               .                 # copy *ESI to EDX
+130     # maxs/ESI = s->end
+131     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           6/r32/ESI   4/disp8         .                 # copy *(ESI+4) to ESI
+132     # EAX = maxs - currs
+133     89/copy                         3/mod/direct    0/rm32/EAX    .           .             .           6/r32/ESI   .               .                 # copy ESI to EAX
+134     29/subtract                     3/mod/direct    0/rm32/EAX    .           .             .           2/r32/EDX   .               .                 # subtract EDX from EAX
+135     # EBX = p
+136     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           3/r32/EBX   0xc/disp8       .                 # copy *(EBP+12) to EBX
+137     # if (p != 0) goto next check
+138     81          7/subop/compare     3/mod/direct    3/rm32/EBX    .           .             .           .           .               0/imm32           # compare EBX
+139     75/jump-if-not-equal  $slice-equal?:nonnull-string/disp8
+140 $slice-equal?:null-string:
+141     # return s->start == s->end
+142     3d/compare-EAX-and  0/imm32
+143     74/jump-if-equal  $slice-equal?:true/disp8
+144     eb/jump  $slice-equal?:false/disp8
+145 $slice-equal?:nonnull-string:
+146     # if (EAX != p->length) return false
+147     39/compare                      0/mod/indirect  3/rm32/EBX    .           .             .           0/r32/EAX   .               .                 # compare *EBX and EAX
+148     75/jump-if-not-equal  $slice-equal?:false/disp8
+149     # currp/EBX = p->data
+150     81          0/subop/add         3/mod/direct    3/rm32/EBX    .           .             .           .           .               4/imm32           # add to EBX
+151     # EAX = ECX = 0
+152     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
+153     31/xor                          3/mod/direct    1/rm32/ECX    .           .             .           1/r32/ECX   .               .                 # clear ECX
+154 $slice-equal?:loop:
+155     # if (currs >= maxs) return true
+156     39/compare                      3/mod/direct    2/rm32/EDX    .           .             .           6/r32/ESI   .               .                 # compare EDX with ESI
+157     7d/jump-if-greater-or-equal  $slice-equal?:true/disp8
+158     # AL = *currp
+159     8a/copy-byte                    0/mod/indirect  3/rm32/EBX    .           .             .           0/r32/AL    .               .                 # copy byte at *EBX to AL
+160     # CL = *currs
+161     8a/copy-byte                    0/mod/indirect  2/rm32/EDX    .           .             .           1/r32/CL    .               .                 # copy byte at *EDX to CL
+162     # if (EAX != ECX) return false
+163     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # compare EAX and ECX
+164     75/jump-if-not-equal  $slice-equal?:false/disp8
+165     # ++currp
+166     43/increment-EBX
+167     # ++currs
+168     42/increment-EDX
+169     eb/jump $slice-equal?:loop/disp8
+170 $slice-equal?:false:
+171     b8/copy-to-EAX  0/imm32
+172     eb/jump  $slice-equal?:end/disp8
+173 $slice-equal?:true:
+174     b8/copy-to-EAX  1/imm32
+175 $slice-equal?:end:
+176     # . restore registers
+177     5e/pop-to-ESI
+178     5b/pop-to-EBX
+179     5a/pop-to-EDX
+180     59/pop-to-ECX
+181     # . epilog
+182     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+183     5d/pop-to-EBP
+184     c3/return
+185 
+186 test-slice-equal:
+187     # - slice-equal?(slice("Abc"), "Abc") == 1
+188     # . prolog
+189     55/push-EBP
+190     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+191     # var slice/ECX
+192     68/push  _test-slice-data-3/imm32/end
+193     68/push  _test-slice-data-0/imm32/start
+194     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+195     # EAX = slice-equal?(ECX, "Abc")
+196     # . . push args
+197     68/push  "Abc"/imm32
+198     51/push-ECX
+199     # . . call
+200     e8/call  slice-equal?/disp32
+201     # . . discard args
+202     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+203     # check-ints-equal(EAX, 1, msg)
+204     # . . push args
+205     68/push  "F - test-slice-equal"/imm32
+206     68/push  1/imm32
+207     50/push-EAX
+208     # . . call
+209     e8/call  check-ints-equal/disp32
+210     # . . discard args
+211     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+212     # . epilog
+213     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+214     5d/pop-to-EBP
+215     c3/return
+216 
+217 test-slice-equal-false:
+218     # - slice-equal?(slice("bcd"), "Abc") == 0
+219     # . prolog
+220     55/push-EBP
+221     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+222     # var slice/ECX
+223     68/push  _test-slice-data-4/imm32/end
+224     68/push  _test-slice-data-1/imm32/start
+225     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+226     # EAX = slice-equal?(ECX, "Abc")
+227     # . . push args
+228     68/push  "Abc"/imm32
+229     51/push-ECX
+230     # . . call
+231     e8/call  slice-equal?/disp32
+232     # . . discard args
+233     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+234     # check-ints-equal(EAX, 0, msg)
+235     # . . push args
+236     68/push  "F - test-slice-equal-false"/imm32
+237     68/push  0/imm32
+238     50/push-EAX
+239     # . . call
+240     e8/call  check-ints-equal/disp32
+241     # . . discard args
+242     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+243     # . epilog
+244     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+245     5d/pop-to-EBP
+246     c3/return
+247 
+248 test-slice-equal-too-long:
+249     # - slice-equal?(slice("Abcd"), "Abc") == 0
+250     # . prolog
+251     55/push-EBP
+252     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+253     # var slice/ECX
+254     68/push  _test-slice-data-4/imm32/end
+255     68/push  _test-slice-data-0/imm32/start
+256     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+257     # EAX = slice-equal?(ECX, "Abc")
+258     # . . push args
+259     68/push  "Abc"/imm32
+260     51/push-ECX
+261     # . . call
+262     e8/call  slice-equal?/disp32
+263     # . . discard args
+264     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+265     # check-ints-equal(EAX, 0, msg)
+266     # . . push args
+267     68/push  "F - test-slice-equal-too-long"/imm32
+268     68/push  0/imm32
+269     50/push-EAX
+270     # . . call
+271     e8/call  check-ints-equal/disp32
+272     # . . discard args
+273     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+274     # . epilog
+275     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+276     5d/pop-to-EBP
+277     c3/return
+278 
+279 test-slice-equal-too-short:
+280     # - slice-equal?(slice("A"), "Abc") == 0
+281     # . prolog
+282     55/push-EBP
+283     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+284     # var slice/ECX
+285     68/push  _test-slice-data-1/imm32/end
+286     68/push  _test-slice-data-0/imm32/start
+287     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+288     # EAX = slice-equal?(ECX, "Abc")
+289     # . . push args
+290     68/push  "Abc"/imm32
+291     51/push-ECX
+292     # . . call
+293     e8/call  slice-equal?/disp32
+294     # . . discard args
+295     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+296     # check-ints-equal(EAX, 0, msg)
+297     # . . push args
+298     68/push  "F - test-slice-equal-too-short"/imm32
+299     68/push  0/imm32
+300     50/push-EAX
+301     # . . call
+302     e8/call  check-ints-equal/disp32
+303     # . . discard args
+304     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+305     # . epilog
+306     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+307     5d/pop-to-EBP
+308     c3/return
+309 
+310 test-slice-equal-empty:
+311     # - slice-equal?(slice(""), "Abc") == 0
+312     # . prolog
+313     55/push-EBP
+314     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+315     # var slice/ECX
+316     68/push  _test-slice-data-0/imm32/end
+317     68/push  _test-slice-data-0/imm32/start
+318     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+319     # EAX = slice-equal?(ECX, "Abc")
+320     # . . push args
+321     68/push  "Abc"/imm32
+322     51/push-ECX
+323     # . . call
+324     e8/call  slice-equal?/disp32
+325     # . . discard args
+326     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+327     # check-ints-equal(EAX, 0, msg)
+328     # . . push args
+329     68/push  "F - test-slice-equal-empty"/imm32
+330     68/push  0/imm32
+331     50/push-EAX
+332     # . . call
+333     e8/call  check-ints-equal/disp32
+334     # . . discard args
+335     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+336     # . epilog
+337     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+338     5d/pop-to-EBP
+339     c3/return
+340 
+341 test-slice-equal-with-empty:
+342     # - slice-equal?(slice("Ab"), "") == 0
+343     # . prolog
+344     55/push-EBP
+345     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+346     # var slice/ECX
+347     68/push  _test-slice-data-2/imm32/end
+348     68/push  _test-slice-data-0/imm32/start
+349     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+350     # EAX = slice-equal?(ECX, "")
+351     # . . push args
+352     68/push  ""/imm32
+353     51/push-ECX
+354     # . . call
+355     e8/call  slice-equal?/disp32
+356     # . . discard args
+357     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+358     # check-ints-equal(EAX, 0, msg)
+359     # . . push args
+360     68/push  "F - test-slice-equal-with-empty"/imm32
+361     68/push  0/imm32
+362     50/push-EAX
+363     # . . call
+364     e8/call  check-ints-equal/disp32
+365     # . . discard args
+366     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+367     # . epilog
+368     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+369     5d/pop-to-EBP
+370     c3/return
+371 
+372 test-slice-equal-empty-with-empty:
+373     # - slice-equal?(slice(""), "") == 1
+374     # . prolog
+375     55/push-EBP
+376     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+377     # var slice/ECX
+378     68/push  _test-slice-data-0/imm32/end
+379     68/push  _test-slice-data-0/imm32/start
+380     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+381     # EAX = slice-equal?(ECX, "")
+382     # . . push args
+383     68/push  ""/imm32
+384     51/push-ECX
+385     # . . call
+386     e8/call  slice-equal?/disp32
+387     # . . discard args
+388     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+389     # check-ints-equal(EAX, 1, msg)
+390     # . . push args
+391     68/push  "F - test-slice-equal-empty-with-empty"/imm32
+392     68/push  1/imm32
+393     50/push-EAX
+394     # . . call
+395     e8/call  check-ints-equal/disp32
+396     # . . discard args
+397     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+398     # . epilog
+399     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+400     5d/pop-to-EBP
+401     c3/return
+402 
+403 test-slice-equal-with-null:
+404     # - slice-equal?(slice("Ab"), null) == 0
+405     # . prolog
+406     55/push-EBP
+407     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+408     # var slice/ECX
+409     68/push  _test-slice-data-2/imm32/end
+410     68/push  _test-slice-data-0/imm32/start
+411     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+412     # EAX = slice-equal?(ECX, 0)
+413     # . . push args
+414     68/push  0/imm32
+415     51/push-ECX
+416     # . . call
+417     e8/call  slice-equal?/disp32
+418     # . . discard args
+419     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+420     # check-ints-equal(EAX, 0, msg)
+421     # . . push args
+422     68/push  "F - test-slice-equal-with-null"/imm32
+423     68/push  0/imm32
+424     50/push-EAX
+425     # . . call
+426     e8/call  check-ints-equal/disp32
+427     # . . discard args
+428     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+429     # . epilog
+430     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+431     5d/pop-to-EBP
+432     c3/return
+433 
+434 slice-starts-with?:  # s : (address slice), head : (address string) -> EAX : boolean
+435     # pseudocode
+436     #   lenh = head->length
+437     #   if (lenh > s->end - s->start) return false
+438     #   i = 0
+439     #   currs = s->start
+440     #   currp = head->data
+441     #   while i < lenh
+442     #     if (*currs != *currh) return false
+443     #     ++i
+444     #     ++currs
+445     #     ++currh
+446     #   return true
+447     #
+448     # registers:
+449     #   currs: ESI
+450     #   currh: EDI
+451     #   *currs: EAX
+452     #   *currh: EBX
+453     #   i: ECX
+454     #   lenh: EDX
+455     #
+456     # . prolog
+457     55/push-EBP
+458     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+459     # . save registers
+460     51/push-ECX
+461     52/push-EDX
+462     53/push-EBX
+463     56/push-ESI
+464     57/push-EDI
+465     # ESI = s
+466     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
+467     # ECX = s->end - s->start
+468     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
+469     2b/subtract                     0/mod/indirect  6/rm32/ESI    .           .             .           1/r32/ECX   .               .                 # subtract *ESI from ECX
+470     # EDI = head
+471     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   0xc/disp8       .                 # copy *(EBP+12) to EDI
+472     # lenh/EDX = head->length
+473     8b/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           2/r32/EDX   .               .                 # copy *EDI to EDX
+474     # if (lenh > s->end - s->start) return false
+475     39/compare                      3/mod/direct    2/rm32/EDX    .           .             .           1/r32/ECX   .               .                 # compare EDX with ECX
+476     7f/jump-if-greater  $slice-starts-with?:false/disp8
+477     # currs/ESI = s->start
+478     8b/subtract                     0/mod/indirect  6/rm32/ESI    .           .             .           6/r32/ESI   .               .                 # copy *ESI to ESI
+479     # currh/EDI = head->data
+480     81          0/subop/add         3/mod/direct    7/rm32/EDI    .           .             .           .           .               4/imm32           # add to EDI
+481     # i/ECX = 0
+482     31/xor                          3/mod/direct    1/rm32/ECX    .           .             .           1/r32/ECX   .               .                 # clear ECX
+483     # EAX = EBX = 0
+484     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
+485     31/xor                          3/mod/direct    3/rm32/EBX    .           .             .           3/r32/EBX   .               .                 # clear EBX
+486 $slice-starts-with?:loop:
+487     # if (i >= lenh) return true
+488     39/compare                      3/mod/direct    1/rm32/ECX    .           .             .           2/r32/EDX   .               .                 # compare ECX with EDX
+489     7d/jump-if-greater-or-equal  $slice-starts-with?:true/disp8
+490     # AL = *currs
+491     8a/copy-byte                    0/mod/indirect  6/rm32/ESI    .           .             .           0/r32/AL    .               .                 # copy byte at *ESI to AL
+492     # BL = *currh
+493     8a/copy-byte                    0/mod/indirect  7/rm32/EDI    .           .             .           3/r32/BL    .               .                 # copy byte at *EDI to BL
+494     # if (*currs != *currh) return false
+495     39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           3/r32/EBX   .               .                 # compare EAX and EBX
+496     75/jump-if-not-equal  $slice-starts-with?:false/disp8
+497     # ++i
+498     41/increment-ECX
+499     # ++currs
+500     46/increment-ESI
+501     # ++currh
+502     47/increment-EDI
+503     eb/jump $slice-starts-with?:loop/disp8
+504 $slice-starts-with?:true:
+505     b8/copy-to-EAX  1/imm32
+506     eb/jump  $slice-starts-with?:end/disp8
+507 $slice-starts-with?:false:
+508     b8/copy-to-EAX  0/imm32
+509 $slice-starts-with?:end:
+510     # . restore registers
+511     5f/pop-to-EDI
+512     5e/pop-to-ESI
+513     5b/pop-to-EBX
+514     5a/pop-to-EDX
+515     59/pop-to-ECX
+516     # . epilog
+517     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+518     5d/pop-to-EBP
+519     c3/return
+520 
+521 test-slice-starts-with-single-character:
+522     # - slice-starts-with?(slice("Abc"), "A") == 1
+523     # . prolog
+524     55/push-EBP
+525     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+526     # var slice/ECX
+527     68/push  _test-slice-data-3/imm32/end
+528     68/push  _test-slice-data-0/imm32/start
+529     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+530     # EAX = slice-starts-with?(ECX, "A")
+531     # . . push args
+532     68/push  "A"/imm32
+533     51/push-ECX
+534     # . . call
+535     e8/call  slice-starts-with?/disp32
+536     # . . discard args
+537     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+538     # check-ints-equal(EAX, 1, msg)
+539     # . . push args
+540     68/push  "F - test-slice-starts-with-single-character"/imm32
+541     68/push  1/imm32
+542     50/push-EAX
+543     # . . call
+544     e8/call  check-ints-equal/disp32
+545     # . . discard args
+546     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+547     # . epilog
+548     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+549     5d/pop-to-EBP
+550     c3/return
+551 
+552 test-slice-starts-with-empty-string:
+553     # - slice-starts-with?(slice("Abc"), "") == 1
+554     # . prolog
+555     55/push-EBP
+556     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+557     # var slice/ECX
+558     68/push  _test-slice-data-3/imm32/end
+559     68/push  _test-slice-data-0/imm32/start
+560     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+561     # EAX = slice-starts-with?(ECX, "")
+562     # . . push args
+563     68/push  ""/imm32
+564     51/push-ECX
+565     # . . call
+566     e8/call  slice-starts-with?/disp32
+567     # . . discard args
+568     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+569     # check-ints-equal(EAX, 1, msg)
+570     # . . push args
+571     68/push  "F - test-slice-starts-with-empty-string"/imm32
+572     68/push  1/imm32
+573     50/push-EAX
+574     # . . call
+575     e8/call  check-ints-equal/disp32
+576     # . . discard args
+577     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+578     # . epilog
+579     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+580     5d/pop-to-EBP
+581     c3/return
+582 
+583 test-slice-starts-with-multiple-characters:
+584     # - slice-starts-with?(slice("Abc"), "Ab") == 1
+585     # . prolog
+586     55/push-EBP
+587     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+588     # var slice/ECX
+589     68/push  _test-slice-data-3/imm32/end
+590     68/push  _test-slice-data-0/imm32/start
+591     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+592     # EAX = slice-starts-with?(ECX, "Ab")
+593     # . . push args
+594     68/push  "Ab"/imm32
+595     51/push-ECX
+596     # . . call
+597     e8/call  slice-starts-with?/disp32
+598     # . . discard args
+599     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+600     # check-ints-equal(EAX, 1, msg)
+601     # . . push args
+602     68/push  "F - test-slice-starts-with-multiple-characters"/imm32
+603     68/push  1/imm32
+604     50/push-EAX
+605     # . . call
+606     e8/call  check-ints-equal/disp32
+607     # . . discard args
+608     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+609     # . epilog
+610     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+611     5d/pop-to-EBP
+612     c3/return
+613 
+614 test-slice-starts-with-entire-string:
+615     # - slice-starts-with?(slice("Abc"), "Abc") == 1
+616     # . prolog
+617     55/push-EBP
+618     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+619     # var slice/ECX
+620     68/push  _test-slice-data-3/imm32/end
+621     68/push  _test-slice-data-0/imm32/start
+622     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+623     # EAX = slice-starts-with?(ECX, "Abc")
+624     # . . push args
+625     68/push  "Abc"/imm32
+626     51/push-ECX
+627     # . . call
+628     e8/call  slice-starts-with?/disp32
+629     # . . discard args
+630     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+631     # check-ints-equal(EAX, 1, msg)
+632     # . . push args
+633     68/push  "F - test-slice-starts-with-entire-string"/imm32
+634     68/push  1/imm32
+635     50/push-EAX
+636     # . . call
+637     e8/call  check-ints-equal/disp32
+638     # . . discard args
+639     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+640     # . epilog
+641     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+642     5d/pop-to-EBP
+643     c3/return
+644 
+645 test-slice-starts-with-fails:
+646     # - slice-starts-with?(slice("Abc"), "Abd") == 1
+647     # . prolog
+648     55/push-EBP
+649     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+650     # var slice/ECX
+651     68/push  _test-slice-data-3/imm32/end
+652     68/push  _test-slice-data-0/imm32/start
+653     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+654     # EAX = slice-starts-with?(ECX, "Abd")
+655     # . . push args
+656     68/push  "Abd"/imm32
+657     51/push-ECX
+658     # . . call
+659     e8/call  slice-starts-with?/disp32
+660     # . . discard args
+661     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+662     # check-ints-equal(EAX, 0, msg)
+663     # . . push args
+664     68/push  "F - test-slice-starts-with-fails"/imm32
+665     68/push  0/imm32
+666     50/push-EAX
+667     # . . call
+668     e8/call  check-ints-equal/disp32
+669     # . . discard args
+670     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+671     # . epilog
+672     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+673     5d/pop-to-EBP
+674     c3/return
+675 
+676 test-slice-starts-with-fails-2:
+677     # - slice-starts-with?(slice("Abc"), "Ac") == 1
+678     # . prolog
+679     55/push-EBP
+680     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+681     # var slice/ECX
+682     68/push  _test-slice-data-3/imm32/end
+683     68/push  _test-slice-data-0/imm32/start
+684     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+685     # EAX = slice-starts-with?(ECX, "Ac")
+686     # . . push args
+687     68/push  "Ac"/imm32
+688     51/push-ECX
+689     # . . call
+690     e8/call  slice-starts-with?/disp32
+691     # . . discard args
+692     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+693     # check-ints-equal(EAX, 0, msg)
+694     # . . push args
+695     68/push  "F - test-slice-starts-with-fails-2"/imm32
+696     68/push  0/imm32
+697     50/push-EAX
+698     # . . call
+699     e8/call  check-ints-equal/disp32
+700     # . . discard args
+701     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+702     # . epilog
+703     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+704     5d/pop-to-EBP
+705     c3/return
+706 
+707 write-slice:  # out : (address buffered-file), s : (address slice)
+708     # . prolog
+709     55/push-EBP
+710     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+711     # . save registers
+712     50/push-EAX
+713     51/push-ECX
+714     52/push-EDX
+715     53/push-EBX
+716     56/push-ESI
+717     57/push-EDI
+718     # ESI = s
+719     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   0xc/disp8       .                 # copy *(EBP+12) to ESI
+720     # curr/ECX = s->start
+721     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           1/r32/ECX   .               .                 # copy *ESI to ECX
+722     # max/ESI = s->end
+723     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           6/r32/ESI   4/disp8         .                 # copy *(ESI+4) to ESI
+724     # EDI = out
+725     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .                         7/r32/EDI   8/disp8         .                 # copy *(EBP+8) to EDI
+726     # EDX = out->length
+727     8b/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           2/r32/EDX   0xc/disp8       .                 # copy *(EDI+12) to EDX
+728     # EBX = out->write
+729     8b/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           3/r32/EBX   4/disp8         .                 # copy *(EDI+4) to EBX
+730 $write-slice:loop:
+731     # if (curr >= max) break
+732     39/compare                      3/mod/direct    1/rm32/ECX    .           .             .           6/r32/ESI   .               .                 # compare ECX with ESI
+733     7d/jump-if-greater-or-equal  $write-slice:loop-end/disp8
+734     # if (out->write >= out->length) flush and clear out's stream
+735     39/compare                      3/mod/direct    3/rm32/EBX    .           .             .           2/r32/EDX   .               .                 # compare EBX with EDX
+736     7c/jump-if-lesser  $write-slice:to-stream/disp8
+737     # . persist out->write
+738     89/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           3/r32/EBX   4/disp8         .                 # copy EBX to *(EDI+4)
+739     # . flush(out)
+740     # . . push args
+741     57/push-EDI
+742     # . . call
+743     e8/call  flush/disp32
+744     # . . discard args
+745     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+746     # . clear-stream(stream = out+4)
+747     # . . push args
+748     8d/copy-address                 1/mod/*+disp8   7/rm32/EDI    .           .             .           0/r32/EAX   4/disp8         .                 # copy EDI+4 to EAX
+749     50/push-EAX
+750     # . . call
+751     e8/call  clear-stream/disp32
+752     # . . discard args
+753     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+754     # . out->write must now be 0; update its cache at EBX
+755     31/xor                          3/mod/direct    3/rm32/EBX    .           .             .           3/r32/EBX   .               .                 # clear EBX
+756 $write-slice:to-stream:
+757     # out->data[out->write] = *in
+758     # . AL = *in
+759     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
+760     8a/copy-byte                    0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/AL    .               .                 # copy byte at *ECX to AL
+761     # . out->data[out->write] = AL
+762     88/copy-byte                    1/mod/*+disp8   4/rm32/sib    7/base/EDI  3/index/EBX   .           0/r32/AL    0x10/disp8      .                 # copy AL to *(EDI+EBX+16)
+763     # ++out->write
+764     43/increment-EBX
+765     # ++in
+766     41/increment-ECX
+767     eb/jump  $write-slice:loop/disp8
+768 $write-slice:loop-end:
+769     # persist necessary variables from registers
+770     89/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           3/r32/EBX   4/disp8         .                 # copy EBX to *(EDI+4)
+771 $write-slice:end:
+772     # . restore registers
+773     5f/pop-to-EDI
+774     5e/pop-to-ESI
+775     5b/pop-to-EBX
+776     5a/pop-to-EDX
+777     59/pop-to-ECX
+778     58/pop-to-EAX
+779     # . epilog
+780     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+781     5d/pop-to-EBP
+782     c3/return
+783 
+784 test-write-slice:
+785     # . prolog
+786     55/push-EBP
+787     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+788     # setup
+789     # . clear-stream(_test-stream)
+790     # . . push args
+791     68/push  _test-stream/imm32
+792     # . . call
+793     e8/call  clear-stream/disp32
+794     # . . discard args
+795     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+796     # . clear-stream(_test-buffered-file+4)
+797     # . . push args
+798     b8/copy-to-EAX  _test-buffered-file/imm32
+799     05/add-to-EAX  4/imm32
+800     50/push-EAX
+801     # . . call
+802     e8/call  clear-stream/disp32
+803     # . . discard args
+804     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+805     # var slice/ECX = "Abc"
+806     68/push  _test-slice-data-3/imm32/end
+807     68/push  _test-slice-data-0/imm32/start
+808     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+809     # write-slice(_test-buffered-file, slice)
+810     # . . push args
+811     51/push-ECX
+812     68/push  _test-buffered-file/imm32
+813     # . . call
+814     e8/call  write-slice/disp32
+815     # . . discard args
+816     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+817     # flush(_test-buffered-file)
+818     # . . push args
+819     68/push  _test-buffered-file/imm32
+820     # . . call
+821     e8/call  flush/disp32
+822     # . . discard args
+823     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+824     # check-stream-equal(_test-stream, "Abc", msg)
+825     # . . push args
+826     68/push  "F - test-write-slice"/imm32
+827     68/push  "Abc"/imm32
+828     68/push  _test-stream/imm32
+829     # . . call
+830     e8/call  check-stream-equal/disp32
+831     # . . discard args
+832     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+833     # . epilog
+834     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+835     5d/pop-to-EBP
+836     c3/return
+837 
+838 # copy a slice into a new (dynamically allocated) string
+839 slice-to-string:  # ad : (address allocation-descriptor), in : (address slice) -> out/EAX : (address array)
+840     # . prolog
+841     55/push-EBP
+842     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+843     # . save registers
+844     51/push-ECX
+845     52/push-EDX
+846     53/push-EBX
+847     56/push-ESI
+848     # ESI = in
+849     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   0xc/disp8       .                 # copy *(EBP+12) to ESI
+850     # curr/EDX = in->start
+851     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           2/r32/EDX   .               .                 # copy *ESI to EDX
+852     # max/EBX = in->end
+853     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           3/r32/EBX   4/disp8         .                 # copy *(ESI+4) to EBX
+854     # size/ECX = max - curr + 4  # total size of output string (including the initial length)
+855     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           3/r32/EBX   .               .                 # copy EBX to ECX
+856     29/subtract                     3/mod/direct    1/rm32/ECX    .           .             .           2/r32/EDX   .               .                 # subtract EDX from ECX
+857     81          0/subop/add         3/mod/direct    1/rm32/ECX    .           .             .           .           .               4/imm32           # add to ECX
+858     # out/EAX = allocate(ad, size)
+859     # . . push args
+860     51/push-ECX
+861     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+862     # . . call
+863     e8/call  allocate/disp32
+864     # . . discard args
+865     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+866     # if (EAX == 0) abort
+867     3d/compare-EAX-and  0/imm32
+868     74/jump-if-equal  $slice-to-string:abort/disp8
+869     # *out = size-4
+870     89/copy                         0/mod/indirect  0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # copy ECX to *EAX
+871     81          5/subop/subtract    0/mod/indirect  0/rm32/EAX    .           .             .           .           .               4/imm32           # subtract 4 from *EAX
+872     # save out
+873     50/push-EAX
+874     # EAX = _append-4(EAX+4, EAX+size, curr, max)  # clobbering ECX
+875     # . . push args
+876     53/push-EBX
+877     52/push-EDX
+878     # . . push EAX+size (clobbering ECX)
+879     01/add                          3/mod/direct    1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # add EAX to ECX
+880     51/push-ECX
+881     # . . push EAX+4 (clobbering EAX)
+882     81          0/subop/add         3/mod/direct    0/rm32/EAX    .           .             .           .           .               4/imm32           # add to EAX
+883     50/push-EAX
+884     # . . call
+885     e8/call  _append-4/disp32
+886     # . . discard args
+887     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0x10/imm32        # add to ESP
+888     # restore out (assumes _append-4 can't error)
+889     58/pop-to-EAX
+890 $slice-to-string:end:
+891     # . restore registers
+892     5e/pop-to-ESI
+893     5b/pop-to-EBX
+894     5a/pop-to-EDX
+895     59/pop-to-ECX
+896     # . epilog
+897     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+898     5d/pop-to-EBP
+899     c3/return
+900 
+901 $slice-to-string:abort:
+902     # . _write(2/stderr, error)
+903     # . . push args
+904     68/push  "slice-to-string: out of space"/imm32
+905     68/push  2/imm32/stderr
+906     # . . call
+907     e8/call  _write/disp32
+908     # . . discard args
+909     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+910     # . syscall(exit, 1)
+911     bb/copy-to-EBX  1/imm32
+912     b8/copy-to-EAX  1/imm32/exit
+913     cd/syscall  0x80/imm8
+914     # never gets here
+915 
+916 test-slice-to-string:
+917     # . prolog
+918     55/push-EBP
+919     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+920     # var slice/ECX = "Abc"
+921     68/push  _test-slice-data-3/imm32/end
+922     68/push  _test-slice-data-0/imm32/start
+923     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+924     # EAX = slice-to-string(Heap, slice)
+925     # . . push args
+926     51/push-ECX
+927     68/push  Heap/imm32
+928     # . . call
+929     e8/call  slice-to-string/disp32
+930     # . . discard args
+931     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+932 +-- 26 lines: #?     # dump word-slice -----------------------------------------------------------------------------------------------------------------------
+958     # EAX = string-equal?(EAX, "Abc")
+959     # . . push args
+960     68/push  "Abc"/imm32
+961     50/push-EAX
+962     # . . call
+963     e8/call  string-equal?/disp32
+964     # . . discard args
+965     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+966     # check-ints-equal(EAX, 1, msg)
+967     # . . push args
+968     68/push  "F - test-slice-to-string"/imm32
+969     68/push  1/imm32/true
+970     50/push-EAX
+971     # . . call
+972     e8/call  check-ints-equal/disp32
+973     # . . discard args
+974     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+975     # . epilog
+976     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+977     5d/pop-to-EBP
+978     c3/return
+979 
+980 == data
+981 
+982 _test-slice-data-0:
+983     41/A
+984 _test-slice-data-1:
+985     62/b
+986 _test-slice-data-2:
+987     63/c
+988 _test-slice-data-3:
+989     64/d
+990 _test-slice-data-4:
+991 
+992 # . _. vim:nowrap:textwidth=0
 
diff --git a/html/subx/073next-token.subx.html b/html/subx/073next-token.subx.html index 3febade6..3e6052b8 100644 --- a/html/subx/073next-token.subx.html +++ b/html/subx/073next-token.subx.html @@ -432,7 +432,7 @@ if ('onhashchange' in window) { 372 39/compare 3/mod/direct 0/rm32/EAX . . . 2/r32/EDX . . # compare EAX and EDX 373 75/jump-if-not-equal $skip-chars-matching:end/disp8 374 # ++in->read -375 41/inc-ECX +375 41/increment-ECX 376 eb/jump $skip-chars-matching:loop/disp8 377 $skip-chars-matching:end: 378 # persist in->read @@ -556,7 +556,7 @@ if ('onhashchange' in window) { 496 39/compare 3/mod/direct 0/rm32/EAX . . . 2/r32/EDX . . # compare EAX and EDX 497 74/jump-if-equal $skip-chars-not-matching:end/disp8 498 # ++in->read -499 41/inc-ECX +499 41/increment-ECX 500 eb/jump $skip-chars-not-matching:loop/disp8 501 $skip-chars-not-matching:end: 502 # persist in->read @@ -724,7 +724,7 @@ if ('onhashchange' in window) { 664 3d/compare-EAX-and 0x0d/imm32/cr 665 74/jump-if-equal $skip-chars-not-matching-whitespace:end/disp8 666 # ++in->read -667 41/inc-ECX +667 41/increment-ECX 668 eb/jump $skip-chars-not-matching-whitespace:loop/disp8 669 $skip-chars-not-matching-whitespace:end: 670 # persist in->read @@ -764,7 +764,7 @@ if ('onhashchange' in window) { 704 39/compare 3/mod/direct 3/rm32/EBX . . . 2/r32/EDX . . # compare EBX and EDX 705 75/jump-if-not-equal $skip-chars-matching-in-slice:end/disp8 706 # ++curr -707 40/inc-EAX +707 40/increment-EAX 708 eb/jump $skip-chars-matching-in-slice:loop/disp8 709 $skip-chars-matching-in-slice:end: 710 # . restore registers @@ -860,7 +860,7 @@ if ('onhashchange' in window) { 800 39/compare 3/mod/direct 3/rm32/EBX . . . 2/r32/EDX . . # compare EBX and EDX 801 74/jump-if-equal $skip-chars-not-matching-in-slice:end/disp8 802 # ++curr -803 40/inc-EAX +803 40/increment-EAX 804 eb/jump $skip-chars-not-matching-in-slice:loop/disp8 805 $skip-chars-not-matching-in-slice:end: 806 # . restore registers diff --git a/html/subx/074print-int-decimal.subx.html b/html/subx/074print-int-decimal.subx.html new file mode 100644 index 00000000..21c14918 --- /dev/null +++ b/html/subx/074print-int-decimal.subx.html @@ -0,0 +1,325 @@ + + + + +Mu - subx/074print-int-decimal.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/074print-int-decimal.subx +
+  1 # Helper to print an int32 in decimal.
+  2 
+  3 == code
+  4 #   instruction                     effective address                                                   register    displacement    immediate
+  5 # . op          subop               mod             rm32          base        index         scale       r32
+  6 # . 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
+  7 
+  8 #? Entry:  # run a single test, while debugging
+  9 #?     e8/call test-print-int32-decimal/disp32
+ 10 #?     # syscall(exit, Num-test-failures)
+ 11 #?     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
+ 12 #?     b8/copy-to-EAX  1/imm32/exit
+ 13 #?     cd/syscall  0x80/imm8
+ 14 
+ 15 print-int32-decimal:  # out : (address stream), n : int32
+ 16     # works by generating characters from lowest to highest and pushing them
+ 17     # to the stack, before popping them one by one into the stream
+ 18     #
+ 19     # pseudocode:
+ 20     #   copy ESP to EBX
+ 21     #   EAX = n
+ 22     #   while true
+ 23     #     if (EAX == 0) break
+ 24     #     sign-extend EAX into EDX
+ 25     #     EAX, EDX = EAX/10, EAX%10
+ 26     #     push EDX
+ 27     #   if n < 0
+ 28     #     push '-' - 0x30 = -3
+ 29     #   w/EAX = out->write
+ 30     #   max/ECX = out->length
+ 31     #   curr/EDI = out->data[out->write]
+ 32     #   while true
+ 33     #     if (ESP == EBX) break
+ 34     #     if (curr >= max) abort
+ 35     #     pop into EDX
+ 36     #     EDX += '0'  # convert decimal digit to ascii
+ 37     #     *curr = DL
+ 38     #     ++curr
+ 39     #     ++w
+ 40     #   out->write = w
+ 41     #
+ 42     # . prolog
+ 43     55/push-EBP
+ 44     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 45     # . save registers
+ 46     50/push-EAX
+ 47     51/push-ECX
+ 48     52/push-EDX
+ 49     53/push-EBX
+ 50     57/push-EDI
+ 51     # copy ESP to EBX
+ 52     89/copy                         3/mod/direct    3/rm32/EBX    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBX
+ 53     # ten/ECX = 10
+ 54     b9/copy-to-ECX  0xa/imm32
+ 55     # EAX = |n|
+ 56     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           0/r32/EAX   0xc/disp8       .                 # copy *(EBP+12) to EAX
+ 57     3d/compare-EAX-with  0/imm32
+ 58     7d/jump-if-greater-or-equal $print-int32-decimal:read-loop/disp8
+ 59 $print-int32-decimal:negative:
+ 60     f7          3/subop/negate      3/mod/direct    0/rm32/EAX    .           .             .           .           .               .                 # negate EAX
+ 61 $print-int32-decimal:read-loop:
+ 62     # if (EAX == 0) break
+ 63     3d/compare-EAX-and  0/imm32
+ 64     74/jump-if-equal $print-int32-decimal:read-break/disp8
+ 65     # sign-extend
+ 66     99/sign-extend-EAX-into-EDX
+ 67     # EAX, EDX = divide-with-remainder EAX/ten, EAX%ten
+ 68     f7          7/subop/divide-by   3/mod/direct    1/rm32/ECX    .           .             .           .           .               .                 # divide EDX:EAX by ECX, storing quotient in EAX and remainder in EDX
+ 69     # push EDX
+ 70     52/push-EDX
+ 71     eb/jump  $print-int32-decimal:read-loop/disp8
+ 72 $print-int32-decimal:read-break:
+ 73     # if (n < 0) push('-')
+ 74     81          7/subop/compare     1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       0/imm32           # compare *(EBP+12)
+ 75     7d/jump-if-greater-or-equal $print-int32-decimal:write/disp8
+ 76 $print-int32-decimal:push-negative:
+ 77     68/push  -3/imm32/dash-minus-zero
+ 78     # fall through
+ 79 $print-int32-decimal:write:
+ 80     # EDI = out
+ 81     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   8/disp8         .                 # copy *(EBP+8) to EDI
+ 82     # max/ECX = &out->data[out->length]
+ 83     8b/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           1/r32/ECX   8/disp8         .                 # copy *(EDI+8) to ECX
+ 84     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    7/base/EDI  1/index/ECX   .           1/r32/ECX   0xc/disp8       .                 # copy EDI+ECX+12 to ECX
+ 85     # w/EAX = out->write
+ 86     8b/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           0/r32/EAX   .               .                 # copy *EDI to EAX
+ 87     # curr/EDI = &out->data[out->write]
+ 88     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    7/base/EDI  0/index/EAX   .           7/r32/EDI   0xc/disp8       .                 # copy EDI+EAX+12 to EDI
+ 89 $print-int32-decimal:write-loop:
+ 90     # if (ESP == EBX) break
+ 91     39/compare                      3/mod/direct    4/rm32/ESP    .           .             .           3/r32/EBX   .               .                 # compare ESP and EBX
+ 92     74/jump-if-equal  $print-int32-decimal:write-break/disp8
+ 93     # if (curr >= max) abort
+ 94     39/compare                      3/mod/direct    7/rm32/EDI    .           .             .           1/r32/ECX   .               .                 # compare EDI and ECX
+ 95     7d/jump-if-greater-or-equal  $print-int32-decimal:abort/disp8
+ 96     # pop into EDX
+ 97     5a/pop-into-EDX
+ 98     # EDX += '0'
+ 99     81          0/subop/add         3/mod/direct    2/rm32/EDX    .           .             .           .           .               0x30/imm32/zero   # add to EDX
+100 $print-int32-decimal:write-char:
+101     # *curr = DL
+102     88/copy-byte                    0/mod/indirect  7/rm32/EDI    .           .             .           2/r32/DL    .               .                 # copy DL to byte at *ECX
+103     # ++curr
+104     47/increment-EDI
+105     # ++w
+106     40/increment-EAX
+107     eb/jump  $print-int32-decimal:write-loop/disp8
+108 $print-int32-decimal:write-break:
+109     # out->write = w
+110     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   8/disp8         .                 # copy *(EBP+8) to EDI
+111     89/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           0/r32/EAX   .               .                 # copy EAX to *EDI
+112 $print-int32-decimal:end:
+113     # . restore registers
+114     5f/pop-to-EDI
+115     5b/pop-to-EBX
+116     5a/pop-to-EDX
+117     59/pop-to-ECX
+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 $print-int32-decimal:abort:
+125     # . _write(2/stderr, error)
+126     # . . push args
+127     68/push  "print-int32-decimal: out of space"/imm32
+128     68/push  2/imm32/stderr
+129     # . . call
+130     e8/call  _write/disp32
+131     # . . discard args
+132     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+133     # . syscall(exit, 1)
+134     bb/copy-to-EBX  1/imm32
+135     b8/copy-to-EAX  1/imm32/exit
+136     cd/syscall  0x80/imm8
+137     # never gets here
+138 
+139 test-print-int32-decimal:
+140     # check that a single-digit number converts correctly
+141     # setup
+142     # . clear-stream(_test-stream)
+143     # . . push args
+144     68/push  _test-stream/imm32
+145     # . . call
+146     e8/call  clear-stream/disp32
+147     # . . discard args
+148     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+149     # print-int32-decimal(_test-stream, 9)
+150     # . . push args
+151     68/push  9/imm32
+152     68/push  _test-stream/imm32
+153     # . . call
+154     e8/call  print-int32-decimal/disp32
+155     # . . discard args
+156     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+157     # check-stream-equal(_test-stream, "9", msg)
+158     # . . push args
+159     68/push  "F - test-print-int32-decimal"/imm32
+160     68/push  "9"/imm32
+161     68/push  _test-stream/imm32
+162     # . . call
+163     e8/call  check-stream-equal/disp32
+164     # . . discard args
+165     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+166     # . end
+167     c3/return
+168 
+169 test-print-int32-decimal-multiple-digits:
+170     # check that a multi-digit number converts correctly
+171     # setup
+172     # . clear-stream(_test-stream)
+173     # . . push args
+174     68/push  _test-stream/imm32
+175     # . . call
+176     e8/call  clear-stream/disp32
+177     # . . discard args
+178     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+179     # print-int32-decimal(_test-stream, 10)
+180     # . . push args
+181     68/push  0xa/imm32
+182     68/push  _test-stream/imm32
+183     # . . call
+184     e8/call  print-int32-decimal/disp32
+185     # . . discard args
+186     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+187     # check-stream-equal(_test-stream, "10", msg)
+188     # . . push args
+189     68/push  "F - test-print-int32-decimal-multiple-digits"/imm32
+190     68/push  "10"/imm32
+191     68/push  _test-stream/imm32
+192     # . . call
+193     e8/call  check-stream-equal/disp32
+194     # . . discard args
+195     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+196     # . end
+197     c3/return
+198 
+199 test-print-int32-decimal-negative:
+200     # check that a negative single-digit number converts correctly
+201     # setup
+202     # . clear-stream(_test-stream)
+203     # . . push args
+204     68/push  _test-stream/imm32
+205     # . . call
+206     e8/call  clear-stream/disp32
+207     # . . discard args
+208     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+209     # print-int32-decimal(_test-stream, -9)
+210     # . . push args
+211     68/push  -9/imm32
+212     68/push  _test-stream/imm32
+213     # . . call
+214     e8/call  print-int32-decimal/disp32
+215     # . . discard args
+216     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+217 +-- 26 lines: #?     # dump _test-stream ---------------------------------------------------------------------------------------------------------------------
+243     # check-stream-equal(_test-stream, "-9", msg)
+244     # . . push args
+245     68/push  "F - test-print-int32-decimal-negative"/imm32
+246     68/push  "-9"/imm32
+247     68/push  _test-stream/imm32
+248     # . . call
+249     e8/call  check-stream-equal/disp32
+250     # . . discard args
+251     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+252     # . end
+253     c3/return
+254 
+255 test-print-int32-decimal-negative-multiple-digits:
+256     # check that a multi-digit number converts correctly
+257     # setup
+258     # . clear-stream(_test-stream)
+259     # . . push args
+260     68/push  _test-stream/imm32
+261     # . . call
+262     e8/call  clear-stream/disp32
+263     # . . discard args
+264     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+265     # print-int32-decimal(_test-stream, -10)
+266     # . . push args
+267     68/push  -0xa/imm32
+268     68/push  _test-stream/imm32
+269     # . . call
+270     e8/call  print-int32-decimal/disp32
+271     # . . discard args
+272     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+273     # check-stream-equal(_test-stream, "-10", msg)
+274     # . . push args
+275     68/push  "F - test-print-int32-decimal-negative-multiple-digits"/imm32
+276     68/push  "-10"/imm32
+277     68/push  _test-stream/imm32
+278     # . . call
+279     e8/call  check-stream-equal/disp32
+280     # . . discard args
+281     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+282     # . end
+283     c3/return
+284 
+285 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/subx/apps/assort.subx.html b/html/subx/apps/assort.subx.html index 676b2d71..947f9474 100644 --- a/html/subx/apps/assort.subx.html +++ b/html/subx/apps/assort.subx.html @@ -173,7 +173,7 @@ if ('onhashchange' in window) { 109 51/push-ECX 110 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) 111 # . . call - 112 e8/call read-segments/disp32 + 112 e8/call read-segments/disp32 113 # . . discard args 114 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 115 $convert:write: @@ -182,7 +182,7 @@ if ('onhashchange' in window) { 118 51/push-ECX 119 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) 120 # . . call - 121 e8/call write-segments/disp32 + 121 e8/call write-segments/disp32 122 # . . discard args 123 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP 124 $convert:end: @@ -195,1022 +195,1060 @@ if ('onhashchange' in window) { 131 5d/pop-to-EBP 132 c3/return 133 - 134 #? test-convert: - 135 #? # . prolog - 136 #? 55/push-EBP - 137 #? 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 138 #? # setup - 139 #? # . clear-stream(_test-input-stream) - 140 #? # . . push args - 141 #? 68/push _test-input-stream/imm32 - 142 #? # . . call - 143 #? e8/call clear-stream/disp32 - 144 #? # . . discard args - 145 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 146 #? # . clear-stream(_test-input-buffered-file+4) - 147 #? # . . push args - 148 #? b8/copy-to-EAX _test-input-buffered-file/imm32 - 149 #? 05/add-to-EAX 4/imm32 - 150 #? 50/push-EAX - 151 #? # . . call - 152 #? e8/call clear-stream/disp32 - 153 #? # . . discard args - 154 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 155 #? # . clear-stream(_test-output-stream) - 156 #? # . . push args - 157 #? 68/push _test-output-stream/imm32 - 158 #? # . . call - 159 #? e8/call clear-stream/disp32 - 160 #? # . . discard args - 161 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 162 #? # . clear-stream(_test-output-buffered-file+4) - 163 #? # . . push args - 164 #? b8/copy-to-EAX _test-output-buffered-file/imm32 - 165 #? 05/add-to-EAX 4/imm32 - 166 #? 50/push-EAX - 167 #? # . . call - 168 #? e8/call clear-stream/disp32 - 169 #? # . . discard args - 170 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 171 #? # initialize input (meta comments in parens) - 172 #? # # comment 1 - 173 #? # # comment 2 indented - 174 #? # == code (new segment) - 175 #? # # comment 3 inside a segment - 176 #? # 1 - 177 #? # (empty line) - 178 #? # 2 3 # comment 4 inline with other contents - 179 #? # == data (new segment) - 180 #? # 4 5/imm32 - 181 #? # == code (existing segment but non-contiguous with previous iteration) - 182 #? # 6 7 - 183 #? # 8 9 (multiple lines) - 184 #? # == code (existing segment contiguous with previous iteration) - 185 #? # 10 11 - 186 #? # . write(_test-input-stream, "# comment 1") - 187 #? # . . push args - 188 #? 68/push "# comment 1"/imm32 - 189 #? 68/push _test-input-stream/imm32 - 190 #? # . . call - 191 #? e8/call write/disp32 - 192 #? # . . discard args - 193 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 194 #? # . write(_test-input-stream, "\n") - 195 #? # . . push args - 196 #? 68/push Newline/imm32 - 197 #? 68/push _test-input-stream/imm32 - 198 #? # . . call - 199 #? e8/call write/disp32 - 200 #? # . . discard args - 201 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 202 #? # . write(_test-input-stream, " # comment 2 indented") - 203 #? # . . push args - 204 #? 68/push " # comment 2 indented"/imm32 - 205 #? 68/push _test-input-stream/imm32 - 206 #? # . . call - 207 #? e8/call write/disp32 - 208 #? # . . discard args - 209 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 210 #? # . write(_test-input-stream, "\n") - 211 #? # . . push args - 212 #? 68/push Newline/imm32 - 213 #? 68/push _test-input-stream/imm32 - 214 #? # . . call - 215 #? e8/call write/disp32 - 216 #? # . . discard args - 217 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 218 #? # . write(_test-input-stream, "== code") - 219 #? # . . push args - 220 #? 68/push "== code"/imm32 - 221 #? 68/push _test-input-stream/imm32 - 222 #? # . . call - 223 #? e8/call write/disp32 - 224 #? # . . discard args - 225 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 226 #? # . write(_test-input-stream, "\n") - 227 #? # . . push args - 228 #? 68/push Newline/imm32 - 229 #? 68/push _test-input-stream/imm32 - 230 #? # . . call - 231 #? e8/call write/disp32 - 232 #? # . . discard args - 233 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 234 #? # . write(_test-input-stream, "# comment 3 inside a segment") - 235 #? # . . push args - 236 #? 68/push "# comment 3 inside a segment"/imm32 - 237 #? 68/push _test-input-stream/imm32 - 238 #? # . . call - 239 #? e8/call write/disp32 - 240 #? # . . discard args - 241 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 242 #? # . write(_test-input-stream, "\n") - 243 #? # . . push args - 244 #? 68/push Newline/imm32 - 245 #? 68/push _test-input-stream/imm32 - 246 #? # . . call - 247 #? e8/call write/disp32 - 248 #? # . . discard args - 249 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 250 #? # . write(_test-input-stream, "1") - 251 #? # . . push args - 252 #? 68/push "1"/imm32 - 253 #? 68/push _test-input-stream/imm32 - 254 #? # . . call - 255 #? e8/call write/disp32 - 256 #? # . . discard args - 257 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 258 #? # . write(_test-input-stream, "\n") - 259 #? # . . push args - 260 #? 68/push Newline/imm32 - 261 #? 68/push _test-input-stream/imm32 - 262 #? # . . call - 263 #? e8/call write/disp32 - 264 #? # . . discard args - 265 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 266 #? # . write(_test-input-stream, "\n") # empty line - 267 #? # . . push args - 268 #? 68/push Newline/imm32 - 269 #? 68/push _test-input-stream/imm32 - 270 #? # . . call - 271 #? e8/call write/disp32 - 272 #? # . . discard args - 273 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 274 #? # . write(_test-input-stream, "2 3 # comment 4 inline with other comments") - 275 #? # . . push args - 276 #? 68/push "2 3 # comment 4 inline with other comments"/imm32 - 277 #? 68/push _test-input-stream/imm32 - 278 #? # . . call - 279 #? e8/call write/disp32 - 280 #? # . . discard args - 281 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 282 #? # . write(_test-input-stream, "\n") - 283 #? # . . push args - 284 #? 68/push Newline/imm32 - 285 #? 68/push _test-input-stream/imm32 - 286 #? # . . call - 287 #? e8/call write/disp32 - 288 #? # . . discard args - 289 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 290 #? # . write(_test-input-stream, "== data") - 291 #? # . . push args - 292 #? 68/push "== data"/imm32 - 293 #? 68/push _test-input-stream/imm32 - 294 #? # . . call - 295 #? e8/call write/disp32 - 296 #? # . . discard args - 297 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 298 #? # . write(_test-input-stream, "\n") - 299 #? # . . push args - 300 #? 68/push Newline/imm32 - 301 #? 68/push _test-input-stream/imm32 - 302 #? # . . call - 303 #? e8/call write/disp32 - 304 #? # . . discard args - 305 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 306 #? # . write(_test-input-stream, "4 5/imm32") - 307 #? # . . push args - 308 #? 68/push "4 5/imm32"/imm32 - 309 #? 68/push _test-input-stream/imm32 - 310 #? # . . call - 311 #? e8/call write/disp32 - 312 #? # . . discard args - 313 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 314 #? # . write(_test-input-stream, "\n") - 315 #? # . . push args - 316 #? 68/push Newline/imm32 - 317 #? 68/push _test-input-stream/imm32 - 318 #? # . . call - 319 #? e8/call write/disp32 - 320 #? # . . discard args - 321 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 322 #? # . write(_test-input-stream, "== code") - 323 #? # . . push args - 324 #? 68/push "== code"/imm32 - 325 #? 68/push _test-input-stream/imm32 - 326 #? # . . call - 327 #? e8/call write/disp32 - 328 #? # . . discard args - 329 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 330 #? # . write(_test-input-stream, "\n") - 331 #? # . . push args - 332 #? 68/push Newline/imm32 - 333 #? 68/push _test-input-stream/imm32 - 334 #? # . . call - 335 #? e8/call write/disp32 - 336 #? # . . discard args - 337 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 338 #? # . write(_test-input-stream, "6 7") - 339 #? # . . push args - 340 #? 68/push "6 7"/imm32 - 341 #? 68/push _test-input-stream/imm32 - 342 #? # . . call - 343 #? e8/call write/disp32 - 344 #? # . . discard args - 345 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 346 #? # . write(_test-input-stream, "\n") - 347 #? # . . push args - 348 #? 68/push Newline/imm32 - 349 #? 68/push _test-input-stream/imm32 - 350 #? # . . call - 351 #? e8/call write/disp32 - 352 #? # . . discard args - 353 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 354 #? # . write(_test-input-stream, "8 9") - 355 #? # . . push args - 356 #? 68/push "6 7"/imm32 - 357 #? 68/push _test-input-stream/imm32 - 358 #? # . . call - 359 #? e8/call write/disp32 - 360 #? # . . discard args - 361 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 362 #? # . write(_test-input-stream, "\n") - 363 #? # . . push args - 364 #? 68/push Newline/imm32 - 365 #? 68/push _test-input-stream/imm32 - 366 #? # . . call - 367 #? e8/call write/disp32 - 368 #? # . . discard args - 369 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 370 #? # . write(_test-input-stream, "== code") - 371 #? # . . push args - 372 #? 68/push "== code"/imm32 - 373 #? 68/push _test-input-stream/imm32 - 374 #? # . . call - 375 #? e8/call write/disp32 - 376 #? # . . discard args - 377 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 378 #? # . write(_test-input-stream, "\n") - 379 #? # . . push args - 380 #? 68/push Newline/imm32 - 381 #? 68/push _test-input-stream/imm32 - 382 #? # . . call - 383 #? e8/call write/disp32 - 384 #? # . . discard args - 385 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 386 #? # . write(_test-input-stream, "10 11") - 387 #? # . . push args - 388 #? 68/push "10 11"/imm32 - 389 #? 68/push _test-input-stream/imm32 - 390 #? # . . call - 391 #? e8/call write/disp32 - 392 #? # . . discard args - 393 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 394 #? # . write(_test-input-stream, "\n") - 395 #? # . . push args - 396 #? 68/push Newline/imm32 - 397 #? 68/push _test-input-stream/imm32 - 398 #? # . . call - 399 #? e8/call write/disp32 - 400 #? # . . discard args - 401 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 402 #? # convert(_test-input-buffered-file, _test-output-buffered-file) - 403 #? # . . push args - 404 #? 68/push _test-output-buffered-file/imm32 - 405 #? 68/push _test-input-buffered-file/imm32 - 406 #? # . . call - 407 #? e8/call convert/disp32 - 408 #? # . . discard args - 409 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 410 #? # check output - 411 #? # == code - 412 #? # 1 - 413 #? # 2 3 # comment 4 inline with other contents - 414 #? # 6 7 - 415 #? # 8 9 - 416 #? # 10 11 - 417 #? # == data - 418 #? # 4 5/imm32 - 419 +-- 34 lines: #? #? # debug print ------------------------------------------------------------------------------------------------------------------------ - 453 #? # . flush(_test-output-buffered-file) - 454 #? # . . push args - 455 #? 68/push _test-output-buffered-file/imm32 - 456 #? # . . call - 457 #? e8/call flush/disp32 - 458 #? # . . discard args - 459 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 460 #? # . check-next-stream-line-equal(_test-output-stream, "== code", msg) - 461 #? # . . push args - 462 #? 68/push "F - test-convert-code-and-data-segments/0"/imm32 - 463 #? 68/push "== code"/imm32 - 464 #? 68/push _test-output-stream/imm32 - 465 #? # . . call - 466 #? e8/call check-next-stream-line-equal/disp32 - 467 #? # . . discard args - 468 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 469 #? # . check-next-stream-line-equal(_test-output-stream, "1", msg) - 470 #? # . . push args - 471 #? 68/push "F - test-convert-code-and-data-segments/1"/imm32 - 472 #? 68/push "e8 20 00 00 00 # e8/call 20/disp32"/imm32 - 473 #? 68/push _test-output-stream/imm32 - 474 #? # . . call - 475 #? e8/call check-next-stream-line-equal/disp32 - 476 #? # . . discard args - 477 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 478 #? # . check-next-stream-line-equal(_test-output-stream, "2 3 # comment 4 inline with other contents", msg) - 479 #? # . . push args - 480 #? 68/push "F - test-convert-code-and-data-segments/2"/imm32 - 481 #? 68/push "2 3 # comment 4 inline with other contents"/imm32 - 482 #? 68/push _test-output-stream/imm32 - 483 #? # . . call - 484 #? e8/call check-next-stream-line-equal/disp32 - 485 #? # . . discard args - 486 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 487 #? # . check-next-stream-line-equal(_test-output-stream, "6 7", msg) - 488 #? # . . push args - 489 #? 68/push "F - test-convert-code-and-data-segments/3"/imm32 - 490 #? 68/push "6 7"/imm32 - 491 #? 68/push _test-output-stream/imm32 - 492 #? # . . call - 493 #? e8/call check-next-stream-line-equal/disp32 - 494 #? # . . discard args - 495 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 496 #? # . check-next-stream-line-equal(_test-output-stream, "8 9", msg) - 497 #? # . . push args - 498 #? 68/push "F - test-convert-code-and-data-segments/4"/imm32 - 499 #? 68/push "8 9"/imm32 - 500 #? 68/push _test-output-stream/imm32 - 501 #? # . . call - 502 #? e8/call check-next-stream-line-equal/disp32 - 503 #? # . . discard args - 504 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 505 #? # . check-next-stream-line-equal(_test-output-stream, "10 11", msg) - 506 #? # . . push args - 507 #? 68/push "F - test-convert-code-and-data-segments/5"/imm32 - 508 #? 68/push "10 11"/imm32 - 509 #? 68/push _test-output-stream/imm32 - 510 #? # . . call - 511 #? e8/call check-next-stream-line-equal/disp32 - 512 #? # . . discard args - 513 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 514 #? # . check-next-stream-line-equal(_test-output-stream, "== data", msg) - 515 #? # . . push args - 516 #? 68/push "F - test-convert-code-and-data-segments/6"/imm32 - 517 #? 68/push "== data"/imm32 - 518 #? 68/push _test-output-stream/imm32 - 519 #? # . . call - 520 #? e8/call check-next-stream-line-equal/disp32 - 521 #? # . . discard args - 522 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 523 #? # . check-next-stream-line-equal(_test-output-stream, "4 5/imm32", msg) - 524 #? # . . push args - 525 #? 68/push "F - test-convert-code-and-data-segments/4"/imm32 - 526 #? 68/push "4 5/imm32"/imm32 - 527 #? 68/push _test-output-stream/imm32 - 528 #? # . . call - 529 #? e8/call check-next-stream-line-equal/disp32 - 530 #? # . . discard args - 531 #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 532 #? # . epilog - 533 #? 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 534 #? 5d/pop-to-EBP - 535 #? c3/return - 536 - 537 read-segments: # in : (address buffered-file), table : (address stream row) - 538 # pseudocode: - 539 # var curr-segment = null - 540 # var line = new-stream(512, 1) - 541 # while true - 542 # clear-stream(line) - 543 # read-line(in, line) - 544 # if (line->write == 0) break # end of file - 545 # var word-slice = next-word(line) - 546 # if slice-empty?(word-slice) # whitespace - 547 # continue - 548 # if slice-starts-with?(word-slice, "#") # comment - 549 # continue - 550 # if (slice-equal?(word-slice, "==")) - 551 # var segment-name = next-word(line) - 552 # curr-segment = get-or-insert-segment(table, segment-name, N) - 553 # else - 554 # write-stream-data(curr-segment, line) - 555 # - 556 # . prolog - 557 55/push-EBP - 558 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 559 # . save registers - 560 51/push-ECX - 561 # var line/ECX : (address stream byte) = stream(512) - 562 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0x200/imm32 # subtract from ESP - 563 68/push 0x200/imm32/length - 564 68/push 0/imm32/read - 565 68/push 0/imm32/write - 566 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 567 # var word-slice/EDX = {0, 0} - 568 68/push 0/imm32/end - 569 68/push 0/imm32/curr - 570 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX - 571 # var curr-segment/EBX = null - 572 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX - 573 $read-segments:loop: - 574 # clear-stream(line) - 575 # . . push args - 576 51/push-ECX - 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 # read-line(in, line) - 582 # . . push args - 583 51/push-ECX - 584 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) - 585 # . . call - 586 e8/call read-line/disp32 - 587 # . . discard args - 588 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 589 $read-segments:check0: - 590 # if (line->write == 0) break - 591 81 7/subop/compare 0/mod/indirect 1/rm32/ECX . . . . . 0/imm32 # compare *ECX - 592 0f 84/jump-if-equal $read-segments:break/disp32 - 593 +-- 34 lines: #? # dump line ----------------------------------------------------------------------------------------------------------------------------- - 627 # next-word(line, word-slice) - 628 # . . push args - 629 52/push-EDX - 630 51/push-ECX - 631 # . . call - 632 e8/call next-word/disp32 - 633 # . . discard args - 634 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 635 $read-segments:check1: - 636 # if (slice-empty?(word-slice)) continue - 637 # . EAX = slice-empty?(word-slice) - 638 # . . push args - 639 52/push-EDX - 640 # . . call - 641 e8/call slice-empty?/disp32 - 642 # . . discard args - 643 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 644 # . if (EAX != 0) continue - 645 3d/compare-EAX-and 0/imm32 - 646 0f 85/jump-if-not-equal $read-segments:loop/disp32 - 647 $read-segments:check-for-comment: - 648 # if (slice-starts-with?(word-slice, "#")) - 649 # . start/EDX = word-slice->start - 650 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX - 651 # . c/EAX = *start - 652 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX - 653 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 0/r32/AL . . # copy byte at *EDX to AL - 654 # . if (EAX == '#') continue - 655 3d/compare-EAX-and 0x23/imm32/hash - 656 74/jump-if-equal $read-segments:loop/disp8 - 657 $read-segments:check-for-segment-header: - 658 +-- 50 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- - 708 # if (slice-equal?(word-slice, "==")) - 709 # segment-name = next-word(line) - 710 # curr-segment = get-or-insert(table, segment-name) - 711 # . EAX = slice-equal?(word-slice, "==") - 712 # . . push args - 713 68/push "=="/imm32 - 714 52/push-EDX - 715 # . . call - 716 e8/call slice-equal?/disp32 - 717 # . . discard args - 718 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 719 # . if (EAX == 0) goto check3 - 720 81 7/subop/compare 3/mod/direct 0/rm32/EAX . . . . . 0/imm32 # compare EAX - 721 0f 84/jump-if-equal $read-segments:regular-line/disp32 - 722 # . next-word(line, segment-name) - 723 # . . push args - 724 52/push-EDX - 725 51/push-ECX - 726 # . . call - 727 e8/call next-word/disp32 - 728 # . . discard args - 729 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 730 +-- 50 lines: #? # dump segment name --------------------------------------------------------------------------------------------------------------------- - 780 # . EAX = get-or-insert-segment(table, segment-name, N) - 781 # . . push args - 782 68/push 0x1000/imm32/segment-size/4KB - 783 52/push-EDX - 784 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 785 # . . call - 786 e8/call get-or-insert-segment/disp32 - 787 # . . discard args - 788 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 789 # . curr-segment = EAX - 790 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX - 791 # . continue - 792 e9/jump $read-segments:loop/disp32 - 793 $read-segments:regular-line: - 794 # write-stream-data(curr-segment, line) - 795 # . . push args - 796 51/push-ECX - 797 53/push-EBX - 798 # . . call - 799 e8/call write-stream-data/disp32 - 800 # . . discard args - 801 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 802 # loop - 803 e9/jump $read-segments:loop/disp32 - 804 $read-segments:break: - 805 $read-segments:end: - 806 # . reclaim locals - 807 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x214/imm32 # add to ESP - 808 # . restore registers - 809 59/pop-to-ECX - 810 # . epilog - 811 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 812 5d/pop-to-EBP - 813 c3/return - 814 - 815 write-segments: # out : (address buffered-file), table : (address stream row) - 816 # pseudocode: - 817 # name, stream = table[0] - 818 # var i = 0 - 819 # while i < table.length - 820 # name = table[i].name - 821 # if (name == null) break - 822 # write-buffered(out, "== ") - 823 # write-buffered(out, name) - 824 # write-buffered(out, "\n") - 825 # stream = table[i].stream - 826 # write-stream-data(out, stream) - 827 # ++i - 828 # flush(out) - 829 # - 830 # . prolog - 831 55/push-EBP - 832 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 833 # . save registers - 834 $write-segments:end: - 835 # . reclaim locals - 836 # . restore registers - 837 # . epilog - 838 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 839 5d/pop-to-EBP - 840 c3/return - 841 - 842 ## helpers - 843 - 844 # TODO: pass in an allocation descriptor - 845 get-or-insert-segment: # table : (address stream row), s : (address slice), n : int -> EAX : (address stream) - 846 # pseudocode: - 847 # curr = table->data - 848 # max = &table->data[table->write] - 849 # while curr < max - 850 # if slice-equal?(s, *curr) - 851 # return *(curr+4) - 852 # curr += 8 - 853 # if table->write < table->length - 854 # *max = slice-to-string(Heap, s) - 855 # result = new-stream(Heap, n, 1) - 856 # *(max+4) = result - 857 # table->write += 8 - 858 # return result - 859 # return 0 - 860 # - 861 # . prolog - 862 55/push-EBP - 863 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 864 # . save registers - 865 51/push-ECX - 866 52/push-EDX - 867 56/push-ESI - 868 # ESI = table - 869 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI - 870 # curr/ECX = table->data - 871 8d/copy-address 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 0xc/disp8 . # copy ESI+12 to ECX - 872 # max/EDX = table->data + table->write - 873 8b/copy 0/mod/indirect 6/rm32/ESI . . . 2/r32/EDX . . # copy *ESI to EDX - 874 8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ECX 2/index/EDX . 2/r32/EDX . . # copy ECX+EDX to EDX - 875 $get-or-insert-segment:search-loop: - 876 # if (curr >= max) break - 877 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX and EDX - 878 7d/jump-if-greater-or-equal $get-or-insert-segment:not-found/disp8 - 879 # if (slice-equal?(s, *curr)) return *(curr+4) - 880 # . EAX = slice-equal?(s, *curr) - 881 # . . push args - 882 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX - 883 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 884 # . . call - 885 e8/call slice-equal?/disp32 - 886 # . . discard args - 887 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 888 # . if (EAX != 0) return EAX = *(curr+4) - 889 3d/compare-EAX-and 0/imm32 - 890 74/jump-if-equal $get-or-insert-segment:mismatch/disp8 - 891 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX - 892 eb/jump $get-or-insert-segment:end/disp8 - 893 $get-or-insert-segment:mismatch: - 894 # curr += 8 - 895 81 0/subop/add 3/mod/direct 1/rm32/ECX . . . . . 8/imm32 # add to ECX - 896 # loop - 897 eb/jump $get-or-insert-segment:search-loop/disp8 - 898 $get-or-insert-segment:not-found: - 899 # result/EAX = 0 - 900 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX - 901 # if (table->write >= table->length) abort - 902 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX - 903 3b/compare 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 8/disp8 . # compare ECX with *(ESI+8) - 904 7d/jump-if-greater-or-equal $get-or-insert-segment:abort/disp8 - 905 # *max = slice-to-string(Heap, s) - 906 # . EAX = slice-to-string(Heap, s) - 907 # . . push args - 908 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 909 68/push Heap/imm32 - 910 # . . call - 911 e8/call slice-to-string/disp32 - 912 # . . discard args - 913 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 914 # . *max = EAX <= writes to 0x0a003873 - 915 89/copy 0/mod/indirect 2/rm32/EDX . . . 0/r32/EAX . . # copy EAX to *EDX - 916 # result/EAX = new-stream(Heap, n, 1) - 917 # . . push args - 918 68/push 1/imm32 - 919 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) - 920 68/push Heap/imm32 - 921 # . . call - 922 e8/call new-stream/disp32 - 923 # . . discard args - 924 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 925 # *(max+4) = result - 926 89/copy 1/mod/*+disp8 2/rm32/EDX . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDX+4) - 927 # table->write += 8 - 928 81 0/subop/add 0/mod/indirect 6/rm32/ESI . . . . . 8/imm32 # add to *ESI - 929 $get-or-insert-segment:end: - 930 # . restore registers - 931 5e/pop-to-ESI - 932 5a/pop-to-EDX - 933 59/pop-to-ECX - 934 # . epilog - 935 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 936 5d/pop-to-EBP - 937 c3/return - 938 - 939 $get-or-insert-segment:abort: - 940 # . _write(2/stderr, error) - 941 # . . push args - 942 68/push "get-or-insert-segment: too many segments"/imm32 - 943 68/push 2/imm32/stderr - 944 # . . call - 945 e8/call _write/disp32 - 946 # . . discard args - 947 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 948 # . syscall(exit, 1) - 949 bb/copy-to-EBX 1/imm32 - 950 b8/copy-to-EAX 1/imm32/exit - 951 cd/syscall 0x80/imm8 - 952 # never gets here - 953 - 954 test-get-or-insert-segment: - 955 # . prolog - 956 55/push-EBP - 957 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 958 # var table/ECX : (address stream byte) = stream(2 * 8) - 959 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # subtract from ESP - 960 68/push 0x10/imm32/length - 961 68/push 0/imm32/read - 962 68/push 0/imm32/write - 963 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - 964 # EDX : (address slice) = "code" - 965 68/push _test-code-segment-end/imm32/end - 966 68/push _test-code-segment/imm32/start - 967 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX - 968 $test-get-or-insert-segment:first-call: - 969 # - start with an empty table, insert one segment, verify that it was inserted - 970 # segment/EAX = get-or-insert-segment(table, "code" slice, 10) - 971 # . . push args - 972 68/push 0xa/imm32/segment-length - 973 52/push-EDX - 974 51/push-ECX - 975 # . . call - 976 e8/call get-or-insert-segment/disp32 - 977 # . . discard args - 978 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 979 # save segment - 980 50/push-EAX - 981 # if (segment != 0) goto next check - 982 3d/compare-EAX-and 0/imm32 - 983 75/jump-if-not-equal $test-get-or-insert-segment:check1/disp8 - 984 # fail test - 985 # . _write(2/stderr, msg) - 986 # . . push args - 987 68/push "F - test-get-or-insert-segment/0"/imm32 - 988 68/push 2/imm32/stderr - 989 # . . call - 990 e8/call _write/disp32 - 991 # . . discard args - 992 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 993 # . _write(2/stderr, Newline) - 994 # . . push args - 995 68/push Newline/imm32 - 996 68/push 2/imm32/stderr - 997 # . . call - 998 e8/call _write/disp32 - 999 # . . discard args -1000 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1001 # . increment Num-test-failures -1002 ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Num-test-failures/disp32 # increment *Num-test-failures -1003 e9/jump $test-get-or-insert-segment:end/disp32 -1004 $test-get-or-insert-segment:check1: -1005 # check-ints-equal(segment->length, 10, msg) -1006 # . . push args -1007 68/push "F - test-get-or-insert-segment/1"/imm32 -1008 68/push 0xa/imm32/segment-length -1009 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 8/disp8 . # push *(EAX+8) -1010 # . . call -1011 e8/call check-ints-equal/disp32 -1012 # . . discard args -1013 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1014 $test-get-or-insert-segment:check2: -1015 # check-ints-equal(table->write, rowsize = 8, msg) -1016 # . . push args -1017 68/push "F - test-get-or-insert-segment/2"/imm32 -1018 68/push 8/imm32/row-size -1019 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX -1020 # . . call -1021 e8/call check-ints-equal/disp32 -1022 # . . discard args -1023 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1024 # EAX = string-equal?(*table->data, "code") -1025 # . . push args -1026 68/push "code"/imm32 -1027 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 0xc/disp8 . # push *(ECX+12) -1028 # . . call -1029 e8/call string-equal?/disp32 -1030 # . . discard args -1031 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1032 # check-ints-equal(EAX, 1, msg) -1033 # . . push args -1034 68/push "F - test-get-or-insert-segment/3"/imm32 -1035 68/push 1/imm32 -1036 50/push-EAX -1037 # . . call -1038 e8/call check-ints-equal/disp32 -1039 # . . discard args -1040 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1041 $test-get-or-insert-segment:check3: -1042 # stream/EAX = *(table->data+4) -1043 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 0x10/disp8 . # copy *(ECX+16) to EAX -1044 # check-ints-equal(stream->length, 10, msg) -1045 # . . push args -1046 68/push "F - test-get-or-insert-segment/4"/imm32 -1047 68/push 0xa/imm32/segment-size -1048 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 8/disp8 . # push *(EAX+8) -1049 # . . call -1050 e8/call check-ints-equal/disp32 -1051 # . . discard args -1052 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1053 $test-get-or-insert-segment:second-call: -1054 # - insert the same segment name again, verify that it was reused -1055 # segment2/EAX = get-or-insert-segment(table, "code" slice, 8) -1056 # . . push args -1057 68/push 8/imm32/segment-length -1058 52/push-EDX -1059 51/push-ECX -1060 # . . call -1061 e8/call get-or-insert-segment/disp32 -1062 # . . discard args -1063 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1064 # restore old segment1 -1065 5a/pop-to-EDX -1066 # check-ints-equal(segment2/EAX, segment1/EDX, msg) -1067 # . . push args -1068 68/push "F - test-get-or-insert-segment/5"/imm32 -1069 52/push-EDX -1070 50/push-EAX -1071 # . . call -1072 e8/call check-ints-equal/disp32 -1073 # . . discard args -1074 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1075 # no change to table size -1076 # . check-ints-equal(table->write, rowsize = 8, msg) -1077 # . . push args -1078 68/push "F - test-get-or-insert-segment/6"/imm32 -1079 68/push 8/imm32/row-size -1080 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX -1081 # . . call -1082 e8/call check-ints-equal/disp32 -1083 # . . discard args -1084 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1085 $test-get-or-insert-segment:third-call: -1086 # - insert a new segment name, verify that it was inserted -1087 # EDX : (address slice) = "data" -1088 c7 0/subop/copy 0/mod/indirect 2/rm32/EDX . . . . . _test-data-segment/imm32 # copy to *EDX -1089 c7 0/subop/copy 1/mod/*+disp8 2/rm32/EDX . . . . 4/disp8 _test-data-segment-end/imm32 # copy to *(EDX+4) -1090 # segment2/EAX = get-or-insert-segment(table, "data" slice, 8) -1091 # . . push args -1092 68/push 8/imm32/segment-length -1093 52/push-EDX -1094 51/push-ECX -1095 # . . call -1096 e8/call get-or-insert-segment/disp32 -1097 # . . discard args -1098 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1099 # table gets a new row -1100 # . check-ints-equal(table->write, 2 rows = 16, msg) -1101 # . . push args -1102 68/push "F - test-get-or-insert-segment/7"/imm32 -1103 68/push 0x10/imm32/two-rows -1104 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX -1105 # . . call -1106 e8/call check-ints-equal/disp32 -1107 # . . discard args -1108 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1109 $test-get-or-insert-segment:end: -1110 # . epilog -1111 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1112 5d/pop-to-EBP -1113 c3/return -1114 -1115 # write an entire stream's contents to a buffered-file -1116 # ways to do this: -1117 # - construct a 'maximal slice' and pass it to write-slice -1118 # - flush the buffered-file and pass the stream directly to its fd (disabling buffering) -1119 # we'll go with the first way for now -1120 write-stream-data: # f : (address buffered-file), s : (address stream) -> <void> -1121 # . prolog -1122 55/push-EBP -1123 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1124 # . save registers -1125 50/push-EAX -1126 51/push-ECX -1127 56/push-ESI -1128 # ESI = s -1129 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI -1130 # var slice/ECX = {s->data, s->data + s->write} -1131 # . push s->data + s->write -1132 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX -1133 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 0/index/EAX . 0/r32/EAX 0xc/disp8 . # copy ESI+EAX+12 to EAX -1134 50/push-EAX -1135 # . push s->data -1136 8d/copy-address 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 0xc/disp8 . # copy ESI+12 to EAX -1137 50/push-EAX -1138 # . ECX = ESP -1139 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1140 # write-slice(f, slice) -1141 # . . push args -1142 51/push-ECX -1143 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 134 test-convert: + 135 # . prolog + 136 55/push-EBP + 137 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 138 # setup + 139 # . clear-stream(_test-input-stream) + 140 # . . push args + 141 68/push _test-input-stream/imm32 + 142 # . . call + 143 e8/call clear-stream/disp32 + 144 # . . discard args + 145 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 146 # . clear-stream(_test-input-buffered-file+4) + 147 # . . push args + 148 b8/copy-to-EAX _test-input-buffered-file/imm32 + 149 05/add-to-EAX 4/imm32 + 150 50/push-EAX + 151 # . . call + 152 e8/call clear-stream/disp32 + 153 # . . discard args + 154 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 155 # . clear-stream(_test-output-stream) + 156 # . . push args + 157 68/push _test-output-stream/imm32 + 158 # . . call + 159 e8/call clear-stream/disp32 + 160 # . . discard args + 161 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 162 # . clear-stream(_test-output-buffered-file+4) + 163 # . . push args + 164 b8/copy-to-EAX _test-output-buffered-file/imm32 + 165 05/add-to-EAX 4/imm32 + 166 50/push-EAX + 167 # . . call + 168 e8/call clear-stream/disp32 + 169 # . . discard args + 170 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 171 # initialize input (meta comments in parens) + 172 # # comment 1 + 173 # # comment 2 indented + 174 # == code (new segment) + 175 # # comment 3 inside a segment + 176 # 1 + 177 # (empty line) + 178 # 2 3 # comment 4 inline with other contents + 179 # == data (new segment) + 180 # 4 5/imm32 + 181 # == code (existing segment but non-contiguous with previous iteration) + 182 # 6 7 + 183 # 8 9 (multiple lines) + 184 # == code (existing segment contiguous with previous iteration) + 185 # 10 11 + 186 # . write(_test-input-stream, "# comment 1\n") + 187 # . . push args + 188 68/push "# comment 1\n"/imm32 + 189 68/push _test-input-stream/imm32 + 190 # . . call + 191 e8/call write/disp32 + 192 # . . discard args + 193 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 194 # . write(_test-input-stream, " # comment 2 indented\n") + 195 # . . push args + 196 68/push " # comment 2 indented\n"/imm32 + 197 68/push _test-input-stream/imm32 + 198 # . . call + 199 e8/call write/disp32 + 200 # . . discard args + 201 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 202 # . write(_test-input-stream, "== code\n") + 203 # . . push args + 204 68/push "== code\n"/imm32 + 205 68/push _test-input-stream/imm32 + 206 # . . call + 207 e8/call write/disp32 + 208 # . . discard args + 209 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 210 # . write(_test-input-stream, "# comment 3 inside a segment\n") + 211 # . . push args + 212 68/push "# comment 3 inside a segment\n"/imm32 + 213 68/push _test-input-stream/imm32 + 214 # . . call + 215 e8/call write/disp32 + 216 # . . discard args + 217 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 218 # . write(_test-input-stream, "1\n") + 219 # . . push args + 220 68/push "1\n"/imm32 + 221 68/push _test-input-stream/imm32 + 222 # . . call + 223 e8/call write/disp32 + 224 # . . discard args + 225 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 226 # . write(_test-input-stream, "\n") # empty line + 227 # . . push args + 228 68/push "\n"/imm32 + 229 68/push _test-input-stream/imm32 + 230 # . . call + 231 e8/call write/disp32 + 232 # . . discard args + 233 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 234 # . write(_test-input-stream, "2 3 # comment 4 inline with other contents\n") + 235 # . . push args + 236 68/push "2 3 # comment 4 inline with other contents\n"/imm32 + 237 68/push _test-input-stream/imm32 + 238 # . . call + 239 e8/call write/disp32 + 240 # . . discard args + 241 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 242 # . write(_test-input-stream, "== data\n") + 243 # . . push args + 244 68/push "== data\n"/imm32 + 245 68/push _test-input-stream/imm32 + 246 # . . call + 247 e8/call write/disp32 + 248 # . . discard args + 249 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 250 # . write(_test-input-stream, "4 5/imm32\n") + 251 # . . push args + 252 68/push "4 5/imm32\n"/imm32 + 253 68/push _test-input-stream/imm32 + 254 # . . call + 255 e8/call write/disp32 + 256 # . . discard args + 257 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 258 # . write(_test-input-stream, "== code\n") + 259 # . . push args + 260 68/push "== code\n"/imm32 + 261 68/push _test-input-stream/imm32 + 262 # . . call + 263 e8/call write/disp32 + 264 # . . discard args + 265 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 266 # . write(_test-input-stream, "6 7\n") + 267 # . . push args + 268 68/push "6 7\n"/imm32 + 269 68/push _test-input-stream/imm32 + 270 # . . call + 271 e8/call write/disp32 + 272 # . . discard args + 273 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 274 # . write(_test-input-stream, "8 9\n") + 275 # . . push args + 276 68/push "8 9\n"/imm32 + 277 68/push _test-input-stream/imm32 + 278 # . . call + 279 e8/call write/disp32 + 280 # . . discard args + 281 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 282 # . write(_test-input-stream, "== code\n") + 283 # . . push args + 284 68/push "== code\n"/imm32 + 285 68/push _test-input-stream/imm32 + 286 # . . call + 287 e8/call write/disp32 + 288 # . . discard args + 289 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 290 # . write(_test-input-stream, "10 11\n") + 291 # . . push args + 292 68/push "10 11\n"/imm32 + 293 68/push _test-input-stream/imm32 + 294 # . . call + 295 e8/call write/disp32 + 296 # . . discard args + 297 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 298 # convert(_test-input-buffered-file, _test-output-buffered-file) + 299 # . . push args + 300 68/push _test-output-buffered-file/imm32 + 301 68/push _test-input-buffered-file/imm32 + 302 # . . call + 303 e8/call convert/disp32 + 304 # . . discard args + 305 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 306 # check output + 307 # == code + 308 # 1 + 309 # 2 3 # comment 4 inline with other contents + 310 # 6 7 + 311 # 8 9 + 312 # 10 11 + 313 # == data + 314 # 4 5/imm32 + 315 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- + 341 # . flush(_test-output-buffered-file) + 342 # . . push args + 343 68/push _test-output-buffered-file/imm32 + 344 # . . call + 345 e8/call flush/disp32 + 346 # . . discard args + 347 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 348 # . check-next-stream-line-equal(_test-output-stream, "== code", msg) + 349 # . . push args + 350 68/push "F - test-convert/0"/imm32 + 351 68/push "== code"/imm32 + 352 68/push _test-output-stream/imm32 + 353 # . . call + 354 e8/call check-next-stream-line-equal/disp32 + 355 # . . discard args + 356 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 357 # . check-next-stream-line-equal(_test-output-stream, "1", msg) + 358 # . . push args + 359 68/push "F - test-convert/1"/imm32 + 360 68/push "1"/imm32 + 361 68/push _test-output-stream/imm32 + 362 # . . call + 363 e8/call check-next-stream-line-equal/disp32 + 364 # . . discard args + 365 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 366 # . check-next-stream-line-equal(_test-output-stream, "2 3 # comment 4 inline with other contents", msg) + 367 # . . push args + 368 68/push "F - test-convert/2"/imm32 + 369 68/push "2 3 # comment 4 inline with other contents"/imm32 + 370 68/push _test-output-stream/imm32 + 371 # . . call + 372 e8/call check-next-stream-line-equal/disp32 + 373 # . . discard args + 374 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 375 # . check-next-stream-line-equal(_test-output-stream, "6 7", msg) + 376 # . . push args + 377 68/push "F - test-convert/3"/imm32 + 378 68/push "6 7"/imm32 + 379 68/push _test-output-stream/imm32 + 380 # . . call + 381 e8/call check-next-stream-line-equal/disp32 + 382 # . . discard args + 383 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 384 # . check-next-stream-line-equal(_test-output-stream, "8 9", msg) + 385 # . . push args + 386 68/push "F - test-convert/4"/imm32 + 387 68/push "8 9"/imm32 + 388 68/push _test-output-stream/imm32 + 389 # . . call + 390 e8/call check-next-stream-line-equal/disp32 + 391 # . . discard args + 392 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 393 # . check-next-stream-line-equal(_test-output-stream, "10 11", msg) + 394 # . . push args + 395 68/push "F - test-convert/5"/imm32 + 396 68/push "10 11"/imm32 + 397 68/push _test-output-stream/imm32 + 398 # . . call + 399 e8/call check-next-stream-line-equal/disp32 + 400 # . . discard args + 401 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 402 # . check-next-stream-line-equal(_test-output-stream, "== data", msg) + 403 # . . push args + 404 68/push "F - test-convert/6"/imm32 + 405 68/push "== data"/imm32 + 406 68/push _test-output-stream/imm32 + 407 # . . call + 408 e8/call check-next-stream-line-equal/disp32 + 409 # . . discard args + 410 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 411 # . check-next-stream-line-equal(_test-output-stream, "4 5/imm32", msg) + 412 # . . push args + 413 68/push "F - test-convert/7"/imm32 + 414 68/push "4 5/imm32"/imm32 + 415 68/push _test-output-stream/imm32 + 416 # . . call + 417 e8/call check-next-stream-line-equal/disp32 + 418 # . . discard args + 419 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 420 # . epilog + 421 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 422 5d/pop-to-EBP + 423 c3/return + 424 + 425 read-segments: # in : (address buffered-file), table : (address stream row) + 426 # pseudocode: + 427 # var curr-segment = null + 428 # var line = new-stream(512, 1) + 429 # while true + 430 # clear-stream(line) + 431 # read-line(in, line) + 432 # if (line->write == 0) break # end of file + 433 # var word-slice = next-word(line) + 434 # if slice-empty?(word-slice) # whitespace + 435 # continue + 436 # if slice-starts-with?(word-slice, "#") # comment + 437 # continue + 438 # if slice-equal?(word-slice, "==") + 439 # var segment-name = next-word(line) + 440 # curr-segment = get-or-insert-segment(table, segment-name, Segment-size) + 441 # else + 442 # rewind-stream(line) + 443 # write-stream(curr-segment, line) # abort if curr-segment overflows + 444 # + 445 # word-slice and segment-name are both slices with disjoint lifetimes, so + 446 # we'll use the same address for them. + 447 # + 448 # registers: + 449 # line: ECX + 450 # word-slice and segment-name: EDX + 451 # segment-name and curr-segment: EBX + 452 # word-slice->start: ESI + 453 # temporary: EAX + 454 # + 455 # . prolog + 456 55/push-EBP + 457 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 458 # . save registers + 459 50/push-EAX + 460 51/push-ECX + 461 52/push-EDX + 462 53/push-EBX + 463 56/push-ESI + 464 # var line/ECX : (address stream byte) = stream(512) + 465 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0x200/imm32 # subtract from ESP + 466 68/push 0x200/imm32/length + 467 68/push 0/imm32/read + 468 68/push 0/imm32/write + 469 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 470 # var word-slice/EDX = {0, 0} + 471 68/push 0/imm32/end + 472 68/push 0/imm32/curr + 473 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX + 474 $read-segments:loop: + 475 # clear-stream(line) + 476 # . . push args + 477 51/push-ECX + 478 # . . call + 479 e8/call clear-stream/disp32 + 480 # . . discard args + 481 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 482 # read-line(in, line) + 483 # . . push args + 484 51/push-ECX + 485 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 486 # . . call + 487 e8/call read-line/disp32 + 488 # . . discard args + 489 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 490 $read-segments:check0: + 491 # if (line->write == 0) break + 492 81 7/subop/compare 0/mod/indirect 1/rm32/ECX . . . . . 0/imm32 # compare *ECX + 493 0f 84/jump-if-equal $read-segments:break/disp32 + 494 +-- 26 lines: #? # dump line ----------------------------------------------------------------------------------------------------------------------------- + 520 # next-word(line, word-slice) + 521 # . . push args + 522 52/push-EDX + 523 51/push-ECX + 524 # . . call + 525 e8/call next-word/disp32 + 526 # . . discard args + 527 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 528 $read-segments:check1: + 529 # if (slice-empty?(word-slice)) continue + 530 # . EAX = slice-empty?(word-slice) + 531 # . . push args + 532 52/push-EDX + 533 # . . call + 534 e8/call slice-empty?/disp32 + 535 # . . discard args + 536 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 537 # . if (EAX != 0) continue + 538 3d/compare-EAX-and 0/imm32 + 539 0f 85/jump-if-not-equal $read-segments:loop/disp32 + 540 $read-segments:check-for-comment: + 541 # if (slice-starts-with?(word-slice, "#")) continue + 542 # . start/ESI = word-slice->start + 543 8b/copy 0/mod/indirect 2/rm32/EDX . . . 6/r32/ESI . . # copy *ECX to ESI + 544 # . c/EAX = *start + 545 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX + 546 8a/copy-byte 0/mod/indirect 6/rm32/ESI . . . 0/r32/AL . . # copy byte at *ESI to AL + 547 # . if (EAX == '#') continue + 548 3d/compare-EAX-and 0x23/imm32/hash + 549 0f 84/jump-if-equal $read-segments:loop/disp32 + 550 $read-segments:check-for-segment-header: + 551 +-- 42 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- + 593 # if slice-equal?(word-slice, "==") + 594 # segment-name = next-word(line) + 595 # curr-segment = get-or-insert(table, segment-name) + 596 # . EAX = slice-equal?(word-slice, "==") + 597 # . . push args + 598 68/push "=="/imm32 + 599 52/push-EDX + 600 # . . call + 601 e8/call slice-equal?/disp32 + 602 # . . discard args + 603 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 604 # . if (EAX == 0) goto check3 + 605 3d/compare-EAX-and 0/imm32 + 606 0f 84/jump-if-equal $read-segments:regular-line/disp32 + 607 # . next-word(line, segment-name) + 608 # . . push args + 609 52/push-EDX + 610 51/push-ECX + 611 # . . call + 612 e8/call next-word/disp32 + 613 # . . discard args + 614 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 615 +-- 42 lines: #? # dump segment name --------------------------------------------------------------------------------------------------------------------- + 657 # . EAX = get-or-insert-segment(table, segment-name, Segment-size) + 658 # . . push args + 659 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Segment-size/disp32 # push *Segment-size + 660 52/push-EDX + 661 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 662 # . . call + 663 e8/call get-or-insert-segment/disp32 + 664 # . . discard args + 665 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 666 # . curr-segment = EAX + 667 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX + 668 # . continue + 669 e9/jump $read-segments:loop/disp32 + 670 $read-segments:regular-line: + 671 # rewind-stream(line) + 672 # . . push args + 673 51/push-ECX + 674 # . . call + 675 e8/call rewind-stream/disp32 + 676 # . . discard args + 677 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 678 # write-stream(curr-segment, line) + 679 # . . push args + 680 51/push-ECX + 681 53/push-EBX + 682 # . . call + 683 e8/call write-stream/disp32 + 684 # . . discard args + 685 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 686 # loop + 687 e9/jump $read-segments:loop/disp32 + 688 $read-segments:break: + 689 $read-segments:end: + 690 # . reclaim locals + 691 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x214/imm32 # add to ESP + 692 # . restore registers + 693 5e/pop-to-ESI + 694 5b/pop-to-EBX + 695 5a/pop-to-EDX + 696 59/pop-to-ECX + 697 58/pop-to-EAX + 698 # . epilog + 699 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 700 5d/pop-to-EBP + 701 c3/return + 702 + 703 write-segments: # out : (address buffered-file), table : (address stream row) + 704 # pseudocode: + 705 # var curr = table->data + 706 # var max = table->data + table->write + 707 # while curr < max + 708 # name = table[i].name + 709 # print out, "== $name\n" + 710 # stream = table[i].stream + 711 # write-stream-data(out, stream) + 712 # curr += 8 + 713 # flush(out) + 714 # + 715 # . prolog + 716 55/push-EBP + 717 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 718 # . save registers + 719 50/push-EAX + 720 52/push-EDX + 721 56/push-ESI + 722 # ESI = table + 723 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI + 724 # write/EDX = table->write + 725 8b/copy 0/mod/indirect 6/rm32/ESI . . . 2/r32/EDX . . # copy *ESI to EDX + 726 # curr/ESI = table->data + 727 81 0/subop/add 3/mod/direct 6/rm32/ESI . . . . . 0xc/imm32 # add to EAX + 728 # max/EDX = curr + write + 729 01/add 3/mod/direct 2/rm32/EDX . . . 6/r32/ESI . . # add ESI to EDX + 730 $write-segments:loop: + 731 # if (curr >= max) break + 732 39/compare 3/mod/direct 6/rm32/ESI . . . 2/r32/EDX . . # compare ESI with EDX + 733 7d/jump-if-greater-or-equal $write-segments:break/disp8 + 734 # name/EAX = table[i].name + 735 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX + 736 # print out, "== $name\n" + 737 # . write-buffered(out, "== ") + 738 # . . push args + 739 68/push "== "/imm32 + 740 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 741 # . . call + 742 e8/call write-buffered/disp32 + 743 # . . discard args + 744 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 745 # . write-buffered(out, name) + 746 # . . push args + 747 50/push-EAX + 748 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 749 # . . call + 750 e8/call write-buffered/disp32 + 751 # . . discard args + 752 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 753 # . write-buffered(out, "\n") + 754 # . . push args + 755 68/push Newline/imm32 + 756 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 757 # . . call + 758 e8/call write-buffered/disp32 + 759 # . . discard args + 760 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 761 # stream/EAX = table[i].stream + 762 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy *(ESI+4) to EAX + 763 # write-stream-data(out, stream) + 764 # . . push args + 765 50/push-EAX + 766 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 767 # . . call + 768 e8/call write-stream-data/disp32 + 769 # . . discard args + 770 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 771 $write-segments:continue: + 772 # curr += 8 + 773 81 0/subop/add 3/mod/direct 6/rm32/ESI . . . . . 8/imm32 # add to ESI + 774 eb/jump $write-segments:loop/disp8 + 775 $write-segments:break: + 776 # flush(out) + 777 # . . push args + 778 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 779 # . . call + 780 e8/call flush/disp32 + 781 # . . discard args + 782 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 783 $write-segments:end: + 784 # . restore registers + 785 5e/pop-to-ESI + 786 5a/pop-to-EDX + 787 58/pop-to-EAX + 788 # . epilog + 789 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 790 5d/pop-to-EBP + 791 c3/return + 792 + 793 ## helpers + 794 + 795 # TODO: pass in an allocation descriptor + 796 get-or-insert-segment: # table : (address stream row), s : (address slice), n : int -> EAX : (address stream) + 797 # pseudocode: + 798 # curr = table->data + 799 # max = &table->data[table->write] + 800 # while curr < max + 801 # if slice-equal?(s, *curr) + 802 # return *(curr+4) + 803 # curr += 8 + 804 # if table->write < table->length + 805 # *max = slice-to-string(Heap, s) + 806 # result = new-stream(Heap, n, 1) + 807 # *(max+4) = result + 808 # table->write += 8 + 809 # return result + 810 # return 0 + 811 # + 812 # . prolog + 813 55/push-EBP + 814 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 815 # . save registers + 816 51/push-ECX + 817 52/push-EDX + 818 56/push-ESI + 819 # ESI = table + 820 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI + 821 # curr/ECX = table->data + 822 8d/copy-address 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 0xc/disp8 . # copy ESI+12 to ECX + 823 # max/EDX = table->data + table->write + 824 8b/copy 0/mod/indirect 6/rm32/ESI . . . 2/r32/EDX . . # copy *ESI to EDX + 825 8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ECX 2/index/EDX . 2/r32/EDX . . # copy ECX+EDX to EDX + 826 $get-or-insert-segment:search-loop: + 827 # if (curr >= max) break + 828 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX + 829 7d/jump-if-greater-or-equal $get-or-insert-segment:not-found/disp8 + 830 # if (slice-equal?(s, *curr)) return *(curr+4) + 831 # . EAX = slice-equal?(s, *curr) + 832 # . . push args + 833 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX + 834 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 835 # . . call + 836 e8/call slice-equal?/disp32 + 837 # . . discard args + 838 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 839 # . if (EAX != 0) return EAX = *(curr+4) + 840 3d/compare-EAX-and 0/imm32 + 841 74/jump-if-equal $get-or-insert-segment:mismatch/disp8 + 842 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX + 843 eb/jump $get-or-insert-segment:end/disp8 + 844 $get-or-insert-segment:mismatch: + 845 # curr += 8 + 846 81 0/subop/add 3/mod/direct 1/rm32/ECX . . . . . 8/imm32 # add to ECX + 847 # loop + 848 eb/jump $get-or-insert-segment:search-loop/disp8 + 849 $get-or-insert-segment:not-found: + 850 # result/EAX = 0 + 851 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX + 852 # if (table->write >= table->length) abort + 853 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX + 854 3b/compare 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 8/disp8 . # compare ECX with *(ESI+8) + 855 7d/jump-if-greater-or-equal $get-or-insert-segment:abort/disp8 + 856 # *max = slice-to-string(Heap, s) + 857 # . EAX = slice-to-string(Heap, s) + 858 # . . push args + 859 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 860 68/push Heap/imm32 + 861 # . . call + 862 e8/call slice-to-string/disp32 + 863 # . . discard args + 864 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 865 # . *max = EAX + 866 89/copy 0/mod/indirect 2/rm32/EDX . . . 0/r32/EAX . . # copy EAX to *EDX + 867 # result/EAX = new-stream(Heap, n, 1) + 868 # . . push args + 869 68/push 1/imm32 + 870 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 871 68/push Heap/imm32 + 872 # . . call + 873 e8/call new-stream/disp32 + 874 # . . discard args + 875 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 876 # *(max+4) = result + 877 89/copy 1/mod/*+disp8 2/rm32/EDX . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDX+4) + 878 # table->write += 8 + 879 81 0/subop/add 0/mod/indirect 6/rm32/ESI . . . . . 8/imm32 # add to *ESI + 880 $get-or-insert-segment:end: + 881 # . restore registers + 882 5e/pop-to-ESI + 883 5a/pop-to-EDX + 884 59/pop-to-ECX + 885 # . epilog + 886 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 887 5d/pop-to-EBP + 888 c3/return + 889 + 890 $get-or-insert-segment:abort: + 891 # . _write(2/stderr, error) + 892 # . . push args + 893 68/push "get-or-insert-segment: too many segments"/imm32 + 894 68/push 2/imm32/stderr + 895 # . . call + 896 e8/call _write/disp32 + 897 # . . discard args + 898 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 899 # . syscall(exit, 1) + 900 bb/copy-to-EBX 1/imm32 + 901 b8/copy-to-EAX 1/imm32/exit + 902 cd/syscall 0x80/imm8 + 903 # never gets here + 904 + 905 test-get-or-insert-segment: + 906 # . prolog + 907 55/push-EBP + 908 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 909 # var table/ECX : (address stream byte) = stream(2 * 8) + 910 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # subtract from ESP + 911 68/push 0x10/imm32/length + 912 68/push 0/imm32/read + 913 68/push 0/imm32/write + 914 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 915 # EDX : (address slice) = "code" + 916 68/push _test-code-segment-end/imm32/end + 917 68/push _test-code-segment/imm32/start + 918 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX + 919 $test-get-or-insert-segment:first-call: + 920 # - start with an empty table, insert one segment, verify that it was inserted + 921 # segment/EAX = get-or-insert-segment(table, "code" slice, 10) + 922 # . . push args + 923 68/push 0xa/imm32/segment-length + 924 52/push-EDX + 925 51/push-ECX + 926 # . . call + 927 e8/call get-or-insert-segment/disp32 + 928 # . . discard args + 929 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 930 # save segment + 931 50/push-EAX + 932 # if (segment != 0) goto next check + 933 3d/compare-EAX-and 0/imm32 + 934 75/jump-if-not-equal $test-get-or-insert-segment:check1/disp8 + 935 # fail test + 936 # . _write(2/stderr, msg) + 937 # . . push args + 938 68/push "F - test-get-or-insert-segment/0\n"/imm32 + 939 68/push 2/imm32/stderr + 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 # . increment Num-test-failures + 945 ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Num-test-failures/disp32 # increment *Num-test-failures + 946 e9/jump $test-get-or-insert-segment:end/disp32 + 947 $test-get-or-insert-segment:check1: + 948 # check-ints-equal(segment->length, 10, msg) + 949 # . . push args + 950 68/push "F - test-get-or-insert-segment/1"/imm32 + 951 68/push 0xa/imm32/segment-length + 952 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 8/disp8 . # push *(EAX+8) + 953 # . . call + 954 e8/call check-ints-equal/disp32 + 955 # . . discard args + 956 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 957 $test-get-or-insert-segment:check2: + 958 # check-ints-equal(table->write, rowsize = 8, msg) + 959 # . . push args + 960 68/push "F - test-get-or-insert-segment/2"/imm32 + 961 68/push 8/imm32/row-size + 962 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX + 963 # . . call + 964 e8/call check-ints-equal/disp32 + 965 # . . discard args + 966 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 967 # EAX = string-equal?(*table->data, "code") + 968 # . . push args + 969 68/push "code"/imm32 + 970 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 0xc/disp8 . # push *(ECX+12) + 971 # . . call + 972 e8/call string-equal?/disp32 + 973 # . . discard args + 974 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 975 # check-ints-equal(EAX, 1, msg) + 976 # . . push args + 977 68/push "F - test-get-or-insert-segment/3"/imm32 + 978 68/push 1/imm32 + 979 50/push-EAX + 980 # . . call + 981 e8/call check-ints-equal/disp32 + 982 # . . discard args + 983 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 984 $test-get-or-insert-segment:check3: + 985 # stream/EAX = *(table->data+4) + 986 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 0x10/disp8 . # copy *(ECX+16) to EAX + 987 # check-ints-equal(stream->length, 10, msg) + 988 # . . push args + 989 68/push "F - test-get-or-insert-segment/4"/imm32 + 990 68/push 0xa/imm32/segment-size + 991 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 8/disp8 . # push *(EAX+8) + 992 # . . call + 993 e8/call check-ints-equal/disp32 + 994 # . . discard args + 995 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 996 $test-get-or-insert-segment:second-call: + 997 # - insert the same segment name again, verify that it was reused + 998 # segment2/EAX = get-or-insert-segment(table, "code" slice, 8) + 999 # . . push args +1000 68/push 8/imm32/segment-length +1001 52/push-EDX +1002 51/push-ECX +1003 # . . call +1004 e8/call get-or-insert-segment/disp32 +1005 # . . discard args +1006 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1007 # restore old segment1 +1008 5a/pop-to-EDX +1009 # check-ints-equal(segment2/EAX, segment1/EDX, msg) +1010 # . . push args +1011 68/push "F - test-get-or-insert-segment/5"/imm32 +1012 52/push-EDX +1013 50/push-EAX +1014 # . . call +1015 e8/call check-ints-equal/disp32 +1016 # . . discard args +1017 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1018 # no change to table size +1019 # . check-ints-equal(table->write, rowsize = 8, msg) +1020 # . . push args +1021 68/push "F - test-get-or-insert-segment/6"/imm32 +1022 68/push 8/imm32/row-size +1023 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX +1024 # . . call +1025 e8/call check-ints-equal/disp32 +1026 # . . discard args +1027 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1028 $test-get-or-insert-segment:third-call: +1029 # - insert a new segment name, verify that it was inserted +1030 # EDX : (address slice) = "data" +1031 c7 0/subop/copy 0/mod/indirect 2/rm32/EDX . . . . . _test-data-segment/imm32 # copy to *EDX +1032 c7 0/subop/copy 1/mod/*+disp8 2/rm32/EDX . . . . 4/disp8 _test-data-segment-end/imm32 # copy to *(EDX+4) +1033 # segment2/EAX = get-or-insert-segment(table, "data" slice, 8) +1034 # . . push args +1035 68/push 8/imm32/segment-length +1036 52/push-EDX +1037 51/push-ECX +1038 # . . call +1039 e8/call get-or-insert-segment/disp32 +1040 # . . discard args +1041 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1042 # table gets a new row +1043 # . check-ints-equal(table->write, 2 rows = 16, msg) +1044 # . . push args +1045 68/push "F - test-get-or-insert-segment/7"/imm32 +1046 68/push 0x10/imm32/two-rows +1047 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX +1048 # . . call +1049 e8/call check-ints-equal/disp32 +1050 # . . discard args +1051 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1052 $test-get-or-insert-segment:end: +1053 # . epilog +1054 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1055 5d/pop-to-EBP +1056 c3/return +1057 +1058 # (re)compute the bounds of the next word in the line +1059 # return empty string on reaching end of file +1060 next-word: # line : (address stream byte), out : (address slice) +1061 # . prolog +1062 55/push-EBP +1063 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1064 # . save registers +1065 50/push-EAX +1066 51/push-ECX +1067 56/push-ESI +1068 57/push-EDI +1069 # ESI = line +1070 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +1071 # EDI = out +1072 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI +1073 # skip-chars-matching(line, ' ') +1074 # . . push args +1075 68/push 0x20/imm32/space +1076 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1077 # . . call +1078 e8/call skip-chars-matching/disp32 +1079 # . . discard args +1080 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1081 $next-word:check0: +1082 # if (line->read >= line->write) clear out and return +1083 # . EAX = line->read +1084 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy *(ESI+4) to EAX +1085 # . if (EAX < line->write) goto next check +1086 3b/compare 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # compare EAX with *ESI +1087 7c/jump-if-lesser $next-word:check-for-comment/disp8 +1088 # . return out = {0, 0} +1089 c7 0/subop/copy 0/mod/direct 7/rm32/EDI . . . . . 0/imm32 # copy to *EDI +1090 c7 0/subop/copy 1/mod/*+disp8 7/rm32/EDI . . . . 4/disp8 0/imm32 # copy to *(EDI+4) +1091 eb/jump $next-word:end/disp8 +1092 $next-word:check-for-comment: +1093 # out->start = &line->data[line->read] +1094 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX +1095 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 1/index/ECX . 0/r32/EAX 0xc/disp8 . # copy ESI+ECX+12 to EAX +1096 89/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to *EDI +1097 # if (line->data[line->read] == '#') out->end = &line->data[line->write]), skip rest of stream and return +1098 # . EAX = line->data[line->read] +1099 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +1100 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/ESI 1/index/ECX . 0/r32/AL 0xc/disp8 . # copy byte at *(ESI+ECX+12) to AL +1101 # . compare +1102 3d/compare-EAX-and 0x23/imm32/pound +1103 75/jump-if-not-equal $next-word:regular-word/disp8 +1104 $next-word:comment: +1105 # . out->end = &line->data[line->write] +1106 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX +1107 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 0/index/EAX . 0/r32/EAX 0xc/disp8 . # copy ESI+EAX+12 to EAX +1108 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDI+4) +1109 # . line->read = line->write +1110 89/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(ESI+4) +1111 # . return +1112 eb/jump $next-word:end/disp8 +1113 $next-word:regular-word: +1114 # otherwise skip-chars-not-matching-whitespace(line) # including trailing newline +1115 # . . push args +1116 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1117 # . . call +1118 e8/call skip-chars-not-matching-whitespace/disp32 +1119 # . . discard args +1120 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1121 # out->end = &line->data[line->read] +1122 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX +1123 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 1/index/ECX . 0/r32/EAX 0xc/disp8 . # copy ESI+ECX+12 to EAX +1124 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDI+4) +1125 $next-word:end: +1126 # . restore registers +1127 5f/pop-to-EDI +1128 5e/pop-to-ESI +1129 59/pop-to-ECX +1130 58/pop-to-EAX +1131 # . epilog +1132 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1133 5d/pop-to-EBP +1134 c3/return +1135 +1136 test-next-word: +1137 # . prolog +1138 55/push-EBP +1139 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1140 # setup +1141 # . clear-stream(_test-stream) +1142 # . . push args +1143 68/push _test-stream/imm32 1144 # . . call -1145 e8/call write-slice/disp32 +1145 e8/call clear-stream/disp32 1146 # . . discard args -1147 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1148 $write-stream-data:end: -1149 # . restore locals -1150 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1151 # . restore registers -1152 5e/pop-to-ESI -1153 59/pop-to-ECX -1154 58/pop-to-EAX -1155 # . epilog -1156 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1157 5d/pop-to-EBP -1158 c3/return -1159 -1160 test-write-stream-data: -1161 # . prolog -1162 55/push-EBP -1163 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1164 # setup -1165 # . clear-stream(_test-stream) -1166 # . . push args -1167 68/push _test-stream/imm32 -1168 # . . call -1169 e8/call clear-stream/disp32 -1170 # . . discard args -1171 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1172 # . clear-stream(_test-buffered-file+4) -1173 # . . push args -1174 b8/copy-to-EAX _test-buffered-file/imm32 -1175 05/add-to-EAX 4/imm32 +1147 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1148 # var slice/ECX = {0, 0} +1149 68/push 0/imm32/end +1150 68/push 0/imm32/start +1151 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1152 # write(_test-stream, " ab") +1153 # . . push args +1154 68/push " ab"/imm32 +1155 68/push _test-stream/imm32 +1156 # . . call +1157 e8/call write/disp32 +1158 # . . discard args +1159 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1160 # next-word(_test-stream, slice) +1161 # . . push args +1162 51/push-ECX +1163 68/push _test-stream/imm32 +1164 # . . call +1165 e8/call next-word/disp32 +1166 # . . discard args +1167 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1168 # check-ints-equal(slice->start - _test-stream->data, 2, msg) +1169 # . check-ints-equal(slice->start - _test-stream, 14, msg) +1170 # . . push args +1171 68/push "F - test-next-word: start"/imm32 +1172 68/push 0xe/imm32 +1173 # . . push slice->start - _test-stream +1174 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX +1175 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-stream/imm32 # subtract from EAX 1176 50/push-EAX 1177 # . . call -1178 e8/call clear-stream/disp32 +1178 e8/call check-ints-equal/disp32 1179 # . . discard args -1180 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1181 # . clear-stream(_test-tmp-stream) -1182 # . . push args -1183 68/push _test-tmp-stream/imm32 -1184 # . . call -1185 e8/call clear-stream/disp32 -1186 # . . discard args -1187 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1188 # initialize input -1189 # . write(_test-tmp-stream, "abcd") -1190 # . . push args -1191 68/push "abcd"/imm32 -1192 68/push _test-tmp-stream/imm32 -1193 # . . call -1194 e8/call write/disp32 -1195 # . . discard args -1196 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1197 # write-stream-data(_test-buffered-file, _test-tmp-stream) -1198 # . . push args -1199 68/push _test-tmp-stream/imm32 -1200 68/push _test-buffered-file/imm32 -1201 # . . call -1202 e8/call write-stream-data/disp32 -1203 # . . discard args -1204 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1205 # check that the write happened as expected -1206 # . flush(_test-buffered-file) -1207 # . . push args -1208 68/push _test-buffered-file/imm32 -1209 # . . call -1210 e8/call flush/disp32 -1211 # . . discard args -1212 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1213 # . check-stream-equal(_test-stream, "abcd", msg) -1214 # . . push args -1215 68/push "F - test-write-stream-data"/imm32 -1216 68/push "abcd"/imm32 -1217 68/push _test-stream/imm32 -1218 # . . call -1219 e8/call check-stream-equal/disp32 -1220 # . . discard args -1221 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1222 # . epilog -1223 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1224 5d/pop-to-EBP -1225 c3/return -1226 -1227 == data -1228 -1229 _test-input-stream: -1230 # current write index -1231 0/imm32 -1232 # current read index -1233 0/imm32 -1234 # length -1235 0x100/imm32 # 256 bytes -1236 # data (16 lines x 16 bytes/line) -1237 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1238 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1239 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1240 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1241 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1242 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1243 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1244 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1245 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1246 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1247 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1248 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1249 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1250 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1251 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1252 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1253 -1254 # a test buffered file for _test-input-stream -1255 _test-input-buffered-file: -1256 # file descriptor or (address stream) -1257 _test-input-stream/imm32 -1258 # current write index -1259 0/imm32 -1260 # current read index -1261 0/imm32 -1262 # length -1263 6/imm32 -1264 # data -1265 00 00 00 00 00 00 # 6 bytes -1266 -1267 _test-output-stream: -1268 # current write index -1269 0/imm32 -1270 # current read index -1271 0/imm32 -1272 # length -1273 0x100/imm32 # 256 bytes -1274 # data (16 lines x 16 bytes/line) -1275 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1276 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1277 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1278 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1279 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1280 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1281 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1282 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1283 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1284 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1285 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1286 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1287 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1288 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1289 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1290 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1291 -1292 # a test buffered file for _test-output-stream -1293 _test-output-buffered-file: -1294 # file descriptor or (address stream) -1295 _test-output-stream/imm32 -1296 # current write index -1297 0/imm32 -1298 # current read index -1299 0/imm32 -1300 # length -1301 6/imm32 -1302 # data -1303 00 00 00 00 00 00 # 6 bytes -1304 -1305 _test-code-segment: -1306 63/c 6f/o 64/d 65/e -1307 _test-code-segment-end: -1308 -1309 _test-data-segment: -1310 64/d 61/a 74/t 61/a -1311 _test-data-segment-end: -1312 -1313 # . . vim:nowrap:textwidth=0 +1180 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1181 # check-ints-equal(slice->end - _test-stream->data, 4, msg) +1182 # . check-ints-equal(slice->end - _test-stream, 16, msg) +1183 # . . push args +1184 68/push "F - test-next-word: end"/imm32 +1185 68/push 0x10/imm32 +1186 # . . push slice->end - _test-stream +1187 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +1188 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-stream/imm32 # subtract from EAX +1189 50/push-EAX +1190 # . . call +1191 e8/call check-ints-equal/disp32 +1192 # . . discard args +1193 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1194 # . epilog +1195 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1196 5d/pop-to-EBP +1197 c3/return +1198 +1199 test-next-word-returns-whole-comment: +1200 # . prolog +1201 55/push-EBP +1202 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1203 # setup +1204 # . clear-stream(_test-stream) +1205 # . . push args +1206 68/push _test-stream/imm32 +1207 # . . call +1208 e8/call clear-stream/disp32 +1209 # . . discard args +1210 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1211 # var slice/ECX = {0, 0} +1212 68/push 0/imm32/end +1213 68/push 0/imm32/start +1214 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1215 # write(_test-stream, " # a") +1216 # . . push args +1217 68/push " # a"/imm32 +1218 68/push _test-stream/imm32 +1219 # . . call +1220 e8/call write/disp32 +1221 # . . discard args +1222 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1223 # next-word(_test-stream, slice) +1224 # . . push args +1225 51/push-ECX +1226 68/push _test-stream/imm32 +1227 # . . call +1228 e8/call next-word/disp32 +1229 # . . discard args +1230 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1231 # check-ints-equal(slice->start - _test-stream->data, 2, msg) +1232 # . check-ints-equal(slice->start - _test-stream, 14, msg) +1233 # . . push args +1234 68/push "F - test-next-word-returns-whole-comment: start"/imm32 +1235 68/push 0xe/imm32 +1236 # . . push slice->start - _test-stream +1237 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX +1238 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-stream/imm32 # subtract from EAX +1239 50/push-EAX +1240 # . . call +1241 e8/call check-ints-equal/disp32 +1242 # . . discard args +1243 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1244 # check-ints-equal(slice->end - _test-stream->data, 5, msg) +1245 # . check-ints-equal(slice->end - _test-stream, 17, msg) +1246 # . . push args +1247 68/push "F - test-next-word-returns-whole-comment: end"/imm32 +1248 68/push 0x11/imm32 +1249 # . . push slice->end - _test-stream +1250 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +1251 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-stream/imm32 # subtract from EAX +1252 50/push-EAX +1253 # . . call +1254 e8/call check-ints-equal/disp32 +1255 # . . discard args +1256 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1257 # . epilog +1258 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1259 5d/pop-to-EBP +1260 c3/return +1261 +1262 test-next-word-returns-empty-string-on-eof: +1263 # . prolog +1264 55/push-EBP +1265 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1266 # setup +1267 # . clear-stream(_test-stream) +1268 # . . push args +1269 68/push _test-stream/imm32 +1270 # . . call +1271 e8/call clear-stream/disp32 +1272 # . . discard args +1273 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1274 # var slice/ECX = {0, 0} +1275 68/push 0/imm32/end +1276 68/push 0/imm32/start +1277 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1278 # write nothing to _test-stream +1279 # next-word(_test-stream, slice) +1280 # . . push args +1281 51/push-ECX +1282 68/push _test-stream/imm32 +1283 # . . call +1284 e8/call next-word/disp32 +1285 # . . discard args +1286 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1287 # check-ints-equal(slice->end - slice->start, 0, msg) +1288 # . . push args +1289 68/push "F - test-next-word-returns-empty-string-on-eof"/imm32 +1290 68/push 0/imm32 +1291 # . . push slice->end - slice->start +1292 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +1293 2b/subtract 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # subtract *ECX from EAX +1294 50/push-EAX +1295 # . . call +1296 e8/call check-ints-equal/disp32 +1297 # . . discard args +1298 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1299 # . epilog +1300 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1301 5d/pop-to-EBP +1302 c3/return +1303 +1304 == data +1305 +1306 _test-code-segment: +1307 63/c 6f/o 64/d 65/e +1308 _test-code-segment-end: +1309 +1310 _test-data-segment: +1311 64/d 61/a 74/t 61/a +1312 _test-data-segment-end: +1313 +1314 Segment-size: +1315 # TODO: there's currently a tight size limit on segments because we aren't growing the heap +1316 0x100/imm32/4KB +1317 #? 0x1000/imm32/4KB +1318 +1319 # . . vim:nowrap:textwidth=0 diff --git a/html/subx/apps/crenshaw2-1.subx.html b/html/subx/apps/crenshaw2-1.subx.html index e9606427..a2b22c5f 100644 --- a/html/subx/apps/crenshaw2-1.subx.html +++ b/html/subx/apps/crenshaw2-1.subx.html @@ -157,7 +157,7 @@ if ('onhashchange' in window) { 94 # . . push args 95 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) 96 # . . call - 97 e8/call get-char/disp32 + 97 e8/call get-char/disp32 98 # . . discard args 99 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 100 # var num/ECX : (address stream) on the stack @@ -185,7 +185,7 @@ if ('onhashchange' in window) { 122 51/push-ECX/num 123 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) 124 # . . call -125 e8/call get-num/disp32 +125 e8/call get-num/disp32 126 # . . discard args 127 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 128 # render 'num' into the following template on 'out': @@ -217,454 +217,430 @@ if ('onhashchange' in window) { 154 e8/call write/disp32 155 # . . discard args 156 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -157 # . write(out, "b8/copy-to-EAX 1/imm32/exit") +157 # . write(out, "b8/copy-to-EAX 1/imm32/exit\n") 158 # . . push args -159 68/push "b8/copy-to-EAX 1/imm32/exit"/imm32 +159 68/push "b8/copy-to-EAX 1/imm32/exit\n"/imm32 160 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) 161 # . . call 162 e8/call write/disp32 163 # . . discard args 164 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -165 # . write(out, Newline) +165 # . write(out, "cd/syscall 0x80/imm8\n") 166 # . . push args -167 68/push Newline/imm32 +167 68/push "cd/syscall 0x80/imm8\n"/imm32 168 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) 169 # . . call 170 e8/call write/disp32 171 # . . discard args 172 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -173 # . write(out, "cd/syscall 0x80/imm8") -174 # . . push args -175 68/push "cd/syscall 0x80/imm8"/imm32 -176 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -177 # . . call -178 e8/call write/disp32 -179 # . . discard args -180 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -181 # . write(out, Newline) -182 # . . push args -183 68/push Newline/imm32 -184 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -185 # . . call -186 e8/call write/disp32 -187 # . . discard args -188 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -189 $compile:end: -190 # . restore registers -191 59/pop-to-ECX -192 58/pop-to-EAX -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 # Read a single digit into 'out'. Abort if there are none, or if there is no space in 'out'. -199 # Input comes from the global variable 'Look', and we leave the next byte from -200 # 'in' into it on exit. -201 get-num: # in : (address buffered-file), out : (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void> -202 # pseudocode: -203 # if (!is-digit?(Look)) expected(ed, err, "integer") -204 # if out->write >= out->length -205 # write(err, "Error: too many digits in number\n") -206 # stop(ed, 1) -207 # out->data[out->write] = LSB(Look) -208 # ++out->write -209 # Look = get-char(in) -210 # -211 # registers: -212 # in: ESI -213 # out: EDI -214 # out->write: ECX (cached copy; need to keep in sync) -215 # out->length: EDX -216 # temporaries: EAX, EBX -217 # We can't allocate Look to a register because it gets written implicitly in -218 # get-char in each iteration of the loop. (Thereby demonstrating that it's -219 # not the right interface for us. But we'll keep it just to follow Crenshaw.) -220 # -221 # . prolog -222 55/push-EBP -223 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -224 # - if (is-digit?(Look)) expected(ed, err, "integer") -225 # . EAX = is-digit?(Look) -226 # . . push args -227 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look -228 # . . call -229 e8/call is-digit?/disp32 -230 # . . discard args -231 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -232 # . if (EAX == 0) -233 3d/compare-EAX-and 0/imm32 -234 75/jump-if-not-equal $get-num:main/disp8 -235 # . expected(ed, err, "integer") -236 # . . push args -237 68/push "integer"/imm32 -238 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) -239 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x14/disp8 . # push *(EBP+20) -240 # . . call -241 e8/call expected/disp32 # never returns -242 # . . discard args -243 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -244 $get-num:main: -245 # - otherwise read a digit -246 # . save registers -247 50/push-EAX -248 51/push-ECX -249 52/push-EDX -250 53/push-EBX -251 56/push-ESI -252 57/push-EDI -253 # read necessary variables to registers -254 # ESI = in -255 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI -256 # EDI = out -257 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI -258 # ECX = out->write -259 8b/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy *EDI to ECX -260 # EDX = out->length -261 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 8/disp8 . # copy *(EDI+8) to EDX -262 # if (out->write >= out->length) error -263 39/compare 3/mod/direct 2/rm32/EDX . . . 1/r32/ECX . . # compare EDX with ECX -264 7d/jump-if-lesser $get-num:stage2/disp8 -265 # . error(ed, err, msg) # TODO: show full number +173 $compile:end: +174 # . restore registers +175 59/pop-to-ECX +176 58/pop-to-EAX +177 # . epilog +178 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +179 5d/pop-to-EBP +180 c3/return +181 +182 # Read a single digit into 'out'. Abort if there are none, or if there is no space in 'out'. +183 # Input comes from the global variable 'Look', and we leave the next byte from +184 # 'in' into it on exit. +185 get-num: # in : (address buffered-file), out : (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void> +186 # pseudocode: +187 # if (!is-digit?(Look)) expected(ed, err, "integer") +188 # if out->write >= out->length +189 # write(err, "Error: too many digits in number\n") +190 # stop(ed, 1) +191 # out->data[out->write] = LSB(Look) +192 # ++out->write +193 # Look = get-char(in) +194 # +195 # registers: +196 # in: ESI +197 # out: EDI +198 # out->write: ECX (cached copy; need to keep in sync) +199 # out->length: EDX +200 # temporaries: EAX, EBX +201 # We can't allocate Look to a register because it gets written implicitly in +202 # get-char in each iteration of the loop. (Thereby demonstrating that it's +203 # not the right interface for us. But we'll keep it just to follow Crenshaw.) +204 # +205 # . prolog +206 55/push-EBP +207 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +208 # - if (is-digit?(Look)) expected(ed, err, "integer") +209 # . EAX = is-digit?(Look) +210 # . . push args +211 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look +212 # . . call +213 e8/call is-digit?/disp32 +214 # . . discard args +215 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +216 # . if (EAX == 0) +217 3d/compare-EAX-and 0/imm32 +218 75/jump-if-not-equal $get-num:main/disp8 +219 # . expected(ed, err, "integer") +220 # . . push args +221 68/push "integer"/imm32 +222 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) +223 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x14/disp8 . # push *(EBP+20) +224 # . . call +225 e8/call expected/disp32 # never returns +226 # . . discard args +227 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +228 $get-num:main: +229 # - otherwise read a digit +230 # . save registers +231 50/push-EAX +232 51/push-ECX +233 52/push-EDX +234 53/push-EBX +235 56/push-ESI +236 57/push-EDI +237 # read necessary variables to registers +238 # ESI = in +239 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +240 # EDI = out +241 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI +242 # ECX = out->write +243 8b/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy *EDI to ECX +244 # EDX = out->length +245 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 8/disp8 . # copy *(EDI+8) to EDX +246 # if (out->write >= out->length) error +247 39/compare 3/mod/direct 2/rm32/EDX . . . 1/r32/ECX . . # compare EDX with ECX +248 7d/jump-if-lesser $get-num:stage2/disp8 +249 # . error(ed, err, msg) # TODO: show full number +250 # . . push args +251 68/push "get-num: too many digits in number"/imm32 +252 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) +253 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x14/disp8 . # push *(EBP+20) +254 # . . call +255 e8/call error/disp32 # never returns +256 # . . discard args +257 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +258 $get-num:stage2: +259 # out->data[out->write] = LSB(Look) +260 8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 3/r32/EBX 0xc/disp8 . # copy EDI+ECX+12 to EBX +261 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Look/disp32 . # copy *Look to EAX +262 88/copy-byte 0/mod/indirect 3/rm32/EBX . . . 0/r32/AL . . # copy byte at AL to *EBX +263 # ++out->write +264 41/increment-ECX +265 # Look = get-char(in) 266 # . . push args -267 68/push "get-num: too many digits in number"/imm32 -268 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) -269 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x14/disp8 . # push *(EBP+20) -270 # . . call -271 e8/call error/disp32 # never returns -272 # . . discard args -273 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -274 $get-num:stage2: -275 # out->data[out->write] = LSB(Look) -276 8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 3/r32/EBX 0xc/disp8 . # copy EDI+ECX+12 to EBX -277 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Look/disp32 . # copy *Look to EAX -278 88/copy-byte 0/mod/indirect 3/rm32/EBX . . . 0/r32/AL . . # copy byte at AL to *EBX -279 # ++out->write -280 41/increment-ECX -281 # Look = get-char(in) -282 # . . push args -283 56/push-ESI -284 # . . call -285 e8/call get-char/disp32 -286 # . . discard args -287 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -288 $get-num:loop-end: -289 # persist necessary variables from registers -290 89/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy ECX to *EDI -291 $get-num:end: -292 # . restore registers -293 5f/pop-to-EDI -294 5e/pop-to-ESI -295 5b/pop-to-EBX -296 5a/pop-to-EDX -297 59/pop-to-ECX -298 58/pop-to-EAX -299 # . epilog -300 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -301 5d/pop-to-EBP -302 c3/return -303 -304 test-get-num-reads-single-digit: -305 # - check that get-num returns first character if it's a digit -306 # This test uses exit-descriptors. Use EBP for setting up local variables. -307 55/push-EBP -308 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -309 # clear all streams -310 # . clear-stream(_test-stream) +267 56/push-ESI +268 # . . call +269 e8/call get-char/disp32 +270 # . . discard args +271 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +272 $get-num:loop-end: +273 # persist necessary variables from registers +274 89/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy ECX to *EDI +275 $get-num:end: +276 # . restore registers +277 5f/pop-to-EDI +278 5e/pop-to-ESI +279 5b/pop-to-EBX +280 5a/pop-to-EDX +281 59/pop-to-ECX +282 58/pop-to-EAX +283 # . epilog +284 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +285 5d/pop-to-EBP +286 c3/return +287 +288 test-get-num-reads-single-digit: +289 # - check that get-num returns first character if it's a digit +290 # This test uses exit-descriptors. Use EBP for setting up local variables. +291 55/push-EBP +292 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +293 # clear all streams +294 # . clear-stream(_test-stream) +295 # . . push args +296 68/push _test-stream/imm32 +297 # . . call +298 e8/call clear-stream/disp32 +299 # . . discard args +300 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +301 # . clear-stream(_test-buffered-file+4) +302 # . . push args +303 b8/copy-to-EAX _test-buffered-file/imm32 +304 05/add-to-EAX 4/imm32 +305 50/push-EAX +306 # . . call +307 e8/call clear-stream/disp32 +308 # . . discard args +309 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +310 # . clear-stream(_test-output-stream) 311 # . . push args -312 68/push _test-stream/imm32 +312 68/push _test-output-stream/imm32 313 # . . call 314 e8/call clear-stream/disp32 315 # . . discard args 316 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -317 # . clear-stream(_test-buffered-file+4) +317 # . clear-stream(_test-error-stream) 318 # . . push args -319 b8/copy-to-EAX _test-buffered-file/imm32 -320 05/add-to-EAX 4/imm32 -321 50/push-EAX -322 # . . call -323 e8/call clear-stream/disp32 -324 # . . discard args -325 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -326 # . clear-stream(_test-output-stream) -327 # . . push args -328 68/push _test-output-stream/imm32 +319 68/push _test-error-stream/imm32 +320 # . . call +321 e8/call clear-stream/disp32 +322 # . . discard args +323 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +324 # initialize 'in' +325 # . write(_test-stream, "3") +326 # . . push args +327 68/push "3"/imm32 +328 68/push _test-stream/imm32 329 # . . call -330 e8/call clear-stream/disp32 +330 e8/call write/disp32 331 # . . discard args -332 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -333 # . clear-stream(_test-error-stream) -334 # . . push args -335 68/push _test-error-stream/imm32 -336 # . . call -337 e8/call clear-stream/disp32 -338 # . . discard args -339 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -340 # initialize 'in' -341 # . write(_test-stream, "3") -342 # . . push args -343 68/push "3"/imm32 -344 68/push _test-stream/imm32 -345 # . . call -346 e8/call write/disp32 -347 # . . discard args -348 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -349 # initialize exit-descriptor 'ed' for the call to 'get-num' below -350 # . var ed/EAX : exit-descriptor -351 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP -352 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX -353 # . tailor-exit-descriptor(ed, 16) +332 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +333 # initialize exit-descriptor 'ed' for the call to 'get-num' below +334 # . var ed/EAX : exit-descriptor +335 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +336 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX +337 # . tailor-exit-descriptor(ed, 16) +338 # . . push args +339 68/push 0x10/imm32/nbytes-of-args-for-get-num +340 50/push-EAX/ed +341 # . . call +342 e8/call tailor-exit-descriptor/disp32 +343 # . . discard args +344 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +345 # prime the pump +346 # . get-char(_test-buffered-file) +347 # . . push args +348 68/push _test-buffered-file/imm32 +349 # . . call +350 e8/call get-char/disp32 +351 # . . discard args +352 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +353 # get-num(in, out, err, ed) 354 # . . push args -355 68/push 0x10/imm32/nbytes-of-args-for-get-num -356 50/push-EAX/ed -357 # . . call -358 e8/call tailor-exit-descriptor/disp32 -359 # . . discard args -360 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -361 # prime the pump -362 # . get-char(_test-buffered-file) -363 # . . push args -364 68/push _test-buffered-file/imm32 -365 # . . call -366 e8/call get-char/disp32 -367 # . . discard args -368 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -369 # get-num(in, out, err, ed) -370 # . . push args -371 50/push-EAX/ed -372 68/push _test-error-stream/imm32 -373 68/push _test-output-stream/imm32 -374 68/push _test-buffered-file/imm32 -375 # . . call -376 e8/call get-num/disp32 -377 # registers except ESP may be clobbered at this point -378 # . . discard args -379 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -380 # check-ints-equal(*_test-output-stream->data, '3', msg) -381 # . . push args -382 68/push "F - test-get-num-reads-single-digit"/imm32 -383 68/push 0x33/imm32 -384 b8/copy-to-EAX _test-output-stream/imm32 -385 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) -386 # . . call -387 e8/call check-ints-equal/disp32 -388 # . . discard args -389 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -390 # . 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-get-num-aborts-on-non-digit-in-Look: -396 # - check that get-num returns first character if it's a digit -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) +355 50/push-EAX/ed +356 68/push _test-error-stream/imm32 +357 68/push _test-output-stream/imm32 +358 68/push _test-buffered-file/imm32 +359 # . . call +360 e8/call get-num/disp32 +361 # registers except ESP may be clobbered at this point +362 # . . discard args +363 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +364 # check-ints-equal(*_test-output-stream->data, '3', msg) +365 # . . push args +366 68/push "F - test-get-num-reads-single-digit"/imm32 +367 68/push 0x33/imm32 +368 b8/copy-to-EAX _test-output-stream/imm32 +369 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) +370 # . . call +371 e8/call check-ints-equal/disp32 +372 # . . discard args +373 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +374 # . reclaim locals +375 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +376 5d/pop-to-EBP +377 c3/return +378 +379 test-get-num-aborts-on-non-digit-in-Look: +380 # - check that get-num returns first character if it's a digit +381 # This test uses exit-descriptors. Use EBP for setting up local variables. +382 55/push-EBP +383 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +384 # clear all streams +385 # . clear-stream(_test-stream) +386 # . . push args +387 68/push _test-stream/imm32 +388 # . . call +389 e8/call clear-stream/disp32 +390 # . . discard args +391 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +392 # . clear-stream(_test-buffered-file+4) +393 # . . push args +394 b8/copy-to-EAX _test-buffered-file/imm32 +395 05/add-to-EAX 4/imm32 +396 50/push-EAX +397 # . . call +398 e8/call clear-stream/disp32 +399 # . . discard args +400 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +401 # . clear-stream(_test-output-stream) 402 # . . push args -403 68/push _test-stream/imm32 +403 68/push _test-output-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) +408 # . clear-stream(_test-error-stream) 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-output-stream) -418 # . . push args -419 68/push _test-output-stream/imm32 +410 68/push _test-error-stream/imm32 +411 # . . call +412 e8/call clear-stream/disp32 +413 # . . discard args +414 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +415 # initialize 'in' +416 # . write(_test-stream, "3") +417 # . . push args +418 68/push "3"/imm32 +419 68/push _test-stream/imm32 420 # . . call -421 e8/call clear-stream/disp32 +421 e8/call write/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-stream) -425 # . . push args -426 68/push _test-error-stream/imm32 -427 # . . call -428 e8/call clear-stream/disp32 -429 # . . discard args -430 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -431 # initialize 'in' -432 # . write(_test-stream, "3") -433 # . . push args -434 68/push "3"/imm32 -435 68/push _test-stream/imm32 -436 # . . call -437 e8/call write/disp32 -438 # . . discard args -439 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -440 # initialize exit-descriptor 'ed' for the call to 'get-num' below -441 # . var ed/EAX : (address exit-descriptor) -442 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP -443 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX -444 # . tailor-exit-descriptor(ed, 16) -445 # . . push args -446 68/push 0x10/imm32/nbytes-of-args-for-get-num -447 50/push-EAX/ed -448 # . . call -449 e8/call tailor-exit-descriptor/disp32 -450 # . . discard args -451 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -452 # *don't* prime the pump -453 # get-num(in, out, err, ed) -454 # . . push args -455 50/push-EAX/ed -456 68/push _test-error-stream/imm32 -457 68/push _test-output-stream/imm32 -458 68/push _test-buffered-file/imm32 -459 # . . call -460 e8/call get-num/disp32 -461 # registers except ESP may be clobbered at this point -462 # . . discard args -463 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -464 # check that get-num tried to call exit(1) -465 # . check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1 -466 # . . push args -467 68/push "F - test-get-num-aborts-on-non-digit-in-Look"/imm32 -468 68/push 2/imm32 -469 # . . push ed->value -470 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) -471 # . . call -472 e8/call check-ints-equal/disp32 -473 # . . discard args -474 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -475 # . reclaim locals -476 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -477 5d/pop-to-EBP -478 c3/return -479 -480 ## helpers -481 -482 # write(f, "Error: "+s+" expected\n") then stop(ed, 1) -483 expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void> -484 # . prolog -485 55/push-EBP -486 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -487 # write(f, "Error: ") +423 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +424 # initialize exit-descriptor 'ed' for the call to 'get-num' below +425 # . var ed/EAX : (address exit-descriptor) +426 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +427 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX +428 # . tailor-exit-descriptor(ed, 16) +429 # . . push args +430 68/push 0x10/imm32/nbytes-of-args-for-get-num +431 50/push-EAX/ed +432 # . . call +433 e8/call tailor-exit-descriptor/disp32 +434 # . . discard args +435 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +436 # *don't* prime the pump +437 # get-num(in, out, err, ed) +438 # . . push args +439 50/push-EAX/ed +440 68/push _test-error-stream/imm32 +441 68/push _test-output-stream/imm32 +442 68/push _test-buffered-file/imm32 +443 # . . call +444 e8/call get-num/disp32 +445 # registers except ESP may be clobbered at this point +446 # . . discard args +447 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +448 # check that get-num tried to call exit(1) +449 # . check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1 +450 # . . push args +451 68/push "F - test-get-num-aborts-on-non-digit-in-Look"/imm32 +452 68/push 2/imm32 +453 # . . push ed->value +454 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +455 # . . call +456 e8/call check-ints-equal/disp32 +457 # . . discard args +458 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +459 # . reclaim locals +460 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +461 5d/pop-to-EBP +462 c3/return +463 +464 ## helpers +465 +466 # write(f, "Error: "+s+" expected\n") then stop(ed, 1) +467 expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void> +468 # . prolog +469 55/push-EBP +470 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +471 # write(f, "Error: ") +472 # . . push args +473 68/push "Error: "/imm32 +474 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +475 # . . call +476 e8/call write/disp32 +477 # . . discard args +478 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +479 # write(f, s) +480 # . . push args +481 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) +482 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +483 # . . call +484 e8/call write/disp32 +485 # . . discard args +486 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +487 # write(f, " expected") 488 # . . push args -489 68/push "Error: "/imm32 +489 68/push " expected\n"/imm32 490 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) 491 # . . call 492 e8/call write/disp32 493 # . . discard args 494 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -495 # write(f, s) +495 # stop(ed, 1) 496 # . . push args -497 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) -498 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +497 68/push 1/imm32 +498 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) 499 # . . call -500 e8/call write/disp32 -501 # . . discard args -502 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -503 # write(f, " expected") -504 # . . push args -505 68/push " expected"/imm32 -506 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -507 # . . call -508 e8/call write/disp32 -509 # . . discard args -510 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -511 # write(f, Newline) -512 # . . push args -513 68/push Newline/imm32 -514 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -515 # . . call -516 e8/call write/disp32 -517 # . . discard args -518 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -519 # stop(ed, 1) -520 # . . push args -521 68/push 1/imm32 -522 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -523 # . . call -524 e8/call stop/disp32 -525 # should never get past this point -526 $expected:dead-end: +500 e8/call stop/disp32 +501 # should never get past this point +502 $expected:dead-end: +503 # . epilog +504 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +505 5d/pop-to-EBP +506 c3/return +507 +508 # read a byte from 'f', and save it in 'Look' +509 get-char: # f : (address buffered-file) -> <void> +510 # . prolog +511 55/push-EBP +512 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +513 # . save registers +514 50/push-EAX +515 # read-byte(f) +516 # . . push args +517 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +518 # . . call +519 e8/call read-byte/disp32 +520 # . . discard args +521 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +522 # save EAX to Look +523 89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Look/disp32 . # copy EAX to *Look +524 $get-char:end: +525 # . restore registers +526 58/pop-to-EAX 527 # . epilog 528 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 529 5d/pop-to-EBP 530 c3/return 531 -532 # read a byte from 'f', and save it in 'Look' -533 get-char: # f : (address buffered-file) -> <void> -534 # . prolog -535 55/push-EBP -536 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -537 # . save registers -538 50/push-EAX -539 # read-byte(f) -540 # . . push args -541 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -542 # . . call -543 e8/call read-byte/disp32 -544 # . . discard args -545 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -546 # save EAX to Look -547 89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Look/disp32 . # copy EAX to *Look -548 $get-char:end: -549 # . restore registers -550 58/pop-to-EAX -551 # . epilog -552 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -553 5d/pop-to-EBP -554 c3/return -555 -556 is-digit?: # c : int -> EAX : boolean -557 # . prolog -558 55/push-EBP -559 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -560 # EAX = false -561 b8/copy-to-EAX 0/imm32 -562 # if (c < '0') return false -563 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x30/imm32 # compare *(EBP+8) -564 7c/jump-if-lesser $is-digit?:end/disp8 -565 # if (c > '9') return false -566 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x39/imm32 # compare *(EBP+8) -567 7f/jump-if-greater $is-digit?:end/disp8 -568 # otherwise return true -569 b8/copy-to-EAX 1/imm32 -570 $is-digit?:end: -571 # . epilog -572 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -573 5d/pop-to-EBP -574 c3/return -575 -576 == data -577 -578 Look: # (char with some extra padding) -579 0/imm32 -580 -581 _test-output-stream: -582 # current write index -583 0/imm32 -584 # current read index -585 0/imm32 -586 # length -587 8/imm32 -588 # data -589 00 00 00 00 00 00 00 00 # 8 bytes -590 -591 _test-error-stream: -592 # current write index -593 0/imm32 -594 # current read index -595 0/imm32 -596 # length -597 0x40/imm32 -598 # data (4 lines x 16 bytes/line) -599 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -600 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -601 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -602 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -603 -604 # . . vim:nowrap:textwidth=0 +532 is-digit?: # c : int -> EAX : boolean +533 # . prolog +534 55/push-EBP +535 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +536 # EAX = false +537 b8/copy-to-EAX 0/imm32 +538 # if (c < '0') return false +539 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x30/imm32 # compare *(EBP+8) +540 7c/jump-if-lesser $is-digit?:end/disp8 +541 # if (c > '9') return false +542 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x39/imm32 # compare *(EBP+8) +543 7f/jump-if-greater $is-digit?:end/disp8 +544 # otherwise return true +545 b8/copy-to-EAX 1/imm32 +546 $is-digit?:end: +547 # . epilog +548 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +549 5d/pop-to-EBP +550 c3/return +551 +552 == data +553 +554 Look: # (char with some extra padding) +555 0/imm32 +556 +557 _test-output-stream: +558 # current write index +559 0/imm32 +560 # current read index +561 0/imm32 +562 # length +563 8/imm32 +564 # data +565 00 00 00 00 00 00 00 00 # 8 bytes +566 +567 _test-error-stream: +568 # current write index +569 0/imm32 +570 # current read index +571 0/imm32 +572 # length +573 0x40/imm32 +574 # data (4 lines x 16 bytes/line) +575 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +576 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +577 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +578 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +579 +580 # . . vim:nowrap:textwidth=0 diff --git a/html/subx/apps/crenshaw2-1b.subx.html b/html/subx/apps/crenshaw2-1b.subx.html index 131da73c..9e027b58 100644 --- a/html/subx/apps/crenshaw2-1b.subx.html +++ b/html/subx/apps/crenshaw2-1b.subx.html @@ -157,7 +157,7 @@ if ('onhashchange' in window) { 94 # . . push args 95 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) 96 # . . call - 97 e8/call get-char/disp32 + 97 e8/call get-char/disp32 98 # . . discard args 99 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP 100 # var num/ECX : (address stream) on the stack @@ -185,7 +185,7 @@ if ('onhashchange' in window) { 122 51/push-ECX/num 123 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) 124 # . . call -125 e8/call get-num/disp32 +125 e8/call get-num/disp32 126 # . . discard args 127 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP 128 # render 'num' into the following template on 'out': @@ -217,653 +217,629 @@ if ('onhashchange' in window) { 154 e8/call write/disp32 155 # . . discard args 156 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -157 # . write(out, "b8/copy-to-EAX 1/imm32/exit") +157 # . write(out, "b8/copy-to-EAX 1/imm32/exit\n") 158 # . . push args -159 68/push "b8/copy-to-EAX 1/imm32/exit"/imm32 +159 68/push "b8/copy-to-EAX 1/imm32/exit\n"/imm32 160 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) 161 # . . call 162 e8/call write/disp32 163 # . . discard args 164 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -165 # . write(out, Newline) +165 # . write(out, "cd/syscall 0x80/imm8\n") 166 # . . push args -167 68/push Newline/imm32 +167 68/push "cd/syscall 0x80/imm8\n"/imm32 168 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) 169 # . . call 170 e8/call write/disp32 171 # . . discard args 172 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -173 # . write(out, "cd/syscall 0x80/imm8") -174 # . . push args -175 68/push "cd/syscall 0x80/imm8"/imm32 -176 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -177 # . . call -178 e8/call write/disp32 -179 # . . discard args -180 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -181 # . write(out, Newline) -182 # . . push args -183 68/push Newline/imm32 -184 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -185 # . . call -186 e8/call write/disp32 -187 # . . discard args -188 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -189 $compile:end: -190 # . restore registers -191 59/pop-to-ECX -192 58/pop-to-EAX -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 # Read a sequence of digits into 'out'. Abort if there are none, or if there is -199 # no space in 'out'. -200 # Input comes from the global variable 'Look' (first byte) and the argument -201 # 'in' (rest). We leave the next byte from 'in' into 'Look' on exit. -202 get-num: # in : (address buffered-file), out : (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void> -203 # pseudocode: -204 # if (!is-digit?(Look)) expected(ed, err, "integer") -205 # do -206 # if out->write >= out->length -207 # write(err, "Error: too many digits in number\n") -208 # stop(ed, 1) -209 # out->data[out->write] = LSB(Look) -210 # ++out->write -211 # Look = get-char(in) -212 # while is-digit?(Look) -213 # This is complicated because I don't want to hard-code the error strategy in -214 # a general helper like write-byte. Maybe I should just create a local helper. -215 # -216 # within the loop we'll try to keep things in registers: -217 # in: ESI -218 # out: EDI -219 # out->write: ECX (cached copy; need to keep in sync) -220 # out->length: EDX -221 # temporaries: EAX, EBX -222 # We can't allocate Look to a register because it gets written implicitly in -223 # get-char in each iteration of the loop. (Thereby demonstrating that it's -224 # not the right interface for us. But we'll keep it just to follow Crenshaw.) -225 # -226 # . prolog -227 55/push-EBP -228 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -229 # - if (is-digit?(Look)) expected(ed, err, "integer") -230 # . EAX = is-digit?(Look) -231 # . . push args -232 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look -233 # . . call -234 e8/call is-digit?/disp32 -235 # . . discard args -236 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -237 # . if (EAX == 0) -238 3d/compare-EAX-and 0/imm32 -239 75/jump-if-not-equal $get-num:main/disp8 -240 # . expected(ed, err, "integer") -241 # . . push args -242 68/push "integer"/imm32 -243 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) -244 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x14/disp8 . # push *(EBP+20) -245 # . . call -246 e8/call expected/disp32 # never returns -247 # . . discard args -248 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -249 $get-num:main: -250 # - otherwise read a digit -251 # . save registers -252 50/push-EAX -253 51/push-ECX -254 52/push-EDX -255 53/push-EBX -256 56/push-ESI -257 57/push-EDI -258 # read necessary variables to registers -259 # ESI = in -260 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI -261 # EDI = out -262 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI -263 # ECX = out->write -264 8b/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy *EDI to ECX -265 # EDX = out->length -266 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 8/disp8 . # copy *(EDI+8) to EDX -267 $get-num:loop: -268 # if (out->write >= out->length) error -269 39/compare 3/mod/direct 2/rm32/EDX . . . 1/r32/ECX . . # compare EDX with ECX -270 7d/jump-if-lesser $get-num:loop-stage2/disp8 -271 # . error(ed, err, msg) # TODO: show full number +173 $compile:end: +174 # . restore registers +175 59/pop-to-ECX +176 58/pop-to-EAX +177 # . epilog +178 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +179 5d/pop-to-EBP +180 c3/return +181 +182 # Read a sequence of digits into 'out'. Abort if there are none, or if there is +183 # no space in 'out'. +184 # Input comes from the global variable 'Look' (first byte) and the argument +185 # 'in' (rest). We leave the next byte from 'in' into 'Look' on exit. +186 get-num: # in : (address buffered-file), out : (address stream), err : fd or (address stream), ed : (address exit-descriptor) -> <void> +187 # pseudocode: +188 # if (!is-digit?(Look)) expected(ed, err, "integer") +189 # do +190 # if out->write >= out->length +191 # write(err, "Error: too many digits in number\n") +192 # stop(ed, 1) +193 # out->data[out->write] = LSB(Look) +194 # ++out->write +195 # Look = get-char(in) +196 # while is-digit?(Look) +197 # This is complicated because I don't want to hard-code the error strategy in +198 # a general helper like write-byte. Maybe I should just create a local helper. +199 # +200 # within the loop we'll try to keep things in registers: +201 # in: ESI +202 # out: EDI +203 # out->write: ECX (cached copy; need to keep in sync) +204 # out->length: EDX +205 # temporaries: EAX, EBX +206 # We can't allocate Look to a register because it gets written implicitly in +207 # get-char in each iteration of the loop. (Thereby demonstrating that it's +208 # not the right interface for us. But we'll keep it just to follow Crenshaw.) +209 # +210 # . prolog +211 55/push-EBP +212 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +213 # - if (is-digit?(Look)) expected(ed, err, "integer") +214 # . EAX = is-digit?(Look) +215 # . . push args +216 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look +217 # . . call +218 e8/call is-digit?/disp32 +219 # . . discard args +220 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +221 # . if (EAX == 0) +222 3d/compare-EAX-and 0/imm32 +223 75/jump-if-not-equal $get-num:main/disp8 +224 # . expected(ed, err, "integer") +225 # . . push args +226 68/push "integer"/imm32 +227 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) +228 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x14/disp8 . # push *(EBP+20) +229 # . . call +230 e8/call expected/disp32 # never returns +231 # . . discard args +232 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +233 $get-num:main: +234 # - otherwise read a digit +235 # . save registers +236 50/push-EAX +237 51/push-ECX +238 52/push-EDX +239 53/push-EBX +240 56/push-ESI +241 57/push-EDI +242 # read necessary variables to registers +243 # ESI = in +244 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +245 # EDI = out +246 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI +247 # ECX = out->write +248 8b/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy *EDI to ECX +249 # EDX = out->length +250 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 8/disp8 . # copy *(EDI+8) to EDX +251 $get-num:loop: +252 # if (out->write >= out->length) error +253 39/compare 3/mod/direct 2/rm32/EDX . . . 1/r32/ECX . . # compare EDX with ECX +254 7d/jump-if-lesser $get-num:loop-stage2/disp8 +255 # . error(ed, err, msg) # TODO: show full number +256 # . . push args +257 68/push "get-num: too many digits in number"/imm32 +258 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) +259 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x14/disp8 . # push *(EBP+20) +260 # . . call +261 e8/call error/disp32 # never returns +262 # . . discard args +263 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +264 $get-num:loop-stage2: +265 # out->data[out->write] = LSB(Look) +266 8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 3/r32/EBX 0xc/disp8 . # copy EDI+ECX+12 to EBX +267 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Look/disp32 . # copy *Look to EAX +268 88/copy-byte 0/mod/indirect 3/rm32/EBX . . . 0/r32/AL . . # copy byte at AL to *EBX +269 # ++out->write +270 41/increment-ECX +271 # Look = get-char(in) 272 # . . push args -273 68/push "get-num: too many digits in number"/imm32 -274 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) -275 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x14/disp8 . # push *(EBP+20) -276 # . . call -277 e8/call error/disp32 # never returns -278 # . . discard args -279 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -280 $get-num:loop-stage2: -281 # out->data[out->write] = LSB(Look) -282 8d/copy-address 1/mod/*+disp8 4/rm32/sib 7/base/EDI 1/index/ECX . 3/r32/EBX 0xc/disp8 . # copy EDI+ECX+12 to EBX -283 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Look/disp32 . # copy *Look to EAX -284 88/copy-byte 0/mod/indirect 3/rm32/EBX . . . 0/r32/AL . . # copy byte at AL to *EBX -285 # ++out->write -286 41/increment-ECX -287 # Look = get-char(in) -288 # . . push args -289 56/push-ESI -290 # . . call -291 e8/call get-char/disp32 -292 # . . discard args -293 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -294 # if (is-digit?(Look)) loop -295 # . EAX = is-digit?(Look) -296 # . . push args -297 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look -298 # . . call -299 e8/call is-digit?/disp32 -300 # . . discard args -301 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -302 # . if (EAX != 0) loop -303 3d/compare-EAX-and 0/imm32 -304 0f 85/jump-if-not-equal $get-num:loop/disp32 -305 $get-num:loop-end: -306 # persist necessary variables from registers -307 89/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy ECX to *EDI -308 $get-num:end: -309 # . restore registers -310 5f/pop-to-EDI -311 5e/pop-to-ESI -312 5b/pop-to-EBX -313 5a/pop-to-EDX -314 59/pop-to-ECX -315 58/pop-to-EAX -316 # . epilog -317 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -318 5d/pop-to-EBP -319 c3/return -320 -321 test-get-num-reads-single-digit: -322 # - check that get-num returns first character if it's a digit -323 # This test uses exit-descriptors. Use EBP for setting up local variables. -324 55/push-EBP -325 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -326 # clear all streams -327 # . clear-stream(_test-stream) +273 56/push-ESI +274 # . . call +275 e8/call get-char/disp32 +276 # . . discard args +277 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +278 # if (is-digit?(Look)) loop +279 # . EAX = is-digit?(Look) +280 # . . push args +281 ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Look/disp32 . # push *Look +282 # . . call +283 e8/call is-digit?/disp32 +284 # . . discard args +285 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +286 # . if (EAX != 0) loop +287 3d/compare-EAX-and 0/imm32 +288 0f 85/jump-if-not-equal $get-num:loop/disp32 +289 $get-num:loop-end: +290 # persist necessary variables from registers +291 89/copy 0/mod/indirect 7/rm32/EDI . . . 1/r32/ECX . . # copy ECX to *EDI +292 $get-num:end: +293 # . restore registers +294 5f/pop-to-EDI +295 5e/pop-to-ESI +296 5b/pop-to-EBX +297 5a/pop-to-EDX +298 59/pop-to-ECX +299 58/pop-to-EAX +300 # . epilog +301 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +302 5d/pop-to-EBP +303 c3/return +304 +305 test-get-num-reads-single-digit: +306 # - check that get-num returns first character if it's a digit +307 # This test uses exit-descriptors. Use EBP for setting up local variables. +308 55/push-EBP +309 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +310 # clear all streams +311 # . clear-stream(_test-stream) +312 # . . push args +313 68/push _test-stream/imm32 +314 # . . call +315 e8/call clear-stream/disp32 +316 # . . discard args +317 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +318 # . clear-stream(_test-buffered-file+4) +319 # . . push args +320 b8/copy-to-EAX _test-buffered-file/imm32 +321 05/add-to-EAX 4/imm32 +322 50/push-EAX +323 # . . call +324 e8/call clear-stream/disp32 +325 # . . discard args +326 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +327 # . clear-stream(_test-output-stream) 328 # . . push args -329 68/push _test-stream/imm32 +329 68/push _test-output-stream/imm32 330 # . . call 331 e8/call clear-stream/disp32 332 # . . discard args 333 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -334 # . clear-stream(_test-buffered-file+4) +334 # . clear-stream(_test-error-stream) 335 # . . push args -336 b8/copy-to-EAX _test-buffered-file/imm32 -337 05/add-to-EAX 4/imm32 -338 50/push-EAX -339 # . . call -340 e8/call clear-stream/disp32 -341 # . . discard args -342 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -343 # . clear-stream(_test-output-stream) -344 # . . push args -345 68/push _test-output-stream/imm32 +336 68/push _test-error-stream/imm32 +337 # . . call +338 e8/call clear-stream/disp32 +339 # . . discard args +340 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +341 # initialize 'in' +342 # . write(_test-stream, "3") +343 # . . push args +344 68/push "3"/imm32 +345 68/push _test-stream/imm32 346 # . . call -347 e8/call clear-stream/disp32 +347 e8/call write/disp32 348 # . . discard args -349 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -350 # . clear-stream(_test-error-stream) -351 # . . push args -352 68/push _test-error-stream/imm32 -353 # . . call -354 e8/call clear-stream/disp32 -355 # . . discard args -356 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -357 # initialize 'in' -358 # . write(_test-stream, "3") -359 # . . push args -360 68/push "3"/imm32 -361 68/push _test-stream/imm32 -362 # . . call -363 e8/call write/disp32 -364 # . . discard args -365 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -366 # initialize exit-descriptor 'ed' for the call to 'get-num' below -367 # . var ed/EAX : exit-descriptor -368 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP -369 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX -370 # . tailor-exit-descriptor(ed, 16) +349 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +350 # initialize exit-descriptor 'ed' for the call to 'get-num' below +351 # . var ed/EAX : exit-descriptor +352 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +353 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX +354 # . tailor-exit-descriptor(ed, 16) +355 # . . push args +356 68/push 0x10/imm32/nbytes-of-args-for-get-num +357 50/push-EAX/ed +358 # . . call +359 e8/call tailor-exit-descriptor/disp32 +360 # . . discard args +361 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +362 # prime the pump +363 # . get-char(_test-buffered-file) +364 # . . push args +365 68/push _test-buffered-file/imm32 +366 # . . call +367 e8/call get-char/disp32 +368 # . . discard args +369 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +370 # get-num(in, out, err, ed) 371 # . . push args -372 68/push 0x10/imm32/nbytes-of-args-for-get-num -373 50/push-EAX/ed -374 # . . call -375 e8/call tailor-exit-descriptor/disp32 -376 # . . discard args -377 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -378 # prime the pump -379 # . get-char(_test-buffered-file) -380 # . . push args -381 68/push _test-buffered-file/imm32 -382 # . . call -383 e8/call get-char/disp32 -384 # . . discard args -385 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -386 # get-num(in, out, err, ed) -387 # . . push args -388 50/push-EAX/ed -389 68/push _test-error-stream/imm32 -390 68/push _test-output-stream/imm32 -391 68/push _test-buffered-file/imm32 -392 # . . call -393 e8/call get-num/disp32 -394 # registers except ESP may be clobbered at this point -395 # . . discard args -396 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -397 # check-ints-equal(*_test-output-stream->data, '3', msg) -398 # . . push args -399 68/push "F - test-get-num-reads-single-digit"/imm32 -400 68/push 0x33/imm32 -401 b8/copy-to-EAX _test-output-stream/imm32 -402 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) -403 # . . call -404 e8/call check-ints-equal/disp32 -405 # . . discard args -406 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -407 # . reclaim locals -408 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -409 5d/pop-to-EBP -410 c3/return -411 -412 test-get-num-aborts-on-non-digit-in-Look: -413 # - check that get-num returns first character if it's a digit -414 # This test uses exit-descriptors. Use EBP for setting up local variables. -415 55/push-EBP -416 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -417 # clear all streams -418 # . clear-stream(_test-stream) +372 50/push-EAX/ed +373 68/push _test-error-stream/imm32 +374 68/push _test-output-stream/imm32 +375 68/push _test-buffered-file/imm32 +376 # . . call +377 e8/call get-num/disp32 +378 # registers except ESP may be clobbered at this point +379 # . . discard args +380 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +381 # check-ints-equal(*_test-output-stream->data, '3', msg) +382 # . . push args +383 68/push "F - test-get-num-reads-single-digit"/imm32 +384 68/push 0x33/imm32 +385 b8/copy-to-EAX _test-output-stream/imm32 +386 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) +387 # . . call +388 e8/call check-ints-equal/disp32 +389 # . . discard args +390 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +391 # . reclaim locals +392 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +393 5d/pop-to-EBP +394 c3/return +395 +396 test-get-num-aborts-on-non-digit-in-Look: +397 # - check that get-num returns first character if it's a digit +398 # This test uses exit-descriptors. Use EBP for setting up local variables. +399 55/push-EBP +400 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +401 # clear all streams +402 # . clear-stream(_test-stream) +403 # . . push args +404 68/push _test-stream/imm32 +405 # . . call +406 e8/call clear-stream/disp32 +407 # . . discard args +408 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +409 # . clear-stream(_test-buffered-file+4) +410 # . . push args +411 b8/copy-to-EAX _test-buffered-file/imm32 +412 05/add-to-EAX 4/imm32 +413 50/push-EAX +414 # . . call +415 e8/call clear-stream/disp32 +416 # . . discard args +417 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +418 # . clear-stream(_test-output-stream) 419 # . . push args -420 68/push _test-stream/imm32 +420 68/push _test-output-stream/imm32 421 # . . call 422 e8/call clear-stream/disp32 423 # . . discard args 424 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -425 # . clear-stream(_test-buffered-file+4) +425 # . clear-stream(_test-error-stream) 426 # . . push args -427 b8/copy-to-EAX _test-buffered-file/imm32 -428 05/add-to-EAX 4/imm32 -429 50/push-EAX -430 # . . call -431 e8/call clear-stream/disp32 -432 # . . discard args -433 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -434 # . clear-stream(_test-output-stream) -435 # . . push args -436 68/push _test-output-stream/imm32 +427 68/push _test-error-stream/imm32 +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 'in' +433 # . write(_test-stream, "3") +434 # . . push args +435 68/push "3"/imm32 +436 68/push _test-stream/imm32 437 # . . call -438 e8/call clear-stream/disp32 +438 e8/call write/disp32 439 # . . discard args -440 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -441 # . clear-stream(_test-error-stream) -442 # . . push args -443 68/push _test-error-stream/imm32 -444 # . . call -445 e8/call clear-stream/disp32 -446 # . . discard args -447 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -448 # initialize 'in' -449 # . write(_test-stream, "3") -450 # . . push args -451 68/push "3"/imm32 -452 68/push _test-stream/imm32 -453 # . . call -454 e8/call write/disp32 -455 # . . discard args -456 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -457 # initialize exit-descriptor 'ed' for the call to 'get-num' below -458 # . var ed/EAX : (address exit-descriptor) -459 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP -460 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX -461 # . tailor-exit-descriptor(ed, 16) -462 # . . push args -463 68/push 0x10/imm32/nbytes-of-args-for-get-num -464 50/push-EAX/ed -465 # . . call -466 e8/call tailor-exit-descriptor/disp32 -467 # . . discard args -468 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -469 # *don't* prime the pump -470 # get-num(in, out, err, ed) -471 # . . push args -472 50/push-EAX/ed -473 68/push _test-error-stream/imm32 -474 68/push _test-output-stream/imm32 -475 68/push _test-buffered-file/imm32 -476 # . . call -477 e8/call get-num/disp32 -478 # registers except ESP may be clobbered at this point -479 # . . discard args -480 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -481 # check that get-num tried to call exit(1) -482 # . check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1 -483 # . . push args -484 68/push "F - test-get-num-aborts-on-non-digit-in-Look"/imm32 -485 68/push 2/imm32 -486 # . . push ed->value -487 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) -488 # . . call -489 e8/call check-ints-equal/disp32 -490 # . . discard args -491 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -492 # . reclaim locals -493 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -494 5d/pop-to-EBP -495 c3/return -496 -497 test-get-num-reads-multiple-digits: -498 # - check that get-num returns all initial digits until it encounters a non-digit -499 # This test uses exit-descriptors. Use EBP for setting up local variables. -500 55/push-EBP -501 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -502 # clear all streams -503 # . clear-stream(_test-stream) +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 'get-num' below +442 # . var ed/EAX : (address exit-descriptor) +443 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +444 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX +445 # . tailor-exit-descriptor(ed, 16) +446 # . . push args +447 68/push 0x10/imm32/nbytes-of-args-for-get-num +448 50/push-EAX/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 # *don't* prime the pump +454 # get-num(in, out, err, ed) +455 # . . push args +456 50/push-EAX/ed +457 68/push _test-error-stream/imm32 +458 68/push _test-output-stream/imm32 +459 68/push _test-buffered-file/imm32 +460 # . . call +461 e8/call get-num/disp32 +462 # registers except ESP may be clobbered at this point +463 # . . discard args +464 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +465 # check that get-num tried to call exit(1) +466 # . check-ints-equal(ed->value, 2, msg) # i.e. stop was called with value 1 +467 # . . push args +468 68/push "F - test-get-num-aborts-on-non-digit-in-Look"/imm32 +469 68/push 2/imm32 +470 # . . push ed->value +471 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 4/disp8 . # push *(EAX+4) +472 # . . call +473 e8/call check-ints-equal/disp32 +474 # . . discard args +475 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +476 # . reclaim locals +477 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +478 5d/pop-to-EBP +479 c3/return +480 +481 test-get-num-reads-multiple-digits: +482 # - check that get-num returns all initial digits until it encounters a non-digit +483 # This test uses exit-descriptors. Use EBP for setting up local variables. +484 55/push-EBP +485 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +486 # clear all streams +487 # . clear-stream(_test-stream) +488 # . . push args +489 68/push _test-stream/imm32 +490 # . . call +491 e8/call clear-stream/disp32 +492 # . . discard args +493 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +494 # . clear-stream(_test-buffered-file+4) +495 # . . push args +496 b8/copy-to-EAX _test-buffered-file/imm32 +497 05/add-to-EAX 4/imm32 +498 50/push-EAX +499 # . . call +500 e8/call clear-stream/disp32 +501 # . . discard args +502 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +503 # . clear-stream(_test-output-stream) 504 # . . push args -505 68/push _test-stream/imm32 +505 68/push _test-output-stream/imm32 506 # . . call 507 e8/call clear-stream/disp32 508 # . . discard args 509 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -510 # . clear-stream(_test-buffered-file+4) +510 # . clear-stream(_test-error-stream) 511 # . . push args -512 b8/copy-to-EAX _test-buffered-file/imm32 -513 05/add-to-EAX 4/imm32 -514 50/push-EAX -515 # . . call -516 e8/call clear-stream/disp32 -517 # . . discard args -518 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -519 # . clear-stream(_test-output-stream) -520 # . . push args -521 68/push _test-output-stream/imm32 +512 68/push _test-error-stream/imm32 +513 # . . call +514 e8/call clear-stream/disp32 +515 # . . discard args +516 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +517 # initialize 'in' +518 # . write(_test-stream, "3456 x") +519 # . . push args +520 68/push "3456"/imm32 +521 68/push _test-stream/imm32 522 # . . call -523 e8/call clear-stream/disp32 +523 e8/call write/disp32 524 # . . discard args -525 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -526 # . clear-stream(_test-error-stream) -527 # . . push args -528 68/push _test-error-stream/imm32 -529 # . . call -530 e8/call clear-stream/disp32 -531 # . . discard args -532 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -533 # initialize 'in' -534 # . write(_test-stream, "3456 x") -535 # . . push args -536 68/push "3456"/imm32 -537 68/push _test-stream/imm32 -538 # . . call -539 e8/call write/disp32 -540 # . . discard args -541 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -542 # initialize exit-descriptor 'ed' for the call to 'get-num' below -543 # . var ed/EAX : (address exit-descriptor) -544 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP -545 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX -546 # . tailor-exit-descriptor(ed, 16) +525 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +526 # initialize exit-descriptor 'ed' for the call to 'get-num' below +527 # . var ed/EAX : (address exit-descriptor) +528 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +529 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX +530 # . tailor-exit-descriptor(ed, 16) +531 # . . push args +532 68/push 0x10/imm32/nbytes-of-args-for-get-num +533 50/push-EAX/ed +534 # . . call +535 e8/call tailor-exit-descriptor/disp32 +536 # . . discard args +537 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +538 # prime the pump +539 # . get-char(_test-buffered-file) +540 # . . push args +541 68/push _test-buffered-file/imm32 +542 # . . call +543 e8/call get-char/disp32 +544 # . . discard args +545 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +546 # get-num(in, out, err, ed) 547 # . . push args -548 68/push 0x10/imm32/nbytes-of-args-for-get-num -549 50/push-EAX/ed -550 # . . call -551 e8/call tailor-exit-descriptor/disp32 -552 # . . discard args -553 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -554 # prime the pump -555 # . get-char(_test-buffered-file) -556 # . . push args -557 68/push _test-buffered-file/imm32 -558 # . . call -559 e8/call get-char/disp32 -560 # . . discard args -561 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -562 # get-num(in, out, err, ed) -563 # . . push args -564 50/push-EAX/ed -565 68/push _test-error-stream/imm32 -566 68/push _test-output-stream/imm32 -567 68/push _test-buffered-file/imm32 -568 # . . call -569 e8/call get-num/disp32 -570 # registers except ESP may be clobbered at this point -571 # . . discard args -572 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -573 # check-ints-equal(*_test-output-stream->data, '3456', msg) -574 # . . push args -575 68/push "F - test-get-num-reads-multiple-digits"/imm32 -576 68/push 0x36353433/imm32 -577 b8/copy-to-EAX _test-output-stream/imm32 -578 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) -579 # . . call -580 e8/call check-ints-equal/disp32 -581 # . . discard args -582 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -583 # . reclaim locals -584 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -585 5d/pop-to-EBP -586 c3/return -587 -588 test-get-num-reads-multiple-digits-followed-by-nondigit: -589 # - check that get-num returns all initial digits until it encounters a non-digit -590 # This test uses exit-descriptors. Use EBP for setting up local variables. -591 55/push-EBP -592 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -593 # clear all streams -594 # . clear-stream(_test-stream) +548 50/push-EAX/ed +549 68/push _test-error-stream/imm32 +550 68/push _test-output-stream/imm32 +551 68/push _test-buffered-file/imm32 +552 # . . call +553 e8/call get-num/disp32 +554 # registers except ESP may be clobbered at this point +555 # . . discard args +556 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +557 # check-ints-equal(*_test-output-stream->data, '3456', msg) +558 # . . push args +559 68/push "F - test-get-num-reads-multiple-digits"/imm32 +560 68/push 0x36353433/imm32 +561 b8/copy-to-EAX _test-output-stream/imm32 +562 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) +563 # . . call +564 e8/call check-ints-equal/disp32 +565 # . . discard args +566 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +567 # . reclaim locals +568 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +569 5d/pop-to-EBP +570 c3/return +571 +572 test-get-num-reads-multiple-digits-followed-by-nondigit: +573 # - check that get-num returns all initial digits until it encounters a non-digit +574 # This test uses exit-descriptors. Use EBP for setting up local variables. +575 55/push-EBP +576 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +577 # clear all streams +578 # . clear-stream(_test-stream) +579 # . . push args +580 68/push _test-stream/imm32 +581 # . . call +582 e8/call clear-stream/disp32 +583 # . . discard args +584 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +585 # . clear-stream(_test-buffered-file+4) +586 # . . push args +587 b8/copy-to-EAX _test-buffered-file/imm32 +588 05/add-to-EAX 4/imm32 +589 50/push-EAX +590 # . . call +591 e8/call clear-stream/disp32 +592 # . . discard args +593 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +594 # . clear-stream(_test-output-stream) 595 # . . push args -596 68/push _test-stream/imm32 +596 68/push _test-output-stream/imm32 597 # . . call 598 e8/call clear-stream/disp32 599 # . . discard args 600 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -601 # . clear-stream(_test-buffered-file+4) +601 # . clear-stream(_test-error-stream) 602 # . . push args -603 b8/copy-to-EAX _test-buffered-file/imm32 -604 05/add-to-EAX 4/imm32 -605 50/push-EAX -606 # . . call -607 e8/call clear-stream/disp32 -608 # . . discard args -609 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -610 # . clear-stream(_test-output-stream) -611 # . . push args -612 68/push _test-output-stream/imm32 +603 68/push _test-error-stream/imm32 +604 # . . call +605 e8/call clear-stream/disp32 +606 # . . discard args +607 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +608 # initialize 'in' +609 # . write(_test-stream, "3456 x") +610 # . . push args +611 68/push "3456 x"/imm32 +612 68/push _test-stream/imm32 613 # . . call -614 e8/call clear-stream/disp32 +614 e8/call write/disp32 615 # . . discard args -616 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -617 # . clear-stream(_test-error-stream) -618 # . . push args -619 68/push _test-error-stream/imm32 -620 # . . call -621 e8/call clear-stream/disp32 -622 # . . discard args -623 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -624 # initialize 'in' -625 # . write(_test-stream, "3456 x") -626 # . . push args -627 68/push "3456 x"/imm32 -628 68/push _test-stream/imm32 -629 # . . call -630 e8/call write/disp32 -631 # . . discard args -632 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -633 # initialize exit-descriptor 'ed' for the call to 'get-num' below -634 # . var ed/EAX : (address exit-descriptor) -635 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP -636 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX -637 # . tailor-exit-descriptor(ed, 16) +616 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +617 # initialize exit-descriptor 'ed' for the call to 'get-num' below +618 # . var ed/EAX : (address exit-descriptor) +619 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +620 89/copy 3/mod/direct 0/rm32/EAX . . . 4/r32/ESP . . # copy ESP to EAX +621 # . tailor-exit-descriptor(ed, 16) +622 # . . push args +623 68/push 0x10/imm32/nbytes-of-args-for-get-num +624 50/push-EAX/ed +625 # . . call +626 e8/call tailor-exit-descriptor/disp32 +627 # . . discard args +628 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +629 # prime the pump +630 # . get-char(_test-buffered-file) +631 # . . push args +632 68/push _test-buffered-file/imm32 +633 # . . call +634 e8/call get-char/disp32 +635 # . . discard args +636 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +637 # get-num(in, out, err, ed) 638 # . . push args -639 68/push 0x10/imm32/nbytes-of-args-for-get-num -640 50/push-EAX/ed -641 # . . call -642 e8/call tailor-exit-descriptor/disp32 -643 # . . discard args -644 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -645 # prime the pump -646 # . get-char(_test-buffered-file) -647 # . . push args -648 68/push _test-buffered-file/imm32 -649 # . . call -650 e8/call get-char/disp32 -651 # . . discard args -652 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -653 # get-num(in, out, err, ed) -654 # . . push args -655 50/push-EAX/ed -656 68/push _test-error-stream/imm32 -657 68/push _test-output-stream/imm32 -658 68/push _test-buffered-file/imm32 -659 # . . call -660 e8/call get-num/disp32 -661 # registers except ESP may be clobbered at this point -662 # . . discard args -663 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -664 # check-ints-equal(*_test-output-stream->data, '3456', msg) -665 # . . push args -666 68/push "F - test-get-num-reads-multiple-digits-followed-by-nondigit"/imm32 -667 68/push 0x36353433/imm32 -668 b8/copy-to-EAX _test-output-stream/imm32 -669 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) -670 # . . call -671 e8/call check-ints-equal/disp32 -672 # . . discard args -673 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -674 # . reclaim locals -675 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -676 5d/pop-to-EBP -677 c3/return -678 -679 ## helpers -680 -681 # write(f, "Error: "+s+" expected\n") then stop(ed, 1) -682 expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void> -683 # . prolog -684 55/push-EBP -685 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -686 # write(f, "Error: ") +639 50/push-EAX/ed +640 68/push _test-error-stream/imm32 +641 68/push _test-output-stream/imm32 +642 68/push _test-buffered-file/imm32 +643 # . . call +644 e8/call get-num/disp32 +645 # registers except ESP may be clobbered at this point +646 # . . discard args +647 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +648 # check-ints-equal(*_test-output-stream->data, '3456', msg) +649 # . . push args +650 68/push "F - test-get-num-reads-multiple-digits-followed-by-nondigit"/imm32 +651 68/push 0x36353433/imm32 +652 b8/copy-to-EAX _test-output-stream/imm32 +653 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) +654 # . . call +655 e8/call check-ints-equal/disp32 +656 # . . discard args +657 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +658 # . reclaim locals +659 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +660 5d/pop-to-EBP +661 c3/return +662 +663 ## helpers +664 +665 # write(f, "Error: "+s+" expected\n") then stop(ed, 1) +666 expected: # ed : (address exit-descriptor), f : fd or (address stream), s : (address array byte) -> <void> +667 # . prolog +668 55/push-EBP +669 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +670 # write(f, "Error: ") +671 # . . push args +672 68/push "Error: "/imm32 +673 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +674 # . . call +675 e8/call write/disp32 +676 # . . discard args +677 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +678 # write(f, s) +679 # . . push args +680 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) +681 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +682 # . . call +683 e8/call write/disp32 +684 # . . discard args +685 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +686 # write(f, " expected\n") 687 # . . push args -688 68/push "Error: "/imm32 +688 68/push " expected\n"/imm32 689 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) 690 # . . call 691 e8/call write/disp32 692 # . . discard args 693 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -694 # write(f, s) +694 # stop(ed, 1) 695 # . . push args -696 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) -697 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +696 68/push 1/imm32 +697 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) 698 # . . call -699 e8/call write/disp32 -700 # . . discard args -701 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -702 # write(f, " expected") -703 # . . push args -704 68/push " expected"/imm32 -705 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -706 # . . call -707 e8/call write/disp32 -708 # . . discard args -709 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -710 # write(f, Newline) -711 # . . push args -712 68/push Newline/imm32 -713 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -714 # . . call -715 e8/call write/disp32 -716 # . . discard args -717 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -718 # stop(ed, 1) -719 # . . push args -720 68/push 1/imm32 -721 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -722 # . . call -723 e8/call stop/disp32 -724 # should never get past this point -725 $expected:dead-end: +699 e8/call stop/disp32 +700 # should never get past this point +701 $expected:dead-end: +702 # . epilog +703 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +704 5d/pop-to-EBP +705 c3/return +706 +707 # read a byte from 'f', and save it in 'Look' +708 get-char: # f : (address buffered-file) -> <void> +709 # . prolog +710 55/push-EBP +711 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +712 # . save registers +713 50/push-EAX +714 # read-byte(f) +715 # . . push args +716 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +717 # . . call +718 e8/call read-byte/disp32 +719 # . . discard args +720 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +721 # save EAX to Look +722 89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Look/disp32 . # copy EAX to *Look +723 $get-char:end: +724 # . restore registers +725 58/pop-to-EAX 726 # . epilog 727 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 728 5d/pop-to-EBP 729 c3/return 730 -731 # read a byte from 'f', and save it in 'Look' -732 get-char: # f : (address buffered-file) -> <void> -733 # . prolog -734 55/push-EBP -735 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -736 # . save registers -737 50/push-EAX -738 # read-byte(f) -739 # . . push args -740 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -741 # . . call -742 e8/call read-byte/disp32 -743 # . . discard args -744 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -745 # save EAX to Look -746 89/copy 0/mod/indirect 5/rm32/.disp32 . . 0/r32/EAX Look/disp32 . # copy EAX to *Look -747 $get-char:end: -748 # . restore registers -749 58/pop-to-EAX -750 # . epilog -751 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -752 5d/pop-to-EBP -753 c3/return -754 -755 is-digit?: # c : int -> EAX : boolean -756 # . prolog -757 55/push-EBP -758 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -759 # EAX = false -760 b8/copy-to-EAX 0/imm32 -761 # if (c < '0') return false -762 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x30/imm32 # compare *(EBP+8) -763 7c/jump-if-lesser $is-digit?:end/disp8 -764 # if (c > '9') return false -765 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x39/imm32 # compare *(EBP+8) -766 7f/jump-if-greater $is-digit?:end/disp8 -767 # otherwise return true -768 b8/copy-to-EAX 1/imm32 -769 $is-digit?:end: -770 # . epilog -771 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -772 5d/pop-to-EBP -773 c3/return -774 -775 == data -776 -777 Look: # (char with some extra padding) -778 0/imm32 -779 -780 _test-output-stream: -781 # current write index -782 0/imm32 -783 # current read index -784 0/imm32 -785 # length -786 8/imm32 -787 # data -788 00 00 00 00 00 00 00 00 # 8 bytes -789 -790 _test-error-stream: -791 # current write index -792 0/imm32 -793 # current read index -794 0/imm32 -795 # length -796 0x40/imm32 -797 # data (4 lines x 16 bytes/line) -798 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -799 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -800 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -801 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -802 -803 # . . vim:nowrap:textwidth=0 +731 is-digit?: # c : int -> EAX : boolean +732 # . prolog +733 55/push-EBP +734 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +735 # EAX = false +736 b8/copy-to-EAX 0/imm32 +737 # if (c < '0') return false +738 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x30/imm32 # compare *(EBP+8) +739 7c/jump-if-lesser $is-digit?:end/disp8 +740 # if (c > '9') return false +741 81 7/subop/compare 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 0x39/imm32 # compare *(EBP+8) +742 7f/jump-if-greater $is-digit?:end/disp8 +743 # otherwise return true +744 b8/copy-to-EAX 1/imm32 +745 $is-digit?:end: +746 # . epilog +747 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +748 5d/pop-to-EBP +749 c3/return +750 +751 == data +752 +753 Look: # (char with some extra padding) +754 0/imm32 +755 +756 _test-output-stream: +757 # current write index +758 0/imm32 +759 # current read index +760 0/imm32 +761 # length +762 8/imm32 +763 # data +764 00 00 00 00 00 00 00 00 # 8 bytes +765 +766 _test-error-stream: +767 # current write index +768 0/imm32 +769 # current read index +770 0/imm32 +771 # length +772 0x40/imm32 +773 # data (4 lines x 16 bytes/line) +774 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +775 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +776 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +777 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +778 +779 # . . vim:nowrap:textwidth=0 diff --git a/html/subx/apps/dquotes.subx.html b/html/subx/apps/dquotes.subx.html new file mode 100644 index 00000000..eeba6473 --- /dev/null +++ b/html/subx/apps/dquotes.subx.html @@ -0,0 +1,1103 @@ + + + + +Mu - subx/apps/dquotes.subx + + + + + + + + + + +https://github.com/akkartik/mu/blob/master/subx/apps/dquotes.subx +
+   1 # Translate literal strings within double quotes.
+   2 # Replace them with references to new variables in the data segment.
+   3 #
+   4 # To run (from the subx/ directory):
+   5 #   $ ./subx translate *.subx apps/dquote.subx -o apps/dquote
+   6 #   $ cat x
+   7 #   == code
+   8 #   ab "cd ef"/imm32
+   9 #   $ cat x  |./subx run apps/dquote
+  10 #   == code
+  11 #   ab __string1/imm32
+  12 #   == data
+  13 #   __string1:
+  14 #     5/imm32
+  15 #     0x63/c 0x64/d 0x20/  0x65/e 0x66/f
+  16 
+  17 == code
+  18 #   instruction                     effective address                                                   register    displacement    immediate
+  19 # . op          subop               mod             rm32          base        index         scale       r32
+  20 # . 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
+  21 
+  22 Entry:  # run tests if necessary, convert stdin if not
+  23 
+  24     # for debugging: run a single test
+  25 #?     e8/call test-next-word-returns-string-with-escapes/disp32
+  26 #?     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
+  27 #?     eb/jump  $main:end/disp8
+  28 
+  29     # . prolog
+  30     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+  31     # - if argc > 1 and argv[1] == "test", then return run_tests()
+  32     # . argc > 1
+  33     81          7/subop/compare     1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0/disp8         1/imm32           # compare *EBP
+  34     7e/jump-if-lesser-or-equal  $run-main/disp8
+  35     # . argv[1] == "test"
+  36     # . . push args
+  37     68/push  "test"/imm32
+  38     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+  39     # . . call
+  40     e8/call  kernel-string-equal?/disp32
+  41     # . . discard args
+  42     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+  43     # . check result
+  44     3d/compare-EAX-and  1/imm32
+  45     75/jump-if-not-equal  $run-main/disp8
+  46     # . run-tests()
+  47     e8/call  run-tests/disp32
+  48     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
+  49     eb/jump  $main:end/disp8
+  50 $run-main:
+  51     # - otherwise convert stdin
+  52     # var ed/EAX : exit-descriptor
+  53     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # subtract from ESP
+  54     89/copy                         3/mod/direct    0/rm32/EAX    .           .             .           4/r32/ESP   .               .                 # copy ESP to EAX
+  55     # configure ed to really exit()
+  56     # . ed->target = 0
+  57     c7          0/subop/copy        0/mod/direct    0/rm32/EAX    .           .             .           .           .               0/imm32           # copy to *EAX
+  58     # return convert(Stdin, 1/stdout, 2/stderr, ed)
+  59     # . . push args
+  60     50/push-EAX/ed
+  61     68/push  Stderr/imm32
+  62     68/push  Stdout/imm32
+  63     68/push  Stdin/imm32
+  64     # . . call
+  65     e8/call  convert/disp32
+  66     # . . discard args
+  67     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0x10/imm32        # add to ESP
+  68     # . syscall(exit, 0)
+  69     bb/copy-to-EBX  0/imm32
+  70 $main:end:
+  71     b8/copy-to-EAX  1/imm32/exit
+  72     cd/syscall  0x80/imm8
+  73 
+  74 # data structure:
+  75 #   row: pair of (address array byte) and (address stream byte)
+  76 #   table: (address stream row)
+  77 
+  78 convert:  # in : (address buffered-file), out : (address buffered-file) -> <void>
+  79     # pseudocode:
+  80     #   var line = new-stream(512, 1)
+  81     #   var new-data-segment = new-stream(Heap, Segment-size, 1)
+  82     #   write-stream(new-data-segment, "== data\n")
+  83     #   while true
+  84     #     clear-stream(line)
+  85     #     read-line(in, line)
+  86     #     if (line->write == 0) break               # end of file
+  87     #     while true
+  88     #       var word-slice = next-word(line)
+  89     #       if slice-empty?(word-slice)             # end of line
+  90     #         break
+  91     #       if slice-starts-with?(word-slice, "#")  # comment
+  92     #         continue
+  93     #       if slice-starts-with?(word-slice, '"')  # string literal <== what we're here for
+  94     #         process-string-literal(word-slice, out, new-data-segment)
+  95     #       else
+  96     #         write-slice(out, word-slice)
+  97     #   write-stream-data(out, new-data-segment)
+  98     #   flush(out)
+  99     #
+ 100     # . prolog
+ 101     55/push-EBP
+ 102     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 103     # . save registers
+ 104     50/push-EAX
+ 105     51/push-ECX
+ 106     52/push-EDX
+ 107     53/push-EBX
+ 108     56/push-ESI
+ 109     57/push-EDI
+ 110     # var line/ECX : (address stream byte) = stream(512)
+ 111     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               0x200/imm32       # subtract from ESP
+ 112     68/push  0x200/imm32/length
+ 113     68/push  0/imm32/read
+ 114     68/push  0/imm32/write
+ 115     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+ 116     # var word-slice/EDX = {0, 0}
+ 117     68/push  0/imm32/end
+ 118     68/push  0/imm32/curr
+ 119     89/copy                         3/mod/direct    2/rm32/EDX    .           .             .           4/r32/ESP   .               .                 # copy ESP to EDX
+ 120     # new-data-segment/EDI = new-stream(Heap, Segment-size, 1)
+ 121     # . EAX = new-stream(Heap, Segment-size, 1)
+ 122     # . . push args
+ 123     68/push  1/imm32
+ 124     ff          6/subop/push        0/mod/indirect  5/rm32/.disp32            .             .           .           Segment-size/disp32               # push *Segment-size
+ 125     68/push  Heap/imm32
+ 126     # . . call
+ 127     e8/call  new-stream/disp32
+ 128     # . . discard args
+ 129     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 130     # . EDI = EAX
+ 131     89/copy                         3/mod/direct    7/rm32/EDI    .           .             .           0/r32/EAX   .               .                 # copy EAX to EDI
+ 132     # write(new-data-segment, "== data\n")
+ 133     # . . push args
+ 134     68/push  "== data\n"/imm32
+ 135     57/push-EDI
+ 136     # . . call
+ 137     e8/call  write/disp32
+ 138     # . . discard args
+ 139     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 140 $convert:line-loop:
+ 141     # clear-stream(line)
+ 142     # . . push args
+ 143     51/push-ECX
+ 144     # . . call
+ 145     e8/call  clear-stream/disp32
+ 146     # . . discard args
+ 147     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 148     # read-line(in, line)
+ 149     # . . push args
+ 150     51/push-ECX
+ 151     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+ 152     # . . call
+ 153     e8/call  read-line/disp32
+ 154     # . . discard args
+ 155     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 156 $convert:check0:
+ 157     # if (line->write == 0) break
+ 158     81          7/subop/compare     0/mod/indirect  1/rm32/ECX    .           .             .           .           .               0/imm32           # compare *ECX
+ 159     0f 84/jump-if-equal  $convert:break/disp32
+ 160 $convert:word-loop:
+ 161     # next-word(line, word-slice)
+ 162     # . . push args
+ 163     52/push-EDX
+ 164     51/push-ECX
+ 165     # . . call
+ 166     e8/call  next-word/disp32
+ 167     # . . discard args
+ 168     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 169 $convert:check1:
+ 170     # if (slice-empty?(word-slice)) break
+ 171     # . EAX = slice-empty?(word-slice)
+ 172     # . . push args
+ 173     52/push-EDX
+ 174     # . . call
+ 175     e8/call  slice-empty?/disp32
+ 176     # . . discard args
+ 177     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 178     # . if (EAX != 0) break
+ 179     3d/compare-EAX-and  0/imm32
+ 180     0f 85/jump-if-not-equal  $convert:next-line/disp32
+ 181 $convert:check-for-comment:
+ 182     # if (slice-starts-with?(word-slice, "#")) continue
+ 183     # . start/ESI = word-slice->start
+ 184     8b/copy                         0/mod/indirect  2/rm32/EDX    .           .             .           6/r32/ESI   .               .                 # copy *EDX to ESI
+ 185     # . c/EAX = *start
+ 186     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
+ 187     8a/copy-byte                    0/mod/indirect  6/rm32/ESI    .           .             .           0/r32/AL    .               .                 # copy byte at *ESI to AL
+ 188     # . if (EAX == '#') continue
+ 189     3d/compare-EAX-and  0x23/imm32/hash
+ 190     74/jump-if-equal  $convert:word-loop/disp8
+ 191 $convert:check-for-string-literal:
+ 192     3d/compare-EAX-and  0x22/imm32/hash
+ 193     75/jump-if-not-equal  $convert:regular-word/disp8
+ 194 $convert:string-literal:
+ 195     # process-string-literal(word-slice, out, new-data-segment)
+ 196     # . . push args
+ 197     57/push-EDI
+ 198     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
+ 199     52/push-EDX
+ 200     # . . call
+ 201     e8/call  process-string-literal/disp32
+ 202     # . . discard args
+ 203     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 204     # continue
+ 205     eb/jump  $convert:next-word/disp8
+ 206 $convert:regular-word:
+ 207     # write-slice(out, word-slice)
+ 208     # . . push args
+ 209     52/push-EDX
+ 210     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
+ 211     # . . call
+ 212     e8/call  write-slice/disp32
+ 213     # . . discard args
+ 214     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 215     # fall through
+ 216 $convert:next-word:
+ 217     # write-buffered(out, " ")
+ 218     # . . push args
+ 219     68/push  " "/imm32
+ 220     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
+ 221     # . . call
+ 222     e8/call  write-buffered/disp32
+ 223     # . . discard args
+ 224     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 225     # loop
+ 226     eb/jump  $convert:word-loop/disp8
+ 227 $convert:next-line:
+ 228     # write-buffered(out, "\n")
+ 229     # . . push args
+ 230     68/push  Newline/imm32
+ 231     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
+ 232     # . . call
+ 233     e8/call  write-buffered/disp32
+ 234     # . . discard args
+ 235     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 236     # loop
+ 237     e9/jump  $convert:line-loop/disp32
+ 238 $convert:break:
+ 239 $convert:end:
+ 240     # . reclaim locals
+ 241     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0x214/imm32       # add to ESP
+ 242     # . restore registers
+ 243     5f/pop-to-EDI
+ 244     5e/pop-to-ESI
+ 245     5b/pop-to-EBX
+ 246     5a/pop-to-EDX
+ 247     59/pop-to-ECX
+ 248     58/pop-to-EAX
+ 249     # . epilog
+ 250     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 251     5d/pop-to-EBP
+ 252     c3/return
+ 253 
+ 254 # Write out 'string-literal' in a new format to 'out-segment', assign it a new
+ 255 # label, and write the new label out to 'out'.
+ 256 process-string-literal:  # string-literal : (address slice), out : (address buffered-file), out-segment : (address stream)
+ 257     # pseudocode:
+ 258     #   print(out-segment, "_string#{Next-string-literal}:\n")
+ 259     #   emit-string-literal-data(out-segment, string-literal)
+ 260     #   print(out, "_string#{Next-string-literal}")
+ 261     #   emit-metadata(out, string-literal)
+ 262     #   ++ *Next-string-literal
+ 263     #
+ 264     # . prolog
+ 265     55/push-EBP
+ 266     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 267     # . save registers
+ 268     51/push-ECX
+ 269     # var int32-stream/ECX = stream(10)  # number of decimal digits a 32-bit number can have
+ 270     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xa/imm32         # subtract from ESP
+ 271     68/push  0xa/imm32/decimal-digits-in-32bit-number
+ 272     68/push  0/imm32/read
+ 273     68/push  0/imm32/write
+ 274     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+ 275     # print(out-segment, "_string#{Next-string-literal}:\n")
+ 276     # . write(out-segment, "_string")
+ 277     # . . push args
+ 278     68/push  "_string"/imm32
+ 279     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0x10/disp8      .                 # push *(EBP+16)
+ 280     # . . call
+ 281     e8/call  write/disp32
+ 282     # . . discard args
+ 283     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 284     # . print-int32-decimal(out-segment, *Next-string-literal)
+ 285     # . write(out-segment, ":\n")
+ 286     # . . push args
+ 287     68/push  ":\n"/imm32
+ 288     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0x10/disp8      .                 # push *(EBP+16)
+ 289     # . . call
+ 290     e8/call  write/disp32
+ 291     # . . discard args
+ 292     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 293     # emit-string-literal-data(out-segment, string-literal)
+ 294     # write(out-segment, "\n")
+ 295     # . . push args
+ 296     68/push  Newline/imm32
+ 297     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0x10/disp8      .                 # push *(EBP+16)
+ 298     # . . call
+ 299     e8/call  write/disp32
+ 300     # . . discard args
+ 301     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 302     # print(out, "_string#{Next-string-literal}")
+ 303     # . write-buffered(out, "_string")
+ 304     # . . push args
+ 305     68/push  "_string"/imm32
+ 306     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
+ 307     # . . call
+ 308     e8/call  write-buffered/disp32
+ 309     # . . discard args
+ 310     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 311     # . print-int32-decimal(tmp, *Next-string-literal)
+ 312     # emit-metadata(out, string-literal)
+ 313     # ++ *Next-string-literal
+ 314     ff          0/subop/increment   0/mod/indirect  5/rm32/.disp32            .             .           .           Next-string-literal/disp32        # increment *Num-test-failures
+ 315 $process-string-literal:end:
+ 316     # . reclaim locals
+ 317     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0x16/imm32        # add to ESP
+ 318     # . restore registers
+ 319     59/pop-to-ECX
+ 320     # . epilog
+ 321     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 322     5d/pop-to-EBP
+ 323     c3/return
+ 324 
+ 325 test-convert-is-idempotent-by-default:
+ 326     # . prolog
+ 327     55/push-EBP
+ 328     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 329     # setup
+ 330     # . clear-stream(_test-input-stream)
+ 331     # . . push args
+ 332     68/push  _test-input-stream/imm32
+ 333     # . . call
+ 334     e8/call  clear-stream/disp32
+ 335     # . . discard args
+ 336     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 337     # . clear-stream(_test-input-buffered-file+4)
+ 338     # . . push args
+ 339     b8/copy-to-EAX  _test-input-buffered-file/imm32
+ 340     05/add-to-EAX  4/imm32
+ 341     50/push-EAX
+ 342     # . . call
+ 343     e8/call  clear-stream/disp32
+ 344     # . . discard args
+ 345     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 346     # . clear-stream(_test-output-stream)
+ 347     # . . push args
+ 348     68/push  _test-output-stream/imm32
+ 349     # . . call
+ 350     e8/call  clear-stream/disp32
+ 351     # . . discard args
+ 352     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 353     # . clear-stream(_test-output-buffered-file+4)
+ 354     # . . push args
+ 355     b8/copy-to-EAX  _test-output-buffered-file/imm32
+ 356     05/add-to-EAX  4/imm32
+ 357     50/push-EAX
+ 358     # . . call
+ 359     e8/call  clear-stream/disp32
+ 360     # . . discard args
+ 361     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 362     # initialize input (meta comments in parens)
+ 363     #   # comment 1
+ 364     #     # comment 2 indented
+ 365     #   == code  (new segment)
+ 366     #   # comment 3 inside a segment
+ 367     #   1
+ 368     #                         (empty line)
+ 369     #   2 3 # comment 4 inline with other contents
+ 370     #   == data  (new segment)
+ 371     #   4 5/imm32
+ 372     # . write(_test-input-stream, "# comment 1\n")
+ 373     # . . push args
+ 374     68/push  "# comment 1\n"/imm32
+ 375     68/push  _test-input-stream/imm32
+ 376     # . . call
+ 377     e8/call  write/disp32
+ 378     # . . discard args
+ 379     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 380     # . write(_test-input-stream, "  # comment 2 indented\n")
+ 381     # . . push args
+ 382     68/push  "  # comment 2 indented\n"/imm32
+ 383     68/push  _test-input-stream/imm32
+ 384     # . . call
+ 385     e8/call  write/disp32
+ 386     # . . discard args
+ 387     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 388     # . write(_test-input-stream, "== code\n")
+ 389     # . . push args
+ 390     68/push  "== code\n"/imm32
+ 391     68/push  _test-input-stream/imm32
+ 392     # . . call
+ 393     e8/call  write/disp32
+ 394     # . . discard args
+ 395     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 396     # . write(_test-input-stream, "# comment 3 inside a segment\n")
+ 397     # . . push args
+ 398     68/push  "# comment 3 inside a segment\n"/imm32
+ 399     68/push  _test-input-stream/imm32
+ 400     # . . call
+ 401     e8/call  write/disp32
+ 402     # . . discard args
+ 403     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 404     # . write(_test-input-stream, "1\n")
+ 405     # . . push args
+ 406     68/push  "1\n"/imm32
+ 407     68/push  _test-input-stream/imm32
+ 408     # . . call
+ 409     e8/call  write/disp32
+ 410     # . . discard args
+ 411     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 412     # . write(_test-input-stream, "\n")  # empty line
+ 413     # . . push args
+ 414     68/push  "\n"/imm32
+ 415     68/push  _test-input-stream/imm32
+ 416     # . . call
+ 417     e8/call  write/disp32
+ 418     # . . discard args
+ 419     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 420     # . write(_test-input-stream, "2 3 # comment 4 inline with other contents\n")
+ 421     # . . push args
+ 422     68/push  "2 3 # comment 4 inline with other contents\n"/imm32
+ 423     68/push  _test-input-stream/imm32
+ 424     # . . call
+ 425     e8/call  write/disp32
+ 426     # . . discard args
+ 427     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 428     # . write(_test-input-stream, "== data\n")
+ 429     # . . push args
+ 430     68/push  "== data\n"/imm32
+ 431     68/push  _test-input-stream/imm32
+ 432     # . . call
+ 433     e8/call  write/disp32
+ 434     # . . discard args
+ 435     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 436     # . write(_test-input-stream, "4 5/imm32\n")
+ 437     # . . push args
+ 438     68/push  "4 5/imm32\n"/imm32
+ 439     68/push  _test-input-stream/imm32
+ 440     # . . call
+ 441     e8/call  write/disp32
+ 442     # . . discard args
+ 443     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 444     # convert(_test-input-buffered-file, _test-output-buffered-file)
+ 445     # . . push args
+ 446     68/push  _test-output-buffered-file/imm32
+ 447     68/push  _test-input-buffered-file/imm32
+ 448     # . . call
+ 449     e8/call  convert/disp32
+ 450     # . . discard args
+ 451     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 452     # . flush(_test-output-buffered-file)
+ 453     # . . push args
+ 454     68/push  _test-output-buffered-file/imm32
+ 455     # . . call
+ 456     e8/call  flush/disp32
+ 457     # . . discard args
+ 458     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 459     # check output
+ 460     #     (comment dropped for now)
+ 461     #     (comment dropped for now)
+ 462     #   == code
+ 463     #     (comment dropped for now)
+ 464     #   1
+ 465     #     (comment dropped for now)
+ 466     #   2 3
+ 467     #   == data
+ 468     #   4 5/imm32
+ 469     # We don't care right now what exactly happens to comments. Trailing spaces are also minor details.
+ 470 +-- 26 lines: #?     # dump output ---------------------------------------------------------------------------------------------------------------------------
+ 496     # . check-next-stream-line-equal(_test-output-stream, "", msg)
+ 497     # . . push args
+ 498     68/push  "F - test-convert/0"/imm32
+ 499     68/push  ""/imm32
+ 500     68/push  _test-output-stream/imm32
+ 501     # . . call
+ 502     e8/call  check-next-stream-line-equal/disp32
+ 503     # . . discard args
+ 504     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 505     # . check-next-stream-line-equal(_test-output-stream, "", msg)
+ 506     # . . push args
+ 507     68/push  "F - test-convert/1"/imm32
+ 508     68/push  ""/imm32
+ 509     68/push  _test-output-stream/imm32
+ 510     # . . call
+ 511     e8/call  check-next-stream-line-equal/disp32
+ 512     # . . discard args
+ 513     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 514     # . check-next-stream-line-equal(_test-output-stream, "== code ", msg)
+ 515     # . . push args
+ 516     68/push  "F - test-convert/2"/imm32
+ 517     68/push  "== code "/imm32
+ 518     68/push  _test-output-stream/imm32
+ 519     # . . call
+ 520     e8/call  check-next-stream-line-equal/disp32
+ 521     # . . discard args
+ 522     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 523     # . check-next-stream-line-equal(_test-output-stream, "", msg)
+ 524     # . . push args
+ 525     68/push  "F - test-convert/3"/imm32
+ 526     68/push  ""/imm32
+ 527     68/push  _test-output-stream/imm32
+ 528     # . . call
+ 529     e8/call  check-next-stream-line-equal/disp32
+ 530     # . . discard args
+ 531     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 532     # . check-next-stream-line-equal(_test-output-stream, "1 ", msg)
+ 533     # . . push args
+ 534     68/push  "F - test-convert/4"/imm32
+ 535     68/push  "1 "/imm32
+ 536     68/push  _test-output-stream/imm32
+ 537     # . . call
+ 538     e8/call  check-next-stream-line-equal/disp32
+ 539     # . . discard args
+ 540     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 541     # . check-next-stream-line-equal(_test-output-stream, "", msg)
+ 542     # . . push args
+ 543     68/push  "F - test-convert/5"/imm32
+ 544     68/push  ""/imm32
+ 545     68/push  _test-output-stream/imm32
+ 546     # . . call
+ 547     e8/call  check-next-stream-line-equal/disp32
+ 548     # . . discard args
+ 549     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 550     # . check-next-stream-line-equal(_test-output-stream, "2 3 ", msg)
+ 551     # . . push args
+ 552     68/push  "F - test-convert/6"/imm32
+ 553     68/push  "2 3 "/imm32
+ 554     68/push  _test-output-stream/imm32
+ 555     # . . call
+ 556     e8/call  check-next-stream-line-equal/disp32
+ 557     # . . discard args
+ 558     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 559     # . check-next-stream-line-equal(_test-output-stream, "== data ", msg)
+ 560     # . . push args
+ 561     68/push  "F - test-convert/7"/imm32
+ 562     68/push  "== data "/imm32
+ 563     68/push  _test-output-stream/imm32
+ 564     # . . call
+ 565     e8/call  check-next-stream-line-equal/disp32
+ 566     # . . discard args
+ 567     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 568     # . check-next-stream-line-equal(_test-output-stream, "4 5/imm32 ", msg)
+ 569     # . . push args
+ 570     68/push  "F - test-convert/8"/imm32
+ 571     68/push  "4 5/imm32 "/imm32
+ 572     68/push  _test-output-stream/imm32
+ 573     # . . call
+ 574     e8/call  check-next-stream-line-equal/disp32
+ 575     # . . discard args
+ 576     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 577     # . epilog
+ 578     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 579     5d/pop-to-EBP
+ 580     c3/return
+ 581 
+ 582 # (re)compute the bounds of the next word in the line
+ 583 # return empty string on reaching end of file
+ 584 next-word:  # line : (address stream byte), out : (address slice)
+ 585     # . prolog
+ 586     55/push-EBP
+ 587     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 588     # . save registers
+ 589     50/push-EAX
+ 590     51/push-ECX
+ 591     56/push-ESI
+ 592     57/push-EDI
+ 593     # ESI = line
+ 594     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
+ 595     # EDI = out
+ 596     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   0xc/disp8       .                 # copy *(EBP+12) to EDI
+ 597     # skip-chars-matching(line, ' ')
+ 598     # . . push args
+ 599     68/push  0x20/imm32/space
+ 600     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+ 601     # . . call
+ 602     e8/call  skip-chars-matching/disp32
+ 603     # . . discard args
+ 604     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 605 $next-word:check0:
+ 606     # if (line->read >= line->write) clear out and return
+ 607     # . EAX = line->read
+ 608     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           0/r32/EAX   4/disp8         .                 # copy *(ESI+4) to EAX
+ 609     # . if (EAX < line->write) goto next check
+ 610     3b/compare                      0/mod/indirect  6/rm32/ESI    .           .             .           0/r32/EAX   .               .                 # compare EAX with *ESI
+ 611     7c/jump-if-lesser  $next-word:check-for-comment/disp8
+ 612     # . return out = {0, 0}
+ 613     c7          0/subop/copy        0/mod/direct    7/rm32/EDI    .           .             .           .           .               0/imm32           # copy to *EDI
+ 614     c7          0/subop/copy        1/mod/*+disp8   7/rm32/EDI    .           .             .           .           4/disp8         0/imm32           # copy to *(EDI+4)
+ 615     eb/jump  $next-word:end/disp8
+ 616 $next-word:check-for-comment:
+ 617     # out->start = &line->data[line->read]
+ 618     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
+ 619     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/EAX   0xc/disp8       .                 # copy ESI+ECX+12 to EAX
+ 620     89/copy                         0/mod/indirect  7/rm32/EDI    .           .             .           0/r32/EAX   .               .                 # copy EAX to *EDI
+ 621     # if line->data[line->read] == '#'
+ 622     # . EAX = line->data[line->read]
+ 623     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
+ 624     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(ESI+ECX+12) to AL
+ 625     # . compare
+ 626     3d/compare-EAX-and  0x23/imm32/pound
+ 627     75/jump-if-not-equal  $next-word:check-for-string-literal/disp8
+ 628 $next-word:comment:
+ 629     # out->end = &line->data[line->write]
+ 630     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           0/r32/EAX   .               .                 # copy *ESI to EAX
+ 631     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/ESI  0/index/EAX   .           0/r32/EAX   0xc/disp8       .                 # copy ESI+EAX+12 to EAX
+ 632     89/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           0/r32/EAX   4/disp8         .                 # copy EAX to *(EDI+4)
+ 633     # line->read = line->write  # skip rest of line
+ 634     89/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           0/r32/EAX   4/disp8         .                 # copy EAX to *(ESI+4)
+ 635     # return
+ 636     eb/jump  $next-word:end/disp8
+ 637 $next-word:check-for-string-literal:
+ 638     # if line->data[line->read] == '"'
+ 639     # . EAX = line->data[line->read]
+ 640     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
+ 641     8a/copy-byte                    1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/AL    0xc/disp8       .                 # copy byte at *(ESI+ECX+12) to AL
+ 642     # . compare
+ 643     3d/compare-EAX-and  0x22/imm32/dquote
+ 644     75/jump-if-not-equal  $next-word:regular-word/disp8
+ 645 $next-word:string-literal:
+ 646     # ++line->read  # skip '"'
+ 647     # . persist line->read
+ 648     89/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy ECX to *(ESI+4)
+ 649     # . ++line->read
+ 650     ff          0/subop/increment   1/mod/*+disp8   6/rm32/ESI    .           .             .           .           4/disp8         .                 # increment *(ESI+4)
+ 651     # parse-string(line, out)
+ 652     # . . push args
+ 653     57/push-EDI
+ 654     56/push-ESI
+ 655     # . . call
+ 656     e8/call  parse-string/disp32
+ 657     # . . discard args
+ 658     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 659     # fall through
+ 660 $next-word:regular-word:
+ 661     # otherwise skip-chars-not-matching-whitespace(line)  # including trailing newline
+ 662     # . . push args
+ 663     ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+ 664     # . . call
+ 665     e8/call  skip-chars-not-matching-whitespace/disp32
+ 666     # . . discard args
+ 667     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 668     # out->end = &line->data[line->read]
+ 669     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
+ 670     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           0/r32/EAX   0xc/disp8       .                 # copy ESI+ECX+12 to EAX
+ 671     89/copy                         1/mod/*+disp8   7/rm32/EDI    .           .             .           0/r32/EAX   4/disp8         .                 # copy EAX to *(EDI+4)
+ 672 $next-word:end:
+ 673     # . restore registers
+ 674     5f/pop-to-EDI
+ 675     5e/pop-to-ESI
+ 676     59/pop-to-ECX
+ 677     58/pop-to-EAX
+ 678     # . epilog
+ 679     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 680     5d/pop-to-EBP
+ 681     c3/return
+ 682 
+ 683 parse-string:  # line : (address stream byte), out : (address slice)
+ 684     # pseudocode:
+ 685     #   ESI = line
+ 686     #   curr/ECX = line->data[line->read]
+ 687     #   max/EDX = line->data[line->write]
+ 688     #   while curr >= max
+ 689     #     if (*curr == '"') ++curr, break
+ 690     #     if (*curr == '\\') curr+=2, continue
+ 691     #     ++curr
+ 692     #   line->read = curr - line->data
+ 693     #   out->end = curr
+ 694     #
+ 695     # . prolog
+ 696     55/push-EBP
+ 697     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 698     # . save registers
+ 699     50/push-EAX
+ 700     51/push-ECX
+ 701     52/push-EDX
+ 702     56/push-ESI
+ 703     # ESI = line
+ 704     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
+ 705     # curr/ECX = &table->data[table->read]
+ 706     # . ECX = table->read
+ 707     8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(ESI+4) to ECX
+ 708     # . ECX = table->data + ECX
+ 709     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/ESI  1/index/ECX   .           1/r32/ECX   0xc/disp8       .                 # copy ESI+ECX+12 to ECX
+ 710     # max/EDX = &table->data[table->write]
+ 711     # . EDX = table->write
+ 712     8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           2/r32/EDX   .               .                 # copy *ESI to EDX
+ 713     # . EDX = table->data + EDX
+ 714     8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/ESI  2/index/EDX   .           2/r32/EDX   0xc/disp8       .                 # copy ESI+EDX+12 to EDX
+ 715     # clear EAX
+ 716     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
+ 717 $parse-string:loop:
+ 718     # if (curr >= max) break
+ 719     39/compare                      3/mod/direct    1/rm32/ECX    .           .             .           2/r32/EDX   .               .                 # compare ECX with EDX
+ 720     7d/jump-if-greater-or-equal  $parse-string:break/disp8
+ 721     # c/EAX = *curr
+ 722     8a/copy-byte                    0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/AL    .               .                 # copy byte at *ECX to AL
+ 723 $parse-string:check1:
+ 724     # if (c == '"') break  # rely on caller to skip trailing non-whitespace
+ 725     3d/compare-EAX-and  0x22/imm32/dquote
+ 726     74/jump-if-equal  $parse-string:break/disp8
+ 727 $parse-string:check2:
+ 728     # if (c == '\\') ++curr
+ 729     3d/compare-EAX-and  0x5c/imm32/backslash
+ 730     75/jump-if-not-equal  $parse-string:continue/disp8
+ 731     # . ++curr
+ 732     41/increment-ECX
+ 733 $parse-string:continue:
+ 734     # ++curr
+ 735     41/increment-ECX
+ 736     # loop
+ 737     eb/jump  $parse-string:loop/disp8
+ 738 $parse-string:break:
+ 739     # out->end = curr
+ 740     8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           0/r32/EAX   0xc/disp8       .                 # copy *(EBP+12) to EDI
+ 741     89/copy                         1/mod/*+disp8   0/rm32/EAX    .           .             .           1/r32/ECX   4/disp8         .                 # copy ECX to *(EAX+4)
+ 742     # line->read = curr - line - 12
+ 743     29/subtract                     3/mod/direct    1/rm32/ECX    .           .             .           6/r32/ESI   .               .                 # subtract ESI from ECX
+ 744     81          5/subop/subtract    3/mod/direct    1/rm32/ECX    .           .             .           .           .               0xc/imm32         # subtract from ECX
+ 745     89/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           1/r32/ECX   4/disp8         .                 # copy ECX to *(ESI+4)
+ 746 $parse-string:end:
+ 747     # . restore registers
+ 748     5e/pop-to-ESI
+ 749     5a/pop-to-EDX
+ 750     59/pop-to-ECX
+ 751     58/pop-to-EAX
+ 752     # . epilog
+ 753     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 754     5d/pop-to-EBP
+ 755     c3/return
+ 756 
+ 757 test-next-word:
+ 758     # . prolog
+ 759     55/push-EBP
+ 760     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 761     # setup
+ 762     # . clear-stream(_test-input-stream)
+ 763     # . . push args
+ 764     68/push  _test-input-stream/imm32
+ 765     # . . call
+ 766     e8/call  clear-stream/disp32
+ 767     # . . discard args
+ 768     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 769     # var slice/ECX = {0, 0}
+ 770     68/push  0/imm32/end
+ 771     68/push  0/imm32/start
+ 772     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+ 773     # write(_test-input-stream, "  ab")
+ 774     # . . push args
+ 775     68/push  "  ab"/imm32
+ 776     68/push  _test-input-stream/imm32
+ 777     # . . call
+ 778     e8/call  write/disp32
+ 779     # . . discard args
+ 780     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 781     # next-word(_test-input-stream, slice)
+ 782     # . . push args
+ 783     51/push-ECX
+ 784     68/push  _test-input-stream/imm32
+ 785     # . . call
+ 786     e8/call  next-word/disp32
+ 787     # . . discard args
+ 788     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 789     # check-ints-equal(slice->start - _test-input-stream->data, 2, msg)
+ 790     # . check-ints-equal(slice->start - _test-input-stream, 14, msg)
+ 791     # . . push args
+ 792     68/push  "F - test-next-word: start"/imm32
+ 793     68/push  0xe/imm32
+ 794     # . . push slice->start - _test-input-stream
+ 795     8b/copy                         0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # copy *ECX to EAX
+ 796     81          5/subop/subtract    3/mod/direct    0/rm32/EAX    .           .             .           .           .               _test-input-stream/imm32 # subtract from EAX
+ 797     50/push-EAX
+ 798     # . . call
+ 799     e8/call  check-ints-equal/disp32
+ 800     # . . discard args
+ 801     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 802     # check-ints-equal(slice->end - _test-input-stream->data, 4, msg)
+ 803     # . check-ints-equal(slice->end - _test-input-stream, 16, msg)
+ 804     # . . push args
+ 805     68/push  "F - test-next-word: end"/imm32
+ 806     68/push  0x10/imm32
+ 807     # . . push slice->end - _test-input-stream
+ 808     8b/copy                         1/mod/*+disp8   1/rm32/ECX    .           .             .           0/r32/EAX   4/disp8         .                 # copy *(ECX+4) to EAX
+ 809     81          5/subop/subtract    3/mod/direct    0/rm32/EAX    .           .             .           .           .               _test-input-stream/imm32 # subtract from EAX
+ 810     50/push-EAX
+ 811     # . . call
+ 812     e8/call  check-ints-equal/disp32
+ 813     # . . discard args
+ 814     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 815     # . epilog
+ 816     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 817     5d/pop-to-EBP
+ 818     c3/return
+ 819 
+ 820 test-next-word-returns-whole-comment:
+ 821     # . prolog
+ 822     55/push-EBP
+ 823     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 824     # setup
+ 825     # . clear-stream(_test-input-stream)
+ 826     # . . push args
+ 827     68/push  _test-input-stream/imm32
+ 828     # . . call
+ 829     e8/call  clear-stream/disp32
+ 830     # . . discard args
+ 831     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 832     # var slice/ECX = {0, 0}
+ 833     68/push  0/imm32/end
+ 834     68/push  0/imm32/start
+ 835     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+ 836     # write(_test-input-stream, "  # a")
+ 837     # . . push args
+ 838     68/push  "  # a"/imm32
+ 839     68/push  _test-input-stream/imm32
+ 840     # . . call
+ 841     e8/call  write/disp32
+ 842     # . . discard args
+ 843     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 844     # next-word(_test-input-stream, slice)
+ 845     # . . push args
+ 846     51/push-ECX
+ 847     68/push  _test-input-stream/imm32
+ 848     # . . call
+ 849     e8/call  next-word/disp32
+ 850     # . . discard args
+ 851     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 852     # check-ints-equal(slice->start - _test-input-stream->data, 2, msg)
+ 853     # . check-ints-equal(slice->start - _test-input-stream, 14, msg)
+ 854     # . . push args
+ 855     68/push  "F - test-next-word-returns-whole-comment: start"/imm32
+ 856     68/push  0xe/imm32
+ 857     # . . push slice->start - _test-input-stream
+ 858     8b/copy                         0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # copy *ECX to EAX
+ 859     81          5/subop/subtract    3/mod/direct    0/rm32/EAX    .           .             .           .           .               _test-input-stream/imm32 # subtract from EAX
+ 860     50/push-EAX
+ 861     # . . call
+ 862     e8/call  check-ints-equal/disp32
+ 863     # . . discard args
+ 864     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 865     # check-ints-equal(slice->end - _test-input-stream->data, 5, msg)
+ 866     # . check-ints-equal(slice->end - _test-input-stream, 17, msg)
+ 867     # . . push args
+ 868     68/push  "F - test-next-word-returns-whole-comment: end"/imm32
+ 869     68/push  0x11/imm32
+ 870     # . . push slice->end - _test-input-stream
+ 871     8b/copy                         1/mod/*+disp8   1/rm32/ECX    .           .             .           0/r32/EAX   4/disp8         .                 # copy *(ECX+4) to EAX
+ 872     81          5/subop/subtract    3/mod/direct    0/rm32/EAX    .           .             .           .           .               _test-input-stream/imm32 # subtract from EAX
+ 873     50/push-EAX
+ 874     # . . call
+ 875     e8/call  check-ints-equal/disp32
+ 876     # . . discard args
+ 877     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 878     # . epilog
+ 879     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 880     5d/pop-to-EBP
+ 881     c3/return
+ 882 
+ 883 test-next-word-returns-empty-string-on-eof:
+ 884     # . prolog
+ 885     55/push-EBP
+ 886     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 887     # setup
+ 888     # . clear-stream(_test-input-stream)
+ 889     # . . push args
+ 890     68/push  _test-input-stream/imm32
+ 891     # . . call
+ 892     e8/call  clear-stream/disp32
+ 893     # . . discard args
+ 894     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 895     # var slice/ECX = {0, 0}
+ 896     68/push  0/imm32/end
+ 897     68/push  0/imm32/start
+ 898     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+ 899     # write nothing to _test-input-stream
+ 900     # next-word(_test-input-stream, slice)
+ 901     # . . push args
+ 902     51/push-ECX
+ 903     68/push  _test-input-stream/imm32
+ 904     # . . call
+ 905     e8/call  next-word/disp32
+ 906     # . . discard args
+ 907     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 908     # check-ints-equal(slice->end - slice->start, 0, msg)
+ 909     # . . push args
+ 910     68/push  "F - test-next-word-returns-empty-string-on-eof"/imm32
+ 911     68/push  0/imm32
+ 912     # . . push slice->end - slice->start
+ 913     8b/copy                         1/mod/*+disp8   1/rm32/ECX    .           .             .           0/r32/EAX   4/disp8         .                 # copy *(ECX+4) to EAX
+ 914     2b/subtract                     0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # subtract *ECX from EAX
+ 915     50/push-EAX
+ 916     # . . call
+ 917     e8/call  check-ints-equal/disp32
+ 918     # . . discard args
+ 919     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 920     # . epilog
+ 921     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 922     5d/pop-to-EBP
+ 923     c3/return
+ 924 
+ 925 test-next-word-returns-whole-string:
+ 926     # . prolog
+ 927     55/push-EBP
+ 928     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 929     # setup
+ 930     # . clear-stream(_test-input-stream)
+ 931     # . . push args
+ 932     68/push  _test-input-stream/imm32
+ 933     # . . call
+ 934     e8/call  clear-stream/disp32
+ 935     # . . discard args
+ 936     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+ 937     # var slice/ECX = {0, 0}
+ 938     68/push  0/imm32/end
+ 939     68/push  0/imm32/start
+ 940     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+ 941     # write(_test-input-stream, " \"a b\"/imm32 ")
+ 942     # . . push args
+ 943     68/push  " \"a b\"/imm32 "/imm32
+ 944     68/push  _test-input-stream/imm32
+ 945     # . . call
+ 946     e8/call  write/disp32
+ 947     # . . discard args
+ 948     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 949     # next-word(_test-input-stream, slice)
+ 950     # . . push args
+ 951     51/push-ECX
+ 952     68/push  _test-input-stream/imm32
+ 953     # . . call
+ 954     e8/call  next-word/disp32
+ 955     # . . discard args
+ 956     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+ 957     # check-ints-equal(slice->start - _test-input-stream->data, 1, msg)
+ 958     # . check-ints-equal(slice->start - _test-input-stream, 13, msg)
+ 959     # . . push args
+ 960     68/push  "F - test-next-word-returns-whole-string: start"/imm32
+ 961     68/push  0xd/imm32
+ 962     # . . push slice->start - _test-input-stream
+ 963     8b/copy                         0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # copy *ECX to EAX
+ 964     81          5/subop/subtract    3/mod/direct    0/rm32/EAX    .           .             .           .           .               _test-input-stream/imm32 # subtract from EAX
+ 965     50/push-EAX
+ 966     # . . call
+ 967     e8/call  check-ints-equal/disp32
+ 968     # . . discard args
+ 969     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 970     # check-ints-equal(slice->end - _test-input-stream->data, 12, msg)
+ 971     # . check-ints-equal(slice->end - _test-input-stream, 24, msg)
+ 972     # . . push args
+ 973     68/push  "F - test-next-word-returns-whole-string: end"/imm32
+ 974     68/push  0x18/imm32
+ 975     # . . push slice->end - _test-input-stream
+ 976     8b/copy                         1/mod/*+disp8   1/rm32/ECX    .           .             .           0/r32/EAX   4/disp8         .                 # copy *(ECX+4) to EAX
+ 977     81          5/subop/subtract    3/mod/direct    0/rm32/EAX    .           .             .           .           .               _test-input-stream/imm32 # subtract from EAX
+ 978     50/push-EAX
+ 979     # . . call
+ 980     e8/call  check-ints-equal/disp32
+ 981     # . . discard args
+ 982     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+ 983     # . epilog
+ 984     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+ 985     5d/pop-to-EBP
+ 986     c3/return
+ 987 
+ 988 test-next-word-returns-string-with-escapes:
+ 989     # . prolog
+ 990     55/push-EBP
+ 991     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+ 992     # setup
+ 993     # . clear-stream(_test-input-stream)
+ 994     # . . push args
+ 995     68/push  _test-input-stream/imm32
+ 996     # . . call
+ 997     e8/call  clear-stream/disp32
+ 998     # . . discard args
+ 999     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+1000     # var slice/ECX = {0, 0}
+1001     68/push  0/imm32/end
+1002     68/push  0/imm32/start
+1003     89/copy                         3/mod/direct    1/rm32/ECX    .           .             .           4/r32/ESP   .               .                 # copy ESP to ECX
+1004     # write(_test-input-stream, " \"a\\\"b\"/x")
+1005     # . . push args
+1006     68/push  " \"a\\\"b\"/x"/imm32
+1007     68/push  _test-input-stream/imm32
+1008     # . . call
+1009     e8/call  write/disp32
+1010     # . . discard args
+1011     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1012     # next-word(_test-input-stream, slice)
+1013     # . . push args
+1014     51/push-ECX
+1015     68/push  _test-input-stream/imm32
+1016     # . . call
+1017     e8/call  next-word/disp32
+1018     # . . discard args
+1019     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+1020     # check-ints-equal(slice->start - _test-input-stream->data, 1, msg)
+1021     # . check-ints-equal(slice->start - _test-input-stream, 13, msg)
+1022     # . . push args
+1023     68/push  "F - test-next-word-returns-string-with-escapes: start"/imm32
+1024     68/push  0xd/imm32
+1025     # . . push slice->start - _test-input-stream
+1026     8b/copy                         0/mod/indirect  1/rm32/ECX    .           .             .           0/r32/EAX   .               .                 # copy *ECX to EAX
+1027     81          5/subop/subtract    3/mod/direct    0/rm32/EAX    .           .             .           .           .               _test-input-stream/imm32 # subtract from EAX
+1028     50/push-EAX
+1029     # . . call
+1030     e8/call  check-ints-equal/disp32
+1031     # . . discard args
+1032     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+1033     # check-ints-equal(slice->end - _test-input-stream->data, 9, msg)
+1034     # . check-ints-equal(slice->end - _test-input-stream, 21, msg)
+1035     # . . push args
+1036     68/push  "F - test-next-word-returns-string-with-escapes: end"/imm32
+1037     68/push  0x15/imm32
+1038     # . . push slice->end - _test-input-stream
+1039     8b/copy                         1/mod/*+disp8   1/rm32/ECX    .           .             .           0/r32/EAX   4/disp8         .                 # copy *(ECX+4) to EAX
+1040     81          5/subop/subtract    3/mod/direct    0/rm32/EAX    .           .             .           .           .               _test-input-stream/imm32 # subtract from EAX
+1041     50/push-EAX
+1042     # . . call
+1043     e8/call  check-ints-equal/disp32
+1044     # . . discard args
+1045     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+1046     # . epilog
+1047     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+1048     5d/pop-to-EBP
+1049     c3/return
+1050 
+1051 == data
+1052 
+1053 Segment-size:
+1054   # TODO: there's currently a tight size limit on segments because we aren't growing the heap
+1055   0x100/imm32/4KB
+1056 #?   0x1000/imm32/4KB
+1057 
+1058 Next-string-literal:
+1059   1/imm32
+1060 
+1061 # . . vim:nowrap:textwidth=0
+
+ + + diff --git a/html/subx/apps/hex.subx.html b/html/subx/apps/hex.subx.html index 4d7dd8cf..a7c0c903 100644 --- a/html/subx/apps/hex.subx.html +++ b/html/subx/apps/hex.subx.html @@ -283,14 +283,14 @@ if ('onhashchange' in window) { 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 + 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 + 230 b8/copy-to-EAX _test-error-buffered-file/imm32 231 05/add-to-EAX 4/imm32 232 50/push-EAX 233 # . . call @@ -321,7 +321,7 @@ if ('onhashchange' in window) { 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 + 261 68/push _test-error-buffered-file/imm32 262 68/push _test-buffered-file/imm32 263 # . . call 264 e8/call convert-next-octet/disp32 @@ -385,14 +385,14 @@ if ('onhashchange' in window) { 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 + 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 + 332 b8/copy-to-EAX _test-error-buffered-file/imm32 333 05/add-to-EAX 4/imm32 334 50/push-EAX 335 # . . call @@ -415,7 +415,7 @@ if ('onhashchange' in window) { 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 + 355 68/push _test-error-buffered-file/imm32 356 68/push _test-buffered-file/imm32 357 # . . call 358 e8/call convert-next-octet/disp32 @@ -479,14 +479,14 @@ if ('onhashchange' in window) { 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 + 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 + 426 b8/copy-to-EAX _test-error-buffered-file/imm32 427 05/add-to-EAX 4/imm32 428 50/push-EAX 429 # . . call @@ -517,7 +517,7 @@ if ('onhashchange' in window) { 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 + 457 68/push _test-error-buffered-file/imm32 458 68/push _test-buffered-file/imm32 459 # . . call 460 e8/call convert-next-octet/disp32 @@ -608,7 +608,7 @@ if ('onhashchange' in window) { 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 + 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 @@ -652,14 +652,14 @@ if ('onhashchange' in window) { 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 + 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 + 599 b8/copy-to-EAX _test-error-buffered-file/imm32 600 05/add-to-EAX 4/imm32 601 50/push-EAX 602 # . . call @@ -690,7 +690,7 @@ if ('onhashchange' in window) { 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 + 630 68/push _test-error-buffered-file/imm32 631 68/push _test-buffered-file/imm32 632 # . . call 633 e8/call scan-next-byte/disp32 @@ -754,14 +754,14 @@ if ('onhashchange' in window) { 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 + 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 + 701 b8/copy-to-EAX _test-error-buffered-file/imm32 702 05/add-to-EAX 4/imm32 703 50/push-EAX 704 # . . call @@ -792,7 +792,7 @@ if ('onhashchange' in window) { 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 + 732 68/push _test-error-buffered-file/imm32 733 68/push _test-buffered-file/imm32 734 # . . call 735 e8/call scan-next-byte/disp32 @@ -856,14 +856,14 @@ if ('onhashchange' in window) { 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 + 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 + 803 b8/copy-to-EAX _test-error-buffered-file/imm32 804 05/add-to-EAX 4/imm32 805 50/push-EAX 806 # . . call @@ -873,737 +873,705 @@ if ('onhashchange' in window) { 810 # initialize '_test-stream' to input with leading comment 811 # . write(_test-stream, comment) 812 # . . push args - 813 68/push "#x"/imm32 + 813 68/push "#x\n"/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) + 819 # . write(_test-stream, real text) 820 # . . push args - 821 68/push Newline/imm32 + 821 68/push "ab"/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) + 827 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below + 828 # . var ed/ECX : exit-descriptor + 829 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 830 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 831 # . tailor-exit-descriptor(ed, 12) + 832 # . . push args + 833 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte + 834 51/push-ECX/ed + 835 # . . call + 836 e8/call tailor-exit-descriptor/disp32 + 837 # . . discard args + 838 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 839 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) 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) + 841 51/push-ECX/ed + 842 68/push _test-error-buffered-file/imm32 + 843 68/push _test-buffered-file/imm32 + 844 # . . call + 845 e8/call scan-next-byte/disp32 + 846 # registers except ESP may be clobbered at this point + 847 # pop args to scan-next-byte + 848 # . . discard first 2 args + 849 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 850 # . . restore ed + 851 59/pop-to-ECX + 852 # check that scan-next-byte didn't abort + 853 # . check-ints-equal(ed->value, 0, msg) + 854 # . . push args + 855 68/push "F - test-scan-next-byte-skips-comment: unexpected abort"/imm32 + 856 68/push 0/imm32 + 857 # . . push ed->value + 858 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) + 859 # . . call + 860 e8/call check-ints-equal/disp32 + 861 # . . discard args + 862 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 863 # return if abort + 864 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) + 865 75/jump-if-not-equal $test-scan-next-byte-skips-comment:end/disp8 + 866 # check-ints-equal(EAX, 0x61/a, msg) + 867 # . . push args + 868 68/push "F - test-scan-next-byte-skips-comment"/imm32 + 869 68/push 0x61/imm32/a + 870 50/push-EAX + 871 # . . call + 872 e8/call check-ints-equal/disp32 + 873 # . . discard args + 874 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 875 $test-scan-next-byte-skips-comment:end: + 876 # . epilog + 877 # don't restore ESP from EBP; manually reclaim locals + 878 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 879 5d/pop-to-EBP + 880 c3/return + 881 + 882 test-scan-next-byte-skips-comment-and-whitespace: + 883 # - check that the first byte after a comment and any further whitespace is returned + 884 # This test uses exit-descriptors. Use EBP for setting up local variables. + 885 55/push-EBP + 886 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 887 # clear all streams + 888 # . clear-stream(_test-stream) + 889 # . . push args + 890 68/push _test-stream/imm32 + 891 # . . call + 892 e8/call clear-stream/disp32 + 893 # . . discard args + 894 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 895 # . clear-stream(_test-buffered-file+4) + 896 # . . push args + 897 b8/copy-to-EAX _test-buffered-file/imm32 + 898 05/add-to-EAX 4/imm32 + 899 50/push-EAX + 900 # . . call + 901 e8/call clear-stream/disp32 + 902 # . . discard args + 903 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 904 # . clear-stream(_test-error-stream) + 905 # . . push args + 906 68/push _test-error-stream/imm32 + 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-buffered-file+4) + 912 # . . push args + 913 b8/copy-to-EAX _test-error-buffered-file/imm32 + 914 05/add-to-EAX 4/imm32 + 915 50/push-EAX + 916 # . . call + 917 e8/call clear-stream/disp32 + 918 # . . discard args + 919 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 920 # initialize '_test-stream' to input with leading comment and more whitespace after newline + 921 # . write(_test-stream, comment) + 922 # . . push args + 923 68/push "#x\n"/imm32 + 924 68/push _test-stream/imm32 + 925 # . . call + 926 e8/call write/disp32 + 927 # . . discard args + 928 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 929 # . write(_test-stream, real text) 930 # . . push args - 931 68/push "#x"/imm32 + 931 68/push " ab"/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) + 937 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below + 938 # . var ed/ECX : exit-descriptor + 939 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP + 940 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 941 # . tailor-exit-descriptor(ed, 12) + 942 # . . push args + 943 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte + 944 51/push-ECX/ed + 945 # . . call + 946 e8/call tailor-exit-descriptor/disp32 + 947 # . . discard args + 948 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 949 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) + 950 # . . push args + 951 51/push-ECX/ed + 952 68/push _test-error-buffered-file/imm32 + 953 68/push _test-buffered-file/imm32 + 954 # . . call + 955 e8/call scan-next-byte/disp32 + 956 # registers except ESP may be clobbered at this point + 957 # pop args to scan-next-byte + 958 # . . discard first 2 args + 959 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 960 # . . restore ed + 961 59/pop-to-ECX + 962 # check that scan-next-byte didn't abort + 963 # . check-ints-equal(ed->value, 0, msg) + 964 # . . push args + 965 68/push "F - test-scan-next-byte-skips-comment-and-whitespace: unexpected abort"/imm32 + 966 68/push 0/imm32 + 967 # . . push ed->value + 968 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) + 969 # . . call + 970 e8/call check-ints-equal/disp32 + 971 # . . discard args + 972 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 973 # return if abort + 974 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) + 975 75/jump-if-not-equal $test-scan-next-byte-skips-comment-and-whitespace:end/disp8 + 976 # check-ints-equal(EAX, 0x61/a, msg) + 977 # . . push args + 978 68/push "F - test-scan-next-byte-skips-comment-and-whitespace"/imm32 + 979 68/push 0x61/imm32/a + 980 50/push-EAX + 981 # . . call + 982 e8/call check-ints-equal/disp32 + 983 # . . discard args + 984 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 985 $test-scan-next-byte-skips-comment-and-whitespace:end: + 986 # . epilog + 987 # don't restore ESP from EBP; manually reclaim locals + 988 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 989 5d/pop-to-EBP + 990 c3/return + 991 + 992 test-scan-next-byte-skips-whitespace-and-comment: + 993 # - check that the first byte after any whitespace and comments is returned + 994 # This test uses exit-descriptors. Use EBP for setting up local variables. + 995 55/push-EBP + 996 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 997 # clear all streams + 998 # . clear-stream(_test-stream) + 999 # . . push args +1000 68/push _test-stream/imm32 +1001 # . . call +1002 e8/call clear-stream/disp32 +1003 # . . discard args +1004 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1005 # . clear-stream(_test-buffered-file+4) +1006 # . . push args +1007 b8/copy-to-EAX _test-buffered-file/imm32 +1008 05/add-to-EAX 4/imm32 +1009 50/push-EAX +1010 # . . call +1011 e8/call clear-stream/disp32 +1012 # . . discard args +1013 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1014 # . clear-stream(_test-error-stream) 1015 # . . push args -1016 68/push _test-stream/imm32 +1016 68/push _test-error-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) +1021 # . clear-stream(_test-error-buffered-file+4) 1022 # . . push args -1023 b8/copy-to-EAX _test-buffered-file/imm32 +1023 b8/copy-to-EAX _test-error-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 +1030 # initialize '_test-stream' to input with leading whitespace and comment +1031 # . write(_test-stream, comment) +1032 # . . push args +1033 68/push " #x\n"/imm32 +1034 68/push _test-stream/imm32 +1035 # . . call +1036 e8/call write/disp32 +1037 # . . discard args +1038 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1039 # . write(_test-stream, real text) +1040 # . . push args +1041 68/push "ab"/imm32 +1042 68/push _test-stream/imm32 +1043 # . . call +1044 e8/call write/disp32 +1045 # . . discard args +1046 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1047 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below +1048 # . var ed/ECX : exit-descriptor +1049 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +1050 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1051 # . tailor-exit-descriptor(ed, 12) +1052 # . . push args +1053 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte +1054 51/push-ECX/ed +1055 # . . call +1056 e8/call tailor-exit-descriptor/disp32 +1057 # . . discard args +1058 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1059 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) +1060 # . . push args +1061 51/push-ECX/ed +1062 68/push _test-error-buffered-file/imm32 +1063 68/push _test-buffered-file/imm32 +1064 # . . call +1065 e8/call scan-next-byte/disp32 +1066 # registers except ESP may be clobbered at this point +1067 # pop args to scan-next-byte +1068 # . . discard first 2 args +1069 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1070 # . . restore ed +1071 59/pop-to-ECX +1072 # check that scan-next-byte didn't abort +1073 # . check-ints-equal(ed->value, 0, msg) +1074 # . . push args +1075 68/push "F - test-scan-next-byte-skips-whitespace-and-comment: unexpected abort"/imm32 +1076 68/push 0/imm32 +1077 # . . push ed->value +1078 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) 1079 # . . call -1080 e8/call tailor-exit-descriptor/disp32 +1080 e8/call check-ints-equal/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 +1082 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1083 # return if abort +1084 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) +1085 75/jump-if-not-equal $test-scan-next-byte-skips-whitespace-and-comment:end/disp8 +1086 # check-ints-equal(EAX, 0x61/a, msg) +1087 # . . push args +1088 68/push "F - test-scan-next-byte-skips-whitespace-and-comment"/imm32 +1089 68/push 0x61/imm32/a +1090 50/push-EAX +1091 # . . call +1092 e8/call check-ints-equal/disp32 +1093 # . . discard args +1094 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1095 $test-scan-next-byte-skips-whitespace-and-comment:end: +1096 # . epilog +1097 # don't restore ESP from EBP; manually reclaim locals +1098 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1099 5d/pop-to-EBP +1100 c3/return +1101 +1102 test-scan-next-byte-reads-final-byte: +1103 # - check that the final byte in input is returned +1104 # This test uses exit-descriptors. Use EBP for setting up local variables. +1105 55/push-EBP +1106 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1107 # clear all streams +1108 # . clear-stream(_test-stream) +1109 # . . push args +1110 68/push _test-stream/imm32 +1111 # . . call +1112 e8/call clear-stream/disp32 +1113 # . . discard args +1114 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1115 # . clear-stream(_test-buffered-file+4) +1116 # . . push args +1117 b8/copy-to-EAX _test-buffered-file/imm32 +1118 05/add-to-EAX 4/imm32 +1119 50/push-EAX +1120 # . . call +1121 e8/call clear-stream/disp32 +1122 # . . discard args +1123 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1124 # . clear-stream(_test-error-stream) +1125 # . . push args +1126 68/push _test-error-stream/imm32 +1127 # . . call +1128 e8/call clear-stream/disp32 +1129 # . . discard args +1130 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1131 # . clear-stream(_test-error-buffered-file+4) +1132 # . . push args +1133 b8/copy-to-EAX _test-error-buffered-file/imm32 +1134 05/add-to-EAX 4/imm32 +1135 50/push-EAX +1136 # . . call +1137 e8/call clear-stream/disp32 +1138 # . . discard args +1139 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1140 # initialize '_test-stream' to input with single character +1141 # . write(_test-stream, character) +1142 # . . push args +1143 68/push "a"/imm32 +1144 68/push _test-stream/imm32 +1145 # . . call +1146 e8/call write/disp32 +1147 # . . discard args +1148 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1149 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below +1150 # . var ed/ECX : exit-descriptor +1151 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +1152 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1153 # . tailor-exit-descriptor(ed, 12) +1154 # . . push args +1155 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte +1156 51/push-ECX/ed +1157 # . . call +1158 e8/call tailor-exit-descriptor/disp32 +1159 # . . discard args +1160 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1161 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) +1162 # . . push args +1163 51/push-ECX/ed +1164 68/push _test-error-buffered-file/imm32 +1165 68/push _test-buffered-file/imm32 +1166 # . . call +1167 e8/call scan-next-byte/disp32 +1168 # registers except ESP may be clobbered at this point +1169 # pop args to scan-next-byte +1170 # . . discard first 2 args +1171 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1172 # . . restore ed +1173 59/pop-to-ECX +1174 # check that scan-next-byte didn't abort +1175 # . check-ints-equal(ed->value, 0, msg) +1176 # . . push args +1177 68/push "F - test-scan-next-byte-reads-final-byte: unexpected abort"/imm32 +1178 68/push 0/imm32 +1179 # . . push ed->value +1180 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) 1181 # . . call -1182 e8/call tailor-exit-descriptor/disp32 +1182 e8/call check-ints-equal/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 +1184 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1185 # return if abort +1186 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) +1187 75/jump-if-not-equal $test-scan-next-byte-reads-final-byte:end/disp8 +1188 # check-ints-equal(EAX, 0x61/a, msg) +1189 # . . push args +1190 68/push "F - test-scan-next-byte-reads-final-byte"/imm32 +1191 68/push 0x61/imm32/a +1192 50/push-EAX +1193 # . . call +1194 e8/call check-ints-equal/disp32 +1195 # . . discard args +1196 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1197 $test-scan-next-byte-reads-final-byte:end: +1198 # . epilog +1199 # don't restore ESP from EBP; manually reclaim locals +1200 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1201 5d/pop-to-EBP +1202 c3/return +1203 +1204 test-scan-next-byte-handles-Eof: +1205 # - check that the right sentinel value is returned when there's no data remaining to be read +1206 # This test uses exit-descriptors. Use EBP for setting up local variables. +1207 55/push-EBP +1208 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1209 # clear all streams +1210 # . clear-stream(_test-stream) +1211 # . . push args +1212 68/push _test-stream/imm32 +1213 # . . call +1214 e8/call clear-stream/disp32 +1215 # . . discard args +1216 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1217 # . clear-stream(_test-buffered-file+4) +1218 # . . push args +1219 b8/copy-to-EAX _test-buffered-file/imm32 +1220 05/add-to-EAX 4/imm32 +1221 50/push-EAX +1222 # . . call +1223 e8/call clear-stream/disp32 +1224 # . . discard args +1225 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1226 # . clear-stream(_test-error-stream) +1227 # . . push args +1228 68/push _test-error-stream/imm32 +1229 # . . call +1230 e8/call clear-stream/disp32 +1231 # . . discard args +1232 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1233 # . clear-stream(_test-error-buffered-file+4) +1234 # . . push args +1235 b8/copy-to-EAX _test-error-buffered-file/imm32 +1236 05/add-to-EAX 4/imm32 +1237 50/push-EAX +1238 # . . call +1239 e8/call clear-stream/disp32 +1240 # . . discard args +1241 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1242 # leave '_test-stream' empty +1243 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below +1244 # . var ed/ECX : exit-descriptor +1245 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +1246 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1247 # . tailor-exit-descriptor(ed, 12) +1248 # . . push args +1249 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte +1250 51/push-ECX/ed +1251 # . . call +1252 e8/call tailor-exit-descriptor/disp32 +1253 # . . discard args +1254 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1255 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) +1256 # . . push args +1257 51/push-ECX/ed +1258 68/push _test-error-buffered-file/imm32 +1259 68/push _test-buffered-file/imm32 +1260 # . . call +1261 e8/call scan-next-byte/disp32 +1262 # registers except ESP may be clobbered at this point +1263 # pop args to scan-next-byte +1264 # . . discard first 2 args +1265 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1266 # . . restore ed +1267 59/pop-to-ECX +1268 # check that scan-next-byte didn't abort +1269 # . check-ints-equal(ed->value, 0, msg) +1270 # . . push args +1271 68/push "F - test-scan-next-byte-handles-Eof: unexpected abort"/imm32 +1272 68/push 0/imm32 +1273 # . . push ed->value +1274 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) 1275 # . . call -1276 e8/call tailor-exit-descriptor/disp32 +1276 e8/call check-ints-equal/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, 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 +1278 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1279 # return if abort +1280 81 7/subop/compare 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 0/imm32 # compare *(ECX+4) +1281 75/jump-if-not-equal $test-scan-next-byte-handles-Eof:end/disp8 +1282 # check-ints-equal(EAX, Eof, msg) +1283 # . . push args +1284 68/push "F - test-scan-next-byte-handles-Eof"/imm32 +1285 68/push 0xffffffff/imm32/Eof +1286 50/push-EAX +1287 # . . call +1288 e8/call check-ints-equal/disp32 +1289 # . . discard args +1290 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1291 $test-scan-next-byte-handles-Eof:end: +1292 # . epilog +1293 # don't restore ESP from EBP; manually reclaim locals +1294 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1295 5d/pop-to-EBP +1296 c3/return +1297 +1298 test-scan-next-byte-aborts-on-invalid-byte: +1299 # - check that the a bad byte immediately aborts +1300 # This test uses exit-descriptors. Use EBP for setting up local variables. +1301 55/push-EBP +1302 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1303 # clear all streams +1304 # . clear-stream(_test-stream) +1305 # . . push args +1306 68/push _test-stream/imm32 +1307 # . . call +1308 e8/call clear-stream/disp32 +1309 # . . discard args +1310 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1311 # . clear-stream(_test-buffered-file+4) +1312 # . . push args +1313 b8/copy-to-EAX _test-buffered-file/imm32 +1314 05/add-to-EAX 4/imm32 +1315 50/push-EAX +1316 # . . call +1317 e8/call clear-stream/disp32 +1318 # . . discard args +1319 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1320 # . clear-stream(_test-error-stream) +1321 # . . push args +1322 68/push _test-error-stream/imm32 +1323 # . . call +1324 e8/call clear-stream/disp32 +1325 # . . discard args +1326 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1327 # . clear-stream(_test-error-buffered-file+4) +1328 # . . push args +1329 b8/copy-to-EAX _test-error-buffered-file/imm32 +1330 05/add-to-EAX 4/imm32 +1331 50/push-EAX +1332 # . . call +1333 e8/call clear-stream/disp32 +1334 # . . discard args +1335 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1336 # initialize '_test-stream' to "x" +1337 # . write(_test-stream, "x") +1338 # . . push args +1339 68/push "x"/imm32 +1340 68/push _test-stream/imm32 +1341 # . . call +1342 e8/call write/disp32 +1343 # . . discard args +1344 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1345 # initialize exit-descriptor 'ed' for the call to 'scan-next-byte' below +1346 # . var ed/ECX : exit-descriptor +1347 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # subtract from ESP +1348 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1349 # . tailor-exit-descriptor(ed, 12) +1350 # . . push args +1351 68/push 0xc/imm32/nbytes-of-args-for-scan-next-byte +1352 51/push-ECX/ed +1353 # . . call +1354 e8/call tailor-exit-descriptor/disp32 +1355 # . . discard args +1356 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1357 # EAX = scan-next-byte(_test-buffered-file, _test-error-buffered-file, ed) +1358 # . . push args +1359 51/push-ECX/ed +1360 68/push _test-error-buffered-file/imm32 +1361 68/push _test-buffered-file/imm32 +1362 # . . call +1363 e8/call scan-next-byte/disp32 +1364 # registers except ESP may be clobbered at this point +1365 # pop args to scan-next-byte +1366 # . . discard first 2 args +1367 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1368 # . . restore ed +1369 59/pop-to-ECX +1370 # check that scan-next-byte aborted +1371 # . check-ints-equal(ed->value, 2, msg) +1372 # . . push args +1373 68/push "F - test-scan-next-byte-aborts-on-invalid-byte"/imm32 +1374 68/push 2/imm32 +1375 # . . push ed->value +1376 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) 1377 # . . call -1378 e8/call tailor-exit-descriptor/disp32 +1378 e8/call check-ints-equal/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 # while true -1416 # EAX = read-byte(in) -1417 # if (EAX == Eof) 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) +1380 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1381 $test-scan-next-byte-aborts-on-invalid-byte:end: +1382 # . epilog +1383 # don't restore ESP from EBP; manually reclaim locals +1384 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1385 5d/pop-to-EBP +1386 c3/return +1387 +1388 skip-until-newline: # in : (address buffered-file) -> <void> +1389 # pseudocode: +1390 # push EAX +1391 # while true +1392 # EAX = read-byte(in) +1393 # if (EAX == Eof) break +1394 # if (EAX == 0x0a) break +1395 # pop EAX +1396 # . prolog +1397 55/push-EBP +1398 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1399 # . save registers +1400 50/push-EAX +1401 $skip-until-newline:loop: +1402 # . EAX = read-byte(in) +1403 # . . push args +1404 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1405 # . . call +1406 e8/call read-byte/disp32 +1407 # . . discard args +1408 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1409 # . if (EAX == Eof) break +1410 3d/compare-EAX-and 0xffffffff/imm32/Eof +1411 74/jump-if-equal $skip-until-newline:end/disp8 +1412 # . if (EAX != 0xa/newline) loop +1413 3d/compare-EAX-and 0xa/imm32/newline +1414 75/jump-if-not-equal $skip-until-newline:loop/disp8 +1415 $skip-until-newline:end: +1416 # . restore registers +1417 58/pop-to-EAX +1418 # . epilog +1419 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1420 5d/pop-to-EBP +1421 c3/return +1422 +1423 test-skip-until-newline: +1424 # - check that the read pointer points after the newline +1425 # setup +1426 # . clear-stream(_test-stream) 1427 # . . push args -1428 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1428 68/push _test-stream/imm32 1429 # . . call -1430 e8/call read-byte/disp32 +1430 e8/call clear-stream/disp32 1431 # . . discard args 1432 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1433 # . if (EAX == Eof) break -1434 3d/compare-EAX-and 0xffffffff/imm32/Eof -1435 74/jump-if-equal $skip-until-newline:end/disp8 -1436 # . if (EAX != 0xa/newline) loop -1437 3d/compare-EAX-and 0xa/imm32/newline -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 +1433 # . clear-stream(_test-buffered-file+4) +1434 # . . push args +1435 b8/copy-to-EAX _test-buffered-file/imm32 +1436 05/add-to-EAX 4/imm32 +1437 50/push-EAX +1438 # . . call +1439 e8/call clear-stream/disp32 +1440 # . . discard args +1441 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1442 # initialize '_test-stream' to "abc\nde" +1443 # . write(_test-stream, "abc") +1444 # . . push args +1445 68/push "abc\n"/imm32 +1446 68/push _test-stream/imm32 +1447 # . . call +1448 e8/call write/disp32 +1449 # . . discard args +1450 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1451 # . write(_test-stream, "de") +1452 # . . push args +1453 68/push "de"/imm32 +1454 68/push _test-stream/imm32 +1455 # . . call +1456 e8/call write/disp32 +1457 # . . discard args +1458 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1459 # skip-until-newline(_test-buffered-file) +1460 # . . push args +1461 68/push _test-buffered-file/imm32 1462 # . . call -1463 e8/call clear-stream/disp32 +1463 e8/call skip-until-newline/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 +1466 # check-ints-equal(_test-buffered-file->read, 4, msg) +1467 # . . push args +1468 68/push "F - test-skip-until-newline"/imm32 +1469 68/push 4/imm32 +1470 b8/copy-to-EAX _test-buffered-file/imm32 +1471 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 8/disp8 . # push *(EAX+8) +1472 # . . call +1473 e8/call check-ints-equal/disp32 +1474 # . . discard args +1475 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1476 # . end +1477 c3/return +1478 +1479 == data +1480 +1481 _test-error-stream: +1482 # current write index +1483 0/imm32 +1484 # current read index +1485 0/imm32 +1486 # line +1487 0x80/imm32 # 128 bytes +1488 # data (8 lines x 16 bytes/line) +1489 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +1490 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +1491 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +1492 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +1493 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +1494 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +1495 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +1496 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +1497 +1498 # a test buffered file for _test-error-stream +1499 _test-error-buffered-file: +1500 # file descriptor or (address stream) +1501 _test-error-stream/imm32 +1502 # current write index +1503 0/imm32 +1504 # current read index +1505 0/imm32 +1506 # length +1507 6/imm32 +1508 # data +1509 00 00 00 00 00 00 # 6 bytes 1510 -1511 == data -1512 -1513 _test-error-stream: -1514 # current write index -1515 0/imm32 -1516 # current read index -1517 0/imm32 -1518 # line -1519 0x80/imm32 # 128 bytes -1520 # data (8 lines x 16 bytes/line) -1521 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1522 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1523 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1524 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1525 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1526 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1527 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1528 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -1529 -1530 # a test buffered file for _test-error-stream -1531 _test-error-buffered-file: -1532 # file descriptor or (address stream) -1533 _test-error-stream/imm32 -1534 # current write index -1535 0/imm32 -1536 # current read index -1537 0/imm32 -1538 # length -1539 6/imm32 -1540 # data -1541 00 00 00 00 00 00 # 6 bytes -1542 -1543 # . . vim:nowrap:textwidth=0 +1511 # . . vim:nowrap:textwidth=0 diff --git a/html/subx/apps/pack.subx.html b/html/subx/apps/pack.subx.html index be124ece..72fc28de 100644 --- a/html/subx/apps/pack.subx.html +++ b/html/subx/apps/pack.subx.html @@ -217,5977 +217,5987 @@ if ('onhashchange' in window) { 153 # if (line->write == 0) break 154 81 7/subop/compare 0/mod/indirect 1/rm32/ECX . . . . . 0/imm32 # compare *ECX 155 0f 84/jump-if-equal $convert:break/disp32 - 156 +-- 34 lines: #? # dump line ----------------------------------------------------------------------------------------------------------------------------- - 190 # next-word(line, word-slice) - 191 # . . push args - 192 52/push-EDX - 193 51/push-ECX - 194 # . . call - 195 e8/call next-word/disp32 - 196 # . . discard args - 197 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 198 $convert:check1: - 199 # if (slice-empty?(word-slice)) write-stream-data(out, line) - 200 # . EAX = slice-empty?(word-slice) - 201 # . . push args - 202 52/push-EDX - 203 # . . call - 204 e8/call slice-empty?/disp32 - 205 # . . discard args - 206 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 207 # . if (EAX != 0) write-stream-data(out, line) - 208 3d/compare-EAX-and 0/imm32 - 209 0f 85/jump-if-not-equal $convert:pass-through/disp32 - 210 $convert:check2: - 211 +-- 50 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- - 261 # if (slice-equal?(word-slice, "==")) - 262 # word-slice = next-word(line) - 263 # in-code? = slice-equal?(word-slice, "code") - 264 # write-stream-data(out, line) - 265 # . EAX = slice-equal?(word-slice, "==") - 266 # . . push args - 267 68/push "=="/imm32 - 268 52/push-EDX - 269 # . . call - 270 e8/call slice-equal?/disp32 - 271 # . . discard args - 272 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 273 # . if (EAX == 0) goto check3 - 274 3d/compare-EAX-and 0/imm32 - 275 0f 84/jump-if-equal $convert:check3/disp32 - 276 # . next-word(line, word-slice) - 277 # . . push args - 278 52/push-EDX - 279 51/push-ECX - 280 # . . call - 281 e8/call next-word/disp32 - 282 # . . discard args - 283 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 284 +-- 50 lines: #? # dump segment name --------------------------------------------------------------------------------------------------------------------- - 334 # . in-code? = slice-equal?(word-slice, "code") - 335 # . . push args - 336 68/push "code"/imm32 - 337 52/push-EDX - 338 # . . call - 339 e8/call slice-equal?/disp32 - 340 # . . discard args - 341 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 342 # . . in-code? = EAX - 343 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX - 344 # . goto pass-through - 345 eb/jump $convert:pass-through/disp8 - 346 $convert:check3: - 347 # else rewind-stream(line) - 348 # . rewind-stream(line) - 349 # . . push args - 350 51/push-ECX - 351 # . . call - 352 e8/call rewind-stream/disp32 - 353 # . . discard args - 354 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 355 # if (in-code? != 0) convert-instruction(line, out) - 356 81 7/subop/compare 3/mod/direct 3/rm32/EBX . . . . . 0/imm32 # compare EBX - 357 74/jump-if-equal $convert:data/disp8 - 358 $convert:code: - 359 # . convert-instruction(line, out) - 360 # . . push args - 361 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 362 51/push-ECX - 363 # . . call - 364 e8/call convert-instruction/disp32 - 365 # . . discard args - 366 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 367 # . loop - 368 e9/jump $convert:loop/disp32 - 369 $convert:data: - 370 # else convert-data(line, out) - 371 # . . push args - 372 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 373 51/push-ECX - 374 # . . call - 375 e8/call convert-data/disp32 - 376 # . . discard args - 377 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 378 # . loop - 379 e9/jump $convert:loop/disp32 - 380 $convert:pass-through: - 381 # write-stream-data(out, line) - 382 # . . push args - 383 51/push-ECX - 384 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 385 # . . call - 386 e8/call write-stream-data/disp32 - 387 # . . discard args - 388 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 389 # . loop - 390 e9/jump $convert:loop/disp32 - 391 $convert:break: - 392 # flush(out) - 393 # . . push args - 394 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 395 # . . call - 396 e8/call flush/disp32 - 397 # . . discard args - 398 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 399 $convert:end: - 400 # . reclaim locals - 401 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x214/imm32 # add to ESP - 402 # . restore registers - 403 5b/pop-to-EBX - 404 5a/pop-to-EDX - 405 59/pop-to-ECX - 406 58/pop-to-EAX - 407 # . epilog - 408 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 409 5d/pop-to-EBP - 410 c3/return - 411 - 412 test-convert-passes-empty-lines-through: - 413 # if a line is empty, pass it along unchanged - 414 # . prolog - 415 55/push-EBP - 416 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 417 # setup - 418 # . clear-stream(_test-input-stream) - 419 # . . push args - 420 68/push _test-input-stream/imm32 - 421 # . . call - 422 e8/call clear-stream/disp32 - 423 # . . discard args - 424 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 425 # . clear-stream(_test-input-buffered-file+4) - 426 # . . push args - 427 b8/copy-to-EAX _test-input-buffered-file/imm32 - 428 05/add-to-EAX 4/imm32 - 429 50/push-EAX - 430 # . . call - 431 e8/call clear-stream/disp32 - 432 # . . discard args - 433 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 434 # . clear-stream(_test-output-stream) - 435 # . . push args - 436 68/push _test-output-stream/imm32 - 437 # . . call - 438 e8/call clear-stream/disp32 - 439 # . . discard args - 440 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 441 # . clear-stream(_test-output-buffered-file+4) - 442 # . . push args - 443 b8/copy-to-EAX _test-output-buffered-file/imm32 - 444 05/add-to-EAX 4/imm32 - 445 50/push-EAX - 446 # . . call - 447 e8/call clear-stream/disp32 - 448 # . . discard args - 449 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 450 # write nothing to input - 451 # convert(_test-input-buffered-file, _test-output-buffered-file) - 452 # . . push args - 453 68/push _test-output-buffered-file/imm32 - 454 68/push _test-input-buffered-file/imm32 - 455 # . . call - 456 e8/call convert/disp32 - 457 # . . discard args - 458 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 459 # check that the line just passed through - 460 # . flush(_test-output-buffered-file) - 461 # . . push args - 462 68/push _test-output-buffered-file/imm32 - 463 # . . call - 464 e8/call flush/disp32 - 465 # . . discard args - 466 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 467 # . check-stream-equal(_test-output-stream, "", msg) - 468 # . . push args - 469 68/push "F - test-convert-passes-empty-lines-through"/imm32 - 470 68/push ""/imm32 - 471 68/push _test-output-stream/imm32 - 472 # . . call - 473 e8/call check-stream-equal/disp32 - 474 # . . discard args - 475 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 476 # . epilog - 477 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 478 5d/pop-to-EBP - 479 c3/return - 480 - 481 test-convert-passes-lines-with-just-whitespace-through: - 482 # if a line is empty, pass it along unchanged - 483 # . prolog - 484 55/push-EBP - 485 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 486 # setup - 487 # . clear-stream(_test-input-stream) - 488 # . . push args - 489 68/push _test-input-stream/imm32 - 490 # . . call - 491 e8/call clear-stream/disp32 - 492 # . . discard args - 493 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 494 # . clear-stream(_test-input-buffered-file+4) - 495 # . . push args - 496 b8/copy-to-EAX _test-input-buffered-file/imm32 - 497 05/add-to-EAX 4/imm32 - 498 50/push-EAX - 499 # . . call - 500 e8/call clear-stream/disp32 - 501 # . . discard args - 502 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 503 # . clear-stream(_test-output-stream) - 504 # . . push args - 505 68/push _test-output-stream/imm32 - 506 # . . call - 507 e8/call clear-stream/disp32 - 508 # . . discard args - 509 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 510 # . clear-stream(_test-output-buffered-file+4) - 511 # . . push args - 512 b8/copy-to-EAX _test-output-buffered-file/imm32 - 513 05/add-to-EAX 4/imm32 - 514 50/push-EAX - 515 # . . call - 516 e8/call clear-stream/disp32 - 517 # . . discard args - 518 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 519 # initialize input - 520 # . write(_test-input-stream, " ") + 156 +-- 26 lines: #? # dump line ----------------------------------------------------------------------------------------------------------------------------- + 182 # next-word(line, word-slice) + 183 # . . push args + 184 52/push-EDX + 185 51/push-ECX + 186 # . . call + 187 e8/call next-word/disp32 + 188 # . . discard args + 189 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 190 $convert:check1: + 191 # if (slice-empty?(word-slice)) write-stream-data(out, line) + 192 # . EAX = slice-empty?(word-slice) + 193 # . . push args + 194 52/push-EDX + 195 # . . call + 196 e8/call slice-empty?/disp32 + 197 # . . discard args + 198 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 199 # . if (EAX != 0) write-stream-data(out, line) + 200 3d/compare-EAX-and 0/imm32 + 201 0f 85/jump-if-not-equal $convert:pass-through/disp32 + 202 $convert:check2: + 203 +-- 42 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- + 245 # if (slice-equal?(word-slice, "==")) + 246 # word-slice = next-word(line) + 247 # in-code? = slice-equal?(word-slice, "code") + 248 # write-stream-data(out, line) + 249 # . EAX = slice-equal?(word-slice, "==") + 250 # . . push args + 251 68/push "=="/imm32 + 252 52/push-EDX + 253 # . . call + 254 e8/call slice-equal?/disp32 + 255 # . . discard args + 256 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 257 # . if (EAX == 0) goto check3 + 258 3d/compare-EAX-and 0/imm32 + 259 0f 84/jump-if-equal $convert:check3/disp32 + 260 # . next-word(line, word-slice) + 261 # . . push args + 262 52/push-EDX + 263 51/push-ECX + 264 # . . call + 265 e8/call next-word/disp32 + 266 # . . discard args + 267 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 268 +-- 42 lines: #? # dump segment name --------------------------------------------------------------------------------------------------------------------- + 310 # . in-code? = slice-equal?(word-slice, "code") + 311 # . . push args + 312 68/push "code"/imm32 + 313 52/push-EDX + 314 # . . call + 315 e8/call slice-equal?/disp32 + 316 # . . discard args + 317 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 318 # . . in-code? = EAX + 319 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX + 320 # . goto pass-through + 321 eb/jump $convert:pass-through/disp8 + 322 $convert:check3: + 323 # else rewind-stream(line) + 324 # . rewind-stream(line) + 325 # . . push args + 326 51/push-ECX + 327 # . . call + 328 e8/call rewind-stream/disp32 + 329 # . . discard args + 330 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 331 # if (in-code? != 0) convert-instruction(line, out) + 332 81 7/subop/compare 3/mod/direct 3/rm32/EBX . . . . . 0/imm32 # compare EBX + 333 74/jump-if-equal $convert:data/disp8 + 334 $convert:code: + 335 # . convert-instruction(line, out) + 336 # . . push args + 337 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 338 51/push-ECX + 339 # . . call + 340 e8/call convert-instruction/disp32 + 341 # . . discard args + 342 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 343 # . loop + 344 e9/jump $convert:loop/disp32 + 345 $convert:data: + 346 # else convert-data(line, out) + 347 # . . push args + 348 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 349 51/push-ECX + 350 # . . call + 351 e8/call convert-data/disp32 + 352 # . . discard args + 353 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 354 # . loop + 355 e9/jump $convert:loop/disp32 + 356 $convert:pass-through: + 357 # write-stream-data(out, line) + 358 # . . push args + 359 51/push-ECX + 360 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 361 # . . call + 362 e8/call write-stream-data/disp32 + 363 # . . discard args + 364 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 365 # . loop + 366 e9/jump $convert:loop/disp32 + 367 $convert:break: + 368 # flush(out) + 369 # . . push args + 370 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 371 # . . call + 372 e8/call flush/disp32 + 373 # . . discard args + 374 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 375 $convert:end: + 376 # . reclaim locals + 377 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x214/imm32 # add to ESP + 378 # . restore registers + 379 5b/pop-to-EBX + 380 5a/pop-to-EDX + 381 59/pop-to-ECX + 382 58/pop-to-EAX + 383 # . epilog + 384 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 385 5d/pop-to-EBP + 386 c3/return + 387 + 388 test-convert-passes-empty-lines-through: + 389 # if a line is empty, pass it along unchanged + 390 # . prolog + 391 55/push-EBP + 392 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 393 # setup + 394 # . clear-stream(_test-input-stream) + 395 # . . push args + 396 68/push _test-input-stream/imm32 + 397 # . . call + 398 e8/call clear-stream/disp32 + 399 # . . discard args + 400 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 401 # . clear-stream(_test-input-buffered-file+4) + 402 # . . push args + 403 b8/copy-to-EAX _test-input-buffered-file/imm32 + 404 05/add-to-EAX 4/imm32 + 405 50/push-EAX + 406 # . . call + 407 e8/call clear-stream/disp32 + 408 # . . discard args + 409 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 410 # . clear-stream(_test-output-stream) + 411 # . . push args + 412 68/push _test-output-stream/imm32 + 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-output-buffered-file+4) + 418 # . . push args + 419 b8/copy-to-EAX _test-output-buffered-file/imm32 + 420 05/add-to-EAX 4/imm32 + 421 50/push-EAX + 422 # . . call + 423 e8/call clear-stream/disp32 + 424 # . . discard args + 425 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 426 # write nothing to input + 427 # convert(_test-input-buffered-file, _test-output-buffered-file) + 428 # . . push args + 429 68/push _test-output-buffered-file/imm32 + 430 68/push _test-input-buffered-file/imm32 + 431 # . . call + 432 e8/call convert/disp32 + 433 # . . discard args + 434 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 435 # check that the line just passed through + 436 # . flush(_test-output-buffered-file) + 437 # . . push args + 438 68/push _test-output-buffered-file/imm32 + 439 # . . call + 440 e8/call flush/disp32 + 441 # . . discard args + 442 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 443 # . check-stream-equal(_test-output-stream, "", msg) + 444 # . . push args + 445 68/push "F - test-convert-passes-empty-lines-through"/imm32 + 446 68/push ""/imm32 + 447 68/push _test-output-stream/imm32 + 448 # . . call + 449 e8/call check-stream-equal/disp32 + 450 # . . discard args + 451 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 452 # . epilog + 453 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 454 5d/pop-to-EBP + 455 c3/return + 456 + 457 test-convert-passes-lines-with-just-whitespace-through: + 458 # if a line is empty, pass it along unchanged + 459 # . prolog + 460 55/push-EBP + 461 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 462 # setup + 463 # . clear-stream(_test-input-stream) + 464 # . . push args + 465 68/push _test-input-stream/imm32 + 466 # . . call + 467 e8/call clear-stream/disp32 + 468 # . . discard args + 469 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 470 # . clear-stream(_test-input-buffered-file+4) + 471 # . . push args + 472 b8/copy-to-EAX _test-input-buffered-file/imm32 + 473 05/add-to-EAX 4/imm32 + 474 50/push-EAX + 475 # . . call + 476 e8/call clear-stream/disp32 + 477 # . . discard args + 478 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 479 # . clear-stream(_test-output-stream) + 480 # . . push args + 481 68/push _test-output-stream/imm32 + 482 # . . call + 483 e8/call clear-stream/disp32 + 484 # . . discard args + 485 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 486 # . clear-stream(_test-output-buffered-file+4) + 487 # . . push args + 488 b8/copy-to-EAX _test-output-buffered-file/imm32 + 489 05/add-to-EAX 4/imm32 + 490 50/push-EAX + 491 # . . call + 492 e8/call clear-stream/disp32 + 493 # . . discard args + 494 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 495 # initialize input + 496 # . write(_test-input-stream, " ") + 497 # . . push args + 498 68/push " "/imm32 + 499 68/push _test-input-stream/imm32 + 500 # . . call + 501 e8/call write/disp32 + 502 # . . discard args + 503 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 504 # convert(_test-input-buffered-file, _test-output-buffered-file) + 505 # . . push args + 506 68/push _test-output-buffered-file/imm32 + 507 68/push _test-input-buffered-file/imm32 + 508 # . . call + 509 e8/call convert/disp32 + 510 # . . discard args + 511 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 512 # check that the line just passed through + 513 # . flush(_test-output-buffered-file) + 514 # . . push args + 515 68/push _test-output-buffered-file/imm32 + 516 # . . call + 517 e8/call flush/disp32 + 518 # . . discard args + 519 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 520 # . check-next-stream-line-equal(_test-output-stream, " ", msg) 521 # . . push args - 522 68/push " "/imm32 - 523 68/push _test-input-stream/imm32 - 524 # . . call - 525 e8/call write/disp32 - 526 # . . discard args - 527 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 528 # convert(_test-input-buffered-file, _test-output-buffered-file) - 529 # . . push args - 530 68/push _test-output-buffered-file/imm32 - 531 68/push _test-input-buffered-file/imm32 - 532 # . . call - 533 e8/call convert/disp32 - 534 # . . discard args - 535 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 536 # check that the line just passed through - 537 # . flush(_test-output-buffered-file) - 538 # . . push args - 539 68/push _test-output-buffered-file/imm32 - 540 # . . call - 541 e8/call flush/disp32 - 542 # . . discard args - 543 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 544 # . check-next-stream-line-equal(_test-output-stream, " ", msg) - 545 # . . push args - 546 68/push "F - test-convert-passes-with-just-whitespace-through"/imm32 - 547 68/push " "/imm32 - 548 68/push _test-output-stream/imm32 - 549 # . . call - 550 e8/call check-next-stream-line-equal/disp32 - 551 # . . discard args - 552 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 553 # . epilog - 554 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 555 5d/pop-to-EBP - 556 c3/return - 557 - 558 test-convert-passes-segment-headers-through: - 559 # if a line starts with '==', pass it along unchanged - 560 # . prolog - 561 55/push-EBP - 562 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 563 # setup - 564 # . clear-stream(_test-input-stream) - 565 # . . push args - 566 68/push _test-input-stream/imm32 - 567 # . . call - 568 e8/call clear-stream/disp32 - 569 # . . discard args - 570 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 571 # . clear-stream(_test-input-buffered-file+4) - 572 # . . push args - 573 b8/copy-to-EAX _test-input-buffered-file/imm32 - 574 05/add-to-EAX 4/imm32 - 575 50/push-EAX - 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-output-stream) - 581 # . . push args - 582 68/push _test-output-stream/imm32 - 583 # . . call - 584 e8/call clear-stream/disp32 - 585 # . . discard args - 586 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 587 # . clear-stream(_test-output-buffered-file+4) - 588 # . . push args - 589 b8/copy-to-EAX _test-output-buffered-file/imm32 - 590 05/add-to-EAX 4/imm32 - 591 50/push-EAX - 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 # initialize input - 597 # . write(_test-input-stream, "== abcd") + 522 68/push "F - test-convert-passes-with-just-whitespace-through"/imm32 + 523 68/push " "/imm32 + 524 68/push _test-output-stream/imm32 + 525 # . . call + 526 e8/call check-next-stream-line-equal/disp32 + 527 # . . discard args + 528 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 529 # . epilog + 530 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 531 5d/pop-to-EBP + 532 c3/return + 533 + 534 test-convert-passes-segment-headers-through: + 535 # if a line starts with '==', pass it along unchanged + 536 # . prolog + 537 55/push-EBP + 538 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 539 # setup + 540 # . clear-stream(_test-input-stream) + 541 # . . push args + 542 68/push _test-input-stream/imm32 + 543 # . . call + 544 e8/call clear-stream/disp32 + 545 # . . discard args + 546 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 547 # . clear-stream(_test-input-buffered-file+4) + 548 # . . push args + 549 b8/copy-to-EAX _test-input-buffered-file/imm32 + 550 05/add-to-EAX 4/imm32 + 551 50/push-EAX + 552 # . . call + 553 e8/call clear-stream/disp32 + 554 # . . discard args + 555 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 556 # . clear-stream(_test-output-stream) + 557 # . . push args + 558 68/push _test-output-stream/imm32 + 559 # . . call + 560 e8/call clear-stream/disp32 + 561 # . . discard args + 562 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 563 # . clear-stream(_test-output-buffered-file+4) + 564 # . . push args + 565 b8/copy-to-EAX _test-output-buffered-file/imm32 + 566 05/add-to-EAX 4/imm32 + 567 50/push-EAX + 568 # . . call + 569 e8/call clear-stream/disp32 + 570 # . . discard args + 571 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 572 # initialize input + 573 # . write(_test-input-stream, "== abcd") + 574 # . . push args + 575 68/push "== abcd"/imm32 + 576 68/push _test-input-stream/imm32 + 577 # . . call + 578 e8/call write/disp32 + 579 # . . discard args + 580 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 581 # convert(_test-input-buffered-file, _test-output-buffered-file) + 582 # . . push args + 583 68/push _test-output-buffered-file/imm32 + 584 68/push _test-input-buffered-file/imm32 + 585 # . . call + 586 e8/call convert/disp32 + 587 # . . discard args + 588 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 589 # check that the line just passed through + 590 # . flush(_test-output-buffered-file) + 591 # . . push args + 592 68/push _test-output-buffered-file/imm32 + 593 # . . call + 594 e8/call flush/disp32 + 595 # . . discard args + 596 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 597 # . check-stream-equal(_test-output-stream, "== abcd", msg) 598 # . . push args - 599 68/push "== abcd"/imm32 - 600 68/push _test-input-stream/imm32 - 601 # . . call - 602 e8/call write/disp32 - 603 # . . discard args - 604 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 605 # convert(_test-input-buffered-file, _test-output-buffered-file) - 606 # . . push args - 607 68/push _test-output-buffered-file/imm32 - 608 68/push _test-input-buffered-file/imm32 - 609 # . . call - 610 e8/call convert/disp32 - 611 # . . discard args - 612 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 613 # check that the line just passed through - 614 # . flush(_test-output-buffered-file) - 615 # . . push args - 616 68/push _test-output-buffered-file/imm32 - 617 # . . call - 618 e8/call flush/disp32 - 619 # . . discard args - 620 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 621 # . check-stream-equal(_test-output-stream, "== abcd", msg) - 622 # . . push args - 623 68/push "F - test-convert-passes-segment-headers-through"/imm32 - 624 68/push "== abcd"/imm32 - 625 68/push _test-output-stream/imm32 - 626 # . . call - 627 e8/call check-stream-equal/disp32 - 628 # . . discard args - 629 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 630 # . epilog - 631 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 632 5d/pop-to-EBP - 633 c3/return - 634 - 635 test-convert-in-data-segment: - 636 # correctly process lines in the data segment - 637 # . prolog - 638 55/push-EBP - 639 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 640 # setup - 641 # . clear-stream(_test-input-stream) - 642 # . . push args - 643 68/push _test-input-stream/imm32 - 644 # . . call - 645 e8/call clear-stream/disp32 - 646 # . . discard args - 647 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 648 # . clear-stream(_test-input-buffered-file+4) - 649 # . . push args - 650 b8/copy-to-EAX _test-input-buffered-file/imm32 - 651 05/add-to-EAX 4/imm32 - 652 50/push-EAX - 653 # . . call - 654 e8/call clear-stream/disp32 - 655 # . . discard args - 656 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 657 # . clear-stream(_test-output-stream) - 658 # . . push args - 659 68/push _test-output-stream/imm32 - 660 # . . call - 661 e8/call clear-stream/disp32 - 662 # . . discard args - 663 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 664 # . clear-stream(_test-output-buffered-file+4) - 665 # . . push args - 666 b8/copy-to-EAX _test-output-buffered-file/imm32 - 667 05/add-to-EAX 4/imm32 - 668 50/push-EAX - 669 # . . call - 670 e8/call clear-stream/disp32 - 671 # . . discard args - 672 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 673 # initialize input - 674 # == code - 675 # == data - 676 # 3 4/imm32 - 677 # . write(_test-input-stream, "== code") + 599 68/push "F - test-convert-passes-segment-headers-through"/imm32 + 600 68/push "== abcd"/imm32 + 601 68/push _test-output-stream/imm32 + 602 # . . call + 603 e8/call check-stream-equal/disp32 + 604 # . . discard args + 605 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 606 # . epilog + 607 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 608 5d/pop-to-EBP + 609 c3/return + 610 + 611 test-convert-in-data-segment: + 612 # correctly process lines in the data segment + 613 # . prolog + 614 55/push-EBP + 615 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 616 # setup + 617 # . clear-stream(_test-input-stream) + 618 # . . push args + 619 68/push _test-input-stream/imm32 + 620 # . . call + 621 e8/call clear-stream/disp32 + 622 # . . discard args + 623 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 624 # . clear-stream(_test-input-buffered-file+4) + 625 # . . push args + 626 b8/copy-to-EAX _test-input-buffered-file/imm32 + 627 05/add-to-EAX 4/imm32 + 628 50/push-EAX + 629 # . . call + 630 e8/call clear-stream/disp32 + 631 # . . discard args + 632 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 633 # . clear-stream(_test-output-stream) + 634 # . . push args + 635 68/push _test-output-stream/imm32 + 636 # . . call + 637 e8/call clear-stream/disp32 + 638 # . . discard args + 639 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 640 # . clear-stream(_test-output-buffered-file+4) + 641 # . . push args + 642 b8/copy-to-EAX _test-output-buffered-file/imm32 + 643 05/add-to-EAX 4/imm32 + 644 50/push-EAX + 645 # . . call + 646 e8/call clear-stream/disp32 + 647 # . . discard args + 648 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 649 # initialize input + 650 # == code + 651 # == data + 652 # 3 4/imm32 + 653 # . write(_test-input-stream, "== code") + 654 # . . push args + 655 68/push "== code\n"/imm32 + 656 68/push _test-input-stream/imm32 + 657 # . . call + 658 e8/call write/disp32 + 659 # . . discard args + 660 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 661 # . write(_test-input-stream, "== data\n") + 662 # . . push args + 663 68/push "== data\n"/imm32 + 664 68/push _test-input-stream/imm32 + 665 # . . call + 666 e8/call write/disp32 + 667 # . . discard args + 668 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 669 # . write(_test-input-stream, "3 4/imm32\n") + 670 # . . push args + 671 68/push "3 4/imm32\n"/imm32 + 672 68/push _test-input-stream/imm32 + 673 # . . call + 674 e8/call write/disp32 + 675 # . . discard args + 676 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 677 # convert(_test-input-buffered-file, _test-output-buffered-file) 678 # . . push args - 679 68/push "== code"/imm32 - 680 68/push _test-input-stream/imm32 + 679 68/push _test-output-buffered-file/imm32 + 680 68/push _test-input-buffered-file/imm32 681 # . . call - 682 e8/call write/disp32 + 682 e8/call convert/disp32 683 # . . discard args 684 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 685 # . write(_test-input-stream, "\n") - 686 # . . push args - 687 68/push Newline/imm32 - 688 68/push _test-input-stream/imm32 - 689 # . . call - 690 e8/call write/disp32 - 691 # . . discard args - 692 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 693 # . write(_test-input-stream, "== data") - 694 # . . push args - 695 68/push "== data"/imm32 - 696 68/push _test-input-stream/imm32 - 697 # . . call - 698 e8/call write/disp32 - 699 # . . discard args - 700 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 701 # . write(_test-input-stream, "\n") - 702 # . . push args - 703 68/push Newline/imm32 - 704 68/push _test-input-stream/imm32 - 705 # . . call - 706 e8/call write/disp32 - 707 # . . discard args - 708 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 709 # . write(_test-input-stream, "3 4/imm32") - 710 # . . push args - 711 68/push "3 4/imm32"/imm32 - 712 68/push _test-input-stream/imm32 - 713 # . . call - 714 e8/call write/disp32 - 715 # . . discard args - 716 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 717 # . write(_test-input-stream, "\n") - 718 # . . push args - 719 68/push Newline/imm32 - 720 68/push _test-input-stream/imm32 - 721 # . . call - 722 e8/call write/disp32 - 723 # . . discard args - 724 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 725 # convert(_test-input-buffered-file, _test-output-buffered-file) - 726 # . . push args - 727 68/push _test-output-buffered-file/imm32 - 728 68/push _test-input-buffered-file/imm32 - 729 # . . call - 730 e8/call convert/disp32 - 731 # . . discard args - 732 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 733 # check output - 734 +-- 34 lines: #? # debug print --------------------------------------------------------------------------------------------------------------------------- - 768 # . flush(_test-output-buffered-file) - 769 # . . push args - 770 68/push _test-output-buffered-file/imm32 - 771 # . . call - 772 e8/call flush/disp32 - 773 # . . discard args - 774 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 775 # . check-next-stream-line-equal(_test-output-stream, "== code", msg) - 776 # . . push args - 777 68/push "F - test-convert-in-data-segment/0"/imm32 - 778 68/push "== code"/imm32 - 779 68/push _test-output-stream/imm32 - 780 # . . call - 781 e8/call check-next-stream-line-equal/disp32 - 782 # . . discard args - 783 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 784 # . check-next-stream-line-equal(_test-output-stream, "== data", msg) - 785 # . . push args - 786 68/push "F - test-convert-in-data-segment/1"/imm32 - 787 68/push "== data"/imm32 - 788 68/push _test-output-stream/imm32 - 789 # . . call - 790 e8/call check-next-stream-line-equal/disp32 - 791 # . . discard args - 792 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 793 # . check-next-stream-line-equal(_test-output-stream, "03 04 00 00 00 ", msg) - 794 # . . push args - 795 68/push "F - test-convert-in-data-segment/2"/imm32 - 796 68/push "03 04 00 00 00 "/imm32 - 797 68/push _test-output-stream/imm32 - 798 # . . call - 799 e8/call check-next-stream-line-equal/disp32 - 800 # . . discard args - 801 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 802 # . epilog - 803 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 804 5d/pop-to-EBP - 805 c3/return - 806 - 807 test-convert-code-and-data-segments: - 808 # correctly process lines in both code and data segments - 809 # . prolog - 810 55/push-EBP - 811 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - 812 # setup - 813 # . clear-stream(_test-input-stream) - 814 # . . push args - 815 68/push _test-input-stream/imm32 - 816 # . . call - 817 e8/call clear-stream/disp32 - 818 # . . discard args - 819 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 820 # . clear-stream(_test-input-buffered-file+4) - 821 # . . push args - 822 b8/copy-to-EAX _test-input-buffered-file/imm32 - 823 05/add-to-EAX 4/imm32 - 824 50/push-EAX - 825 # . . call - 826 e8/call clear-stream/disp32 - 827 # . . discard args - 828 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 829 # . clear-stream(_test-output-stream) - 830 # . . push args - 831 68/push _test-output-stream/imm32 - 832 # . . call - 833 e8/call clear-stream/disp32 - 834 # . . discard args - 835 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 836 # . clear-stream(_test-output-buffered-file+4) - 837 # . . push args - 838 b8/copy-to-EAX _test-output-buffered-file/imm32 - 839 05/add-to-EAX 4/imm32 - 840 50/push-EAX - 841 # . . call - 842 e8/call clear-stream/disp32 - 843 # . . discard args - 844 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 845 # initialize input - 846 # == code - 847 # e8/call 20/disp32 - 848 # 68/push 0x20/imm8 - 849 # == data - 850 # 3 4/imm32 - 851 # . write(_test-input-stream, "== code") - 852 # . . push args - 853 68/push "== code"/imm32 - 854 68/push _test-input-stream/imm32 - 855 # . . call - 856 e8/call write/disp32 - 857 # . . discard args - 858 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 859 # . write(_test-input-stream, "\n") - 860 # . . push args - 861 68/push Newline/imm32 - 862 68/push _test-input-stream/imm32 - 863 # . . call - 864 e8/call write/disp32 - 865 # . . discard args - 866 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 867 # . write(_test-input-stream, "e8/call 20/disp32") - 868 # . . push args - 869 68/push "e8/call 20/disp32"/imm32 - 870 68/push _test-input-stream/imm32 - 871 # . . call - 872 e8/call write/disp32 - 873 # . . discard args - 874 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 875 # . write(_test-input-stream, "\n") + 685 # check output + 686 +-- 26 lines: #? # debug print --------------------------------------------------------------------------------------------------------------------------- + 712 # . flush(_test-output-buffered-file) + 713 # . . push args + 714 68/push _test-output-buffered-file/imm32 + 715 # . . call + 716 e8/call flush/disp32 + 717 # . . discard args + 718 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 719 # . check-next-stream-line-equal(_test-output-stream, "== code", msg) + 720 # . . push args + 721 68/push "F - test-convert-in-data-segment/0"/imm32 + 722 68/push "== code"/imm32 + 723 68/push _test-output-stream/imm32 + 724 # . . call + 725 e8/call check-next-stream-line-equal/disp32 + 726 # . . discard args + 727 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 728 # . check-next-stream-line-equal(_test-output-stream, "== data", msg) + 729 # . . push args + 730 68/push "F - test-convert-in-data-segment/1"/imm32 + 731 68/push "== data"/imm32 + 732 68/push _test-output-stream/imm32 + 733 # . . call + 734 e8/call check-next-stream-line-equal/disp32 + 735 # . . discard args + 736 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 737 # . check-next-stream-line-equal(_test-output-stream, "03 04 00 00 00 ", msg) + 738 # . . push args + 739 68/push "F - test-convert-in-data-segment/2"/imm32 + 740 68/push "03 04 00 00 00 "/imm32 + 741 68/push _test-output-stream/imm32 + 742 # . . call + 743 e8/call check-next-stream-line-equal/disp32 + 744 # . . discard args + 745 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 746 # . epilog + 747 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 748 5d/pop-to-EBP + 749 c3/return + 750 + 751 test-convert-code-and-data-segments: + 752 # correctly process lines in both code and data segments + 753 # . prolog + 754 55/push-EBP + 755 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 756 # setup + 757 # . clear-stream(_test-input-stream) + 758 # . . push args + 759 68/push _test-input-stream/imm32 + 760 # . . call + 761 e8/call clear-stream/disp32 + 762 # . . discard args + 763 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 764 # . clear-stream(_test-input-buffered-file+4) + 765 # . . push args + 766 b8/copy-to-EAX _test-input-buffered-file/imm32 + 767 05/add-to-EAX 4/imm32 + 768 50/push-EAX + 769 # . . call + 770 e8/call clear-stream/disp32 + 771 # . . discard args + 772 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 773 # . clear-stream(_test-output-stream) + 774 # . . push args + 775 68/push _test-output-stream/imm32 + 776 # . . call + 777 e8/call clear-stream/disp32 + 778 # . . discard args + 779 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 780 # . clear-stream(_test-output-buffered-file+4) + 781 # . . push args + 782 b8/copy-to-EAX _test-output-buffered-file/imm32 + 783 05/add-to-EAX 4/imm32 + 784 50/push-EAX + 785 # . . call + 786 e8/call clear-stream/disp32 + 787 # . . discard args + 788 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 789 # initialize input + 790 # == code + 791 # e8/call 20/disp32 + 792 # 68/push 0x20/imm8 + 793 # == data + 794 # 3 4/imm32 + 795 # . write(_test-input-stream, "== code\n") + 796 # . . push args + 797 68/push "== code\n"/imm32 + 798 68/push _test-input-stream/imm32 + 799 # . . call + 800 e8/call write/disp32 + 801 # . . discard args + 802 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 803 # . write(_test-input-stream, "e8/call 20/disp32\n") + 804 # . . push args + 805 68/push "e8/call 20/disp32\n"/imm32 + 806 68/push _test-input-stream/imm32 + 807 # . . call + 808 e8/call write/disp32 + 809 # . . discard args + 810 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 811 # . write(_test-input-stream, "68/push 0x20/imm8\n") + 812 # . . push args + 813 68/push "68/push 0x20/imm8\n"/imm32 + 814 68/push _test-input-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-input-stream, "== data\n") + 820 # . . push args + 821 68/push "== data\n"/imm32 + 822 68/push _test-input-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-input-stream, "3 4/imm32\n") + 828 # . . push args + 829 68/push "3 4/imm32\n"/imm32 + 830 68/push _test-input-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 # convert(_test-input-buffered-file, _test-output-buffered-file) + 836 # . . push args + 837 68/push _test-output-buffered-file/imm32 + 838 68/push _test-input-buffered-file/imm32 + 839 # . . call + 840 e8/call convert/disp32 + 841 # . . discard args + 842 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 843 # check output + 844 # == code + 845 # e8 20 00 00 00 # e8/call 20/disp32 + 846 # 68 20 # 68/push 0x20/imm8 + 847 # == data + 848 # 03 04 00 00 00 + 849 +-- 26 lines: #? # debug print --------------------------------------------------------------------------------------------------------------------------- + 875 # . flush(_test-output-buffered-file) 876 # . . push args - 877 68/push Newline/imm32 - 878 68/push _test-input-stream/imm32 - 879 # . . call - 880 e8/call write/disp32 - 881 # . . discard args - 882 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 883 # . write(_test-input-stream, "68/push 0x20/imm8") - 884 # . . push args - 885 68/push "68/push 0x20/imm8"/imm32 - 886 68/push _test-input-stream/imm32 + 877 68/push _test-output-buffered-file/imm32 + 878 # . . call + 879 e8/call flush/disp32 + 880 # . . discard args + 881 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 882 # . check-next-stream-line-equal(_test-output-stream, "== code", msg) + 883 # . . push args + 884 68/push "F - test-convert-code-and-data-segments/0"/imm32 + 885 68/push "== code"/imm32 + 886 68/push _test-output-stream/imm32 887 # . . call - 888 e8/call write/disp32 + 888 e8/call check-next-stream-line-equal/disp32 889 # . . discard args - 890 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 891 # . write(_test-input-stream, "\n") + 890 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 891 # . check-next-stream-line-equal(_test-output-stream, "e8 20 00 00 00 # e8/call 20/disp32", msg) 892 # . . push args - 893 68/push Newline/imm32 - 894 68/push _test-input-stream/imm32 - 895 # . . call - 896 e8/call write/disp32 - 897 # . . discard args - 898 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 899 # . write(_test-input-stream, "== data") - 900 # . . push args - 901 68/push "== data"/imm32 - 902 68/push _test-input-stream/imm32 - 903 # . . call - 904 e8/call write/disp32 - 905 # . . discard args - 906 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 907 # . write(_test-input-stream, "\n") - 908 # . . push args - 909 68/push Newline/imm32 - 910 68/push _test-input-stream/imm32 - 911 # . . call - 912 e8/call write/disp32 - 913 # . . discard args - 914 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 915 # . write(_test-input-stream, "3 4/imm32") - 916 # . . push args - 917 68/push "3 4/imm32"/imm32 - 918 68/push _test-input-stream/imm32 - 919 # . . call - 920 e8/call write/disp32 - 921 # . . discard args - 922 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 923 # . write(_test-input-stream, "\n") - 924 # . . push args - 925 68/push Newline/imm32 - 926 68/push _test-input-stream/imm32 - 927 # . . call - 928 e8/call write/disp32 - 929 # . . discard args - 930 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 931 # convert(_test-input-buffered-file, _test-output-buffered-file) - 932 # . . push args - 933 68/push _test-output-buffered-file/imm32 - 934 68/push _test-input-buffered-file/imm32 - 935 # . . call - 936 e8/call convert/disp32 - 937 # . . discard args - 938 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - 939 # check output - 940 # == code - 941 # e8 20 00 00 00 # e8/call 20/disp32 - 942 # 68 20 # 68/push 0x20/imm8 - 943 # == data - 944 # 03 04 00 00 00 - 945 +-- 34 lines: #? # debug print --------------------------------------------------------------------------------------------------------------------------- - 979 # . flush(_test-output-buffered-file) - 980 # . . push args - 981 68/push _test-output-buffered-file/imm32 - 982 # . . call - 983 e8/call flush/disp32 - 984 # . . discard args - 985 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP - 986 # . check-next-stream-line-equal(_test-output-stream, "== code", msg) - 987 # . . push args - 988 68/push "F - test-convert-code-and-data-segments/0"/imm32 - 989 68/push "== code"/imm32 - 990 68/push _test-output-stream/imm32 - 991 # . . call - 992 e8/call check-next-stream-line-equal/disp32 - 993 # . . discard args - 994 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - 995 # . check-next-stream-line-equal(_test-output-stream, "e8 20 00 00 00 # e8/call 20/disp32", msg) - 996 # . . push args - 997 68/push "F - test-convert-code-and-data-segments/1"/imm32 - 998 68/push "e8 20 00 00 00 # e8/call 20/disp32"/imm32 - 999 68/push _test-output-stream/imm32 -1000 # . . call -1001 e8/call check-next-stream-line-equal/disp32 -1002 # . . discard args -1003 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1004 # . check-next-stream-line-equal(_test-output-stream, "68 20 # 68/push 0x20/imm8", msg) -1005 # . . push args -1006 68/push "F - test-convert-code-and-data-segments/2"/imm32 -1007 68/push "68 20 # 68/push 0x20/imm8"/imm32 -1008 68/push _test-output-stream/imm32 -1009 # . . call -1010 e8/call check-next-stream-line-equal/disp32 -1011 # . . discard args -1012 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1013 # . check-next-stream-line-equal(_test-output-stream, "== data", msg) -1014 # . . push args -1015 68/push "F - test-convert-code-and-data-segments/3"/imm32 -1016 68/push "== data"/imm32 -1017 68/push _test-output-stream/imm32 -1018 # . . call -1019 e8/call check-next-stream-line-equal/disp32 -1020 # . . discard args -1021 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1022 # . check-next-stream-line-equal(_test-output-stream, "03 04 00 00 00 ", msg) -1023 # . . push args -1024 68/push "F - test-convert-code-and-data-segments/4"/imm32 -1025 68/push "03 04 00 00 00 "/imm32 -1026 68/push _test-output-stream/imm32 -1027 # . . call -1028 e8/call check-next-stream-line-equal/disp32 -1029 # . . discard args -1030 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1031 # . epilog -1032 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1033 5d/pop-to-EBP -1034 c3/return -1035 -1036 convert-data: # line : (address stream byte), out : (address buffered-file) -> <void> -1037 # pseudocode: -1038 # var word-slice = {0, 0} -1039 # while true -1040 # word-slice = next-word(line) -1041 # if slice-empty?(word-slice) # end of file (maybe including trailing whitespace) -1042 # break # skip emitting some whitespace -1043 # if slice-starts-with?(word-slice, "#") # comment -1044 # write-slice(out, word-slice) -1045 # break -1046 # if slice-ends-with?(word-slice, ":") # label -1047 # write-stream-data(out, line) -1048 # break -1049 # if has-metadata?(word-slice, "imm32") -1050 # emit(out, word-slice, 4) -1051 # # disp32 is not permitted in data segments, and anything else is only a byte long -1052 # else -1053 # emit(out, word-slice, 1) -1054 # -1055 # . prolog -1056 55/push-EBP -1057 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1058 # . save registers -1059 50/push-EAX -1060 51/push-ECX -1061 52/push-EDX -1062 # var word-slice/ECX = {0, 0} -1063 68/push 0/imm32/end -1064 68/push 0/imm32/start -1065 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -1066 +-- 34 lines: #? # dump line ----------------------------------------------------------------------------------------------------------------------------- -1100 $convert-data:loop: -1101 # next-word(line, word-slice) -1102 # . . push args -1103 51/push-ECX -1104 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -1105 # . . call -1106 e8/call next-word/disp32 -1107 # . . discard args -1108 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1109 +-- 50 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- -1159 $convert-data:check0: -1160 # if (slice-empty?(word-slice)) break -1161 # . EAX = slice-empty?(word-slice) + 893 68/push "F - test-convert-code-and-data-segments/1"/imm32 + 894 68/push "e8 20 00 00 00 # e8/call 20/disp32"/imm32 + 895 68/push _test-output-stream/imm32 + 896 # . . call + 897 e8/call check-next-stream-line-equal/disp32 + 898 # . . discard args + 899 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 900 # . check-next-stream-line-equal(_test-output-stream, "68 20 # 68/push 0x20/imm8", msg) + 901 # . . push args + 902 68/push "F - test-convert-code-and-data-segments/2"/imm32 + 903 68/push "68 20 # 68/push 0x20/imm8"/imm32 + 904 68/push _test-output-stream/imm32 + 905 # . . call + 906 e8/call check-next-stream-line-equal/disp32 + 907 # . . discard args + 908 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 909 # . check-next-stream-line-equal(_test-output-stream, "== data", msg) + 910 # . . push args + 911 68/push "F - test-convert-code-and-data-segments/3"/imm32 + 912 68/push "== data"/imm32 + 913 68/push _test-output-stream/imm32 + 914 # . . call + 915 e8/call check-next-stream-line-equal/disp32 + 916 # . . discard args + 917 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 918 # . check-next-stream-line-equal(_test-output-stream, "03 04 00 00 00 ", msg) + 919 # . . push args + 920 68/push "F - test-convert-code-and-data-segments/4"/imm32 + 921 68/push "03 04 00 00 00 "/imm32 + 922 68/push _test-output-stream/imm32 + 923 # . . call + 924 e8/call check-next-stream-line-equal/disp32 + 925 # . . discard args + 926 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 927 # . epilog + 928 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 929 5d/pop-to-EBP + 930 c3/return + 931 + 932 convert-data: # line : (address stream byte), out : (address buffered-file) -> <void> + 933 # pseudocode: + 934 # var word-slice = {0, 0} + 935 # while true + 936 # word-slice = next-word(line) + 937 # if slice-empty?(word-slice) # end of file (maybe including trailing whitespace) + 938 # break # skip emitting some whitespace + 939 # if slice-starts-with?(word-slice, "#") # comment + 940 # write-slice(out, word-slice) + 941 # break + 942 # if slice-ends-with?(word-slice, ":") # label + 943 # write-stream-data(out, line) + 944 # break + 945 # if has-metadata?(word-slice, "imm32") + 946 # emit(out, word-slice, 4) + 947 # # disp32 is not permitted in data segments, and anything else is only a byte long + 948 # else + 949 # emit(out, word-slice, 1) + 950 # + 951 # . prolog + 952 55/push-EBP + 953 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 954 # . save registers + 955 50/push-EAX + 956 51/push-ECX + 957 52/push-EDX + 958 # var word-slice/ECX = {0, 0} + 959 68/push 0/imm32/end + 960 68/push 0/imm32/start + 961 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 962 +-- 26 lines: #? # dump line ----------------------------------------------------------------------------------------------------------------------------- + 988 $convert-data:loop: + 989 # next-word(line, word-slice) + 990 # . . push args + 991 51/push-ECX + 992 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) + 993 # . . call + 994 e8/call next-word/disp32 + 995 # . . discard args + 996 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + 997 +-- 42 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- +1039 $convert-data:check0: +1040 # if (slice-empty?(word-slice)) break +1041 # . EAX = slice-empty?(word-slice) +1042 # . . push args +1043 51/push-ECX +1044 # . . call +1045 e8/call slice-empty?/disp32 +1046 # . . discard args +1047 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1048 # . if (EAX != 0) break +1049 3d/compare-EAX-and 0/imm32 +1050 0f 85/jump-if-not-equal $convert-data:break/disp32 +1051 $convert-data:check-for-comment: +1052 # if (slice-starts-with?(word-slice, "#")) +1053 # . start/EDX = word-slice->start +1054 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX +1055 # . c/EAX = *start +1056 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +1057 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 0/r32/AL . . # copy byte at *EDX to AL +1058 # . if (EAX != '#') goto next check +1059 3d/compare-EAX-and 0x23/imm32/hash +1060 75/jump-if-not-equal $convert-data:check-for-label/disp8 +1061 $convert-data:comment: +1062 # write-slice(out, word-slice) +1063 # . . push args +1064 51/push-ECX +1065 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +1066 # . . call +1067 e8/call write-slice/disp32 +1068 # . . discard args +1069 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1070 # break +1071 75/jump-if-not-equal $convert-data:break/disp8 +1072 $convert-data:check-for-label: +1073 # if (slice-ends-with?(word-slice, ":")) +1074 # . end/EDX = word-slice->end +1075 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 2/r32/EDX 4/disp8 . # copy *(ECX+4) to EDX +1076 # . c/EAX = *(end-1) +1077 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +1078 8a/copy-byte 1/mod/*+disp8 2/rm32/EDX . . . 0/r32/AL -1/disp8 . # copy byte at *ECX to AL +1079 # . if (EAX != ':') goto next check +1080 3d/compare-EAX-and 0x3a/imm32/colon +1081 75/jump-if-not-equal $convert-data:check-for-imm32/disp8 +1082 $convert-data:label: +1083 # write-stream-data(out, line) +1084 # . . push args +1085 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1086 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +1087 # . . call +1088 e8/call write-stream-data/disp32 +1089 # . . discard args +1090 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1091 # break +1092 75/jump-if-not-equal $convert-data:break/disp8 +1093 $convert-data:check-for-imm32: +1094 # if (has-metadata?(word-slice, "imm32")) +1095 # . EAX = has-metadata?(ECX, "imm32") +1096 # . . push args +1097 68/push "imm32"/imm32 +1098 51/push-ECX +1099 # . . call +1100 e8/call has-metadata?/disp32 +1101 # . . discard args +1102 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1103 # . if (EAX == 0) process as a single byte +1104 3d/compare-EAX-and 0/imm32 +1105 74/jump-if-equal $convert-data:single-byte/disp8 +1106 $convert-data:imm32: +1107 # emit(out, word-slice, 4) +1108 # . . push args +1109 68/push 4/imm32 +1110 51/push-ECX +1111 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +1112 # . . call +1113 e8/call emit/disp32 +1114 # . . discard args +1115 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1116 e9/jump $convert-data:loop/disp32 +1117 $convert-data:single-byte: +1118 # emit(out, word-slice, 1) +1119 # . . push args +1120 68/push 1/imm32 +1121 51/push-ECX +1122 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +1123 # . . call +1124 e8/call emit/disp32 +1125 # . . discard args +1126 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1127 e9/jump $convert-data:loop/disp32 +1128 $convert-data:break: +1129 $convert-data:end: +1130 # . reclaim locals +1131 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1132 # . restore registers +1133 5a/pop-to-EDX +1134 59/pop-to-ECX +1135 58/pop-to-EAX +1136 # . epilog +1137 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1138 5d/pop-to-EBP +1139 c3/return +1140 +1141 test-convert-data-passes-comments-through: +1142 # if a line starts with '#', pass it along unchanged +1143 # . prolog +1144 55/push-EBP +1145 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1146 # setup +1147 # . clear-stream(_test-input-stream) +1148 # . . push args +1149 68/push _test-input-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-output-stream) +1155 # . . push args +1156 68/push _test-output-stream/imm32 +1157 # . . call +1158 e8/call clear-stream/disp32 +1159 # . . discard args +1160 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1161 # . clear-stream(_test-output-buffered-file+4) 1162 # . . push args -1163 51/push-ECX -1164 # . . call -1165 e8/call slice-empty?/disp32 -1166 # . . discard args -1167 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1168 # . if (EAX != 0) break -1169 3d/compare-EAX-and 0/imm32 -1170 0f 85/jump-if-not-equal $convert-data:break/disp32 -1171 $convert-data:check-for-comment: -1172 # if (slice-starts-with?(word-slice, "#")) -1173 # . start/EDX = word-slice->start -1174 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX -1175 # . c/EAX = *start -1176 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -1177 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 0/r32/AL . . # copy byte at *EDX to AL -1178 # . if (EAX != '#') goto next check -1179 3d/compare-EAX-and 0x23/imm32/hash -1180 75/jump-if-not-equal $convert-data:check-for-label/disp8 -1181 $convert-data:comment: -1182 # write-slice(out, word-slice) -1183 # . . push args -1184 51/push-ECX -1185 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -1186 # . . call -1187 e8/call write-slice/disp32 -1188 # . . discard args -1189 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1190 # break -1191 75/jump-if-not-equal $convert-data:break/disp8 -1192 $convert-data:check-for-label: -1193 # if (slice-ends-with?(word-slice, ":")) -1194 # . end/EDX = word-slice->end -1195 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 2/r32/EDX 4/disp8 . # copy *(ECX+4) to EDX -1196 # . c/EAX = *(end-1) -1197 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -1198 8a/copy-byte 1/mod/*+disp8 2/rm32/EDX . . . 0/r32/AL -1/disp8 . # copy byte at *ECX to AL -1199 # . if (EAX != ':') goto next check -1200 3d/compare-EAX-and 0x3a/imm32/colon -1201 75/jump-if-not-equal $convert-data:check-for-imm32/disp8 -1202 $convert-data:label: -1203 # write-stream-data(out, line) -1204 # . . push args -1205 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -1206 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -1207 # . . call -1208 e8/call write-stream-data/disp32 -1209 # . . discard args -1210 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1211 # break -1212 75/jump-if-not-equal $convert-data:break/disp8 -1213 $convert-data:check-for-imm32: -1214 # if (has-metadata?(word-slice, "imm32")) -1215 # . EAX = has-metadata?(ECX, "imm32") -1216 # . . push args -1217 68/push "imm32"/imm32 -1218 51/push-ECX -1219 # . . call -1220 e8/call has-metadata?/disp32 -1221 # . . discard args -1222 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1223 # . if (EAX == 0) process as a single byte -1224 3d/compare-EAX-and 0/imm32 -1225 74/jump-if-equal $convert-data:single-byte/disp8 -1226 $convert-data:imm32: -1227 # emit(out, word-slice, 4) -1228 # . . push args -1229 68/push 4/imm32 -1230 51/push-ECX -1231 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -1232 # . . call -1233 e8/call emit/disp32 -1234 # . . discard args -1235 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1236 e9/jump $convert-data:loop/disp32 -1237 $convert-data:single-byte: -1238 # emit(out, word-slice, 1) -1239 # . . push args -1240 68/push 1/imm32 -1241 51/push-ECX -1242 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -1243 # . . call -1244 e8/call emit/disp32 -1245 # . . discard args -1246 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1247 e9/jump $convert-data:loop/disp32 -1248 $convert-data:break: -1249 $convert-data:end: -1250 # . reclaim locals -1251 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1252 # . restore registers -1253 5a/pop-to-EDX -1254 59/pop-to-ECX -1255 58/pop-to-EAX -1256 # . epilog -1257 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1258 5d/pop-to-EBP -1259 c3/return -1260 -1261 test-convert-data-passes-comments-through: -1262 # if a line starts with '#', pass it along unchanged -1263 # . prolog -1264 55/push-EBP -1265 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1266 # setup -1267 # . clear-stream(_test-input-stream) -1268 # . . push args -1269 68/push _test-input-stream/imm32 -1270 # . . call -1271 e8/call clear-stream/disp32 -1272 # . . discard args -1273 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1274 # . clear-stream(_test-output-stream) -1275 # . . push args -1276 68/push _test-output-stream/imm32 +1163 b8/copy-to-EAX _test-output-buffered-file/imm32 +1164 05/add-to-EAX 4/imm32 +1165 50/push-EAX +1166 # . . call +1167 e8/call clear-stream/disp32 +1168 # . . discard args +1169 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1170 # initialize input +1171 # . write(_test-input-stream, "# abcd") +1172 # . . push args +1173 68/push "# abcd"/imm32 +1174 68/push _test-input-stream/imm32 +1175 # . . call +1176 e8/call write/disp32 +1177 # . . discard args +1178 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1179 # convert-data(_test-input-stream, _test-output-buffered-file) +1180 # . . push args +1181 68/push _test-output-buffered-file/imm32 +1182 68/push _test-input-stream/imm32 +1183 # . . call +1184 e8/call convert-data/disp32 +1185 # . . discard args +1186 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1187 # check that the line just passed through +1188 # . flush(_test-output-buffered-file) +1189 # . . push args +1190 68/push _test-output-buffered-file/imm32 +1191 # . . call +1192 e8/call flush/disp32 +1193 # . . discard args +1194 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1195 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +1221 # . check-stream-equal(_test-output-stream, "# abcd", msg) +1222 # . . push args +1223 68/push "F - test-convert-data-passes-comments-through"/imm32 +1224 68/push "# abcd"/imm32 +1225 68/push _test-output-stream/imm32 +1226 # . . call +1227 e8/call check-stream-equal/disp32 +1228 # . . discard args +1229 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1230 # . epilog +1231 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1232 5d/pop-to-EBP +1233 c3/return +1234 +1235 test-convert-data-passes-labels-through: +1236 # if the first word ends with ':', pass along the entire line unchanged +1237 # . prolog +1238 55/push-EBP +1239 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1240 # setup +1241 # . clear-stream(_test-input-stream) +1242 # . . push args +1243 68/push _test-input-stream/imm32 +1244 # . . call +1245 e8/call clear-stream/disp32 +1246 # . . discard args +1247 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1248 # . clear-stream(_test-output-stream) +1249 # . . push args +1250 68/push _test-output-stream/imm32 +1251 # . . call +1252 e8/call clear-stream/disp32 +1253 # . . discard args +1254 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1255 # . clear-stream(_test-output-buffered-file+4) +1256 # . . push args +1257 b8/copy-to-EAX _test-output-buffered-file/imm32 +1258 05/add-to-EAX 4/imm32 +1259 50/push-EAX +1260 # . . call +1261 e8/call clear-stream/disp32 +1262 # . . discard args +1263 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1264 # initialize input +1265 # . write(_test-input-stream, "ab: # cd") +1266 # . . push args +1267 68/push "ab: # cd"/imm32 +1268 68/push _test-input-stream/imm32 +1269 # . . call +1270 e8/call write/disp32 +1271 # . . discard args +1272 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1273 # convert-data(_test-input-stream, _test-output-buffered-file) +1274 # . . push args +1275 68/push _test-output-buffered-file/imm32 +1276 68/push _test-input-stream/imm32 1277 # . . call -1278 e8/call clear-stream/disp32 +1278 e8/call convert-data/disp32 1279 # . . discard args -1280 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1281 # . clear-stream(_test-output-buffered-file+4) -1282 # . . push args -1283 b8/copy-to-EAX _test-output-buffered-file/imm32 -1284 05/add-to-EAX 4/imm32 -1285 50/push-EAX -1286 # . . call -1287 e8/call clear-stream/disp32 -1288 # . . discard args -1289 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1290 # initialize input -1291 # . write(_test-input-stream, "# abcd") -1292 # . . push args -1293 68/push "# abcd"/imm32 -1294 68/push _test-input-stream/imm32 -1295 # . . call -1296 e8/call write/disp32 -1297 # . . discard args -1298 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1299 # convert-data(_test-input-stream, _test-output-buffered-file) -1300 # . . push args -1301 68/push _test-output-buffered-file/imm32 -1302 68/push _test-input-stream/imm32 -1303 # . . call -1304 e8/call convert-data/disp32 -1305 # . . discard args -1306 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1307 # check that the line just passed through -1308 # . flush(_test-output-buffered-file) -1309 # . . push args -1310 68/push _test-output-buffered-file/imm32 -1311 # . . call -1312 e8/call flush/disp32 -1313 # . . discard args -1314 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1315 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -1349 # . check-stream-equal(_test-output-stream, "# abcd", msg) -1350 # . . push args -1351 68/push "F - test-convert-data-passes-comments-through"/imm32 -1352 68/push "# abcd"/imm32 -1353 68/push _test-output-stream/imm32 +1280 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1281 # check that the line just passed through +1282 # . flush(_test-output-buffered-file) +1283 # . . push args +1284 68/push _test-output-buffered-file/imm32 +1285 # . . call +1286 e8/call flush/disp32 +1287 # . . discard args +1288 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1289 # . check-stream-equal(_test-output-stream, "ab: # cd", msg) +1290 # . . push args +1291 68/push "F - test-convert-data-passes-labels-through"/imm32 +1292 68/push "ab: # cd"/imm32 +1293 68/push _test-output-stream/imm32 +1294 # . . call +1295 e8/call check-stream-equal/disp32 +1296 # . . discard args +1297 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1298 # . epilog +1299 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1300 5d/pop-to-EBP +1301 c3/return +1302 +1303 test-convert-data-passes-names-through: +1304 # If a word is a valid name, just emit it unchanged. +1305 # Later phases will deal with it. +1306 # . prolog +1307 55/push-EBP +1308 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1309 # setup +1310 # . clear-stream(_test-input-stream) +1311 # . . push args +1312 68/push _test-input-stream/imm32 +1313 # . . call +1314 e8/call clear-stream/disp32 +1315 # . . discard args +1316 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1317 # . clear-stream(_test-output-stream) +1318 # . . push args +1319 68/push _test-output-stream/imm32 +1320 # . . call +1321 e8/call clear-stream/disp32 +1322 # . . discard args +1323 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1324 # . clear-stream(_test-output-buffered-file+4) +1325 # . . push args +1326 b8/copy-to-EAX _test-output-buffered-file/imm32 +1327 05/add-to-EAX 4/imm32 +1328 50/push-EAX +1329 # . . call +1330 e8/call clear-stream/disp32 +1331 # . . discard args +1332 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1333 # initialize input +1334 # . write(_test-input-stream, "abcd/imm32") +1335 # . . push args +1336 68/push "abcd/imm32"/imm32 +1337 68/push _test-input-stream/imm32 +1338 # . . call +1339 e8/call write/disp32 +1340 # . . discard args +1341 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1342 # convert-data(_test-input-stream, _test-output-buffered-file) +1343 # . . push args +1344 68/push _test-output-buffered-file/imm32 +1345 68/push _test-input-stream/imm32 +1346 # . . call +1347 e8/call convert-data/disp32 +1348 # . . discard args +1349 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1350 # check that the line just passed through +1351 # . flush(_test-output-buffered-file) +1352 # . . push args +1353 68/push _test-output-buffered-file/imm32 1354 # . . call -1355 e8/call check-stream-equal/disp32 +1355 e8/call flush/disp32 1356 # . . discard args -1357 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1358 # . epilog -1359 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1360 5d/pop-to-EBP -1361 c3/return -1362 -1363 test-convert-data-passes-labels-through: -1364 # if the first word ends with ':', pass along the entire line unchanged -1365 # . prolog -1366 55/push-EBP -1367 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1368 # setup -1369 # . clear-stream(_test-input-stream) -1370 # . . push args -1371 68/push _test-input-stream/imm32 -1372 # . . call -1373 e8/call clear-stream/disp32 -1374 # . . discard args -1375 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1376 # . clear-stream(_test-output-stream) -1377 # . . push args -1378 68/push _test-output-stream/imm32 -1379 # . . call -1380 e8/call clear-stream/disp32 -1381 # . . discard args -1382 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1383 # . clear-stream(_test-output-buffered-file+4) -1384 # . . push args -1385 b8/copy-to-EAX _test-output-buffered-file/imm32 -1386 05/add-to-EAX 4/imm32 -1387 50/push-EAX +1357 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1358 # . check-stream-equal(_test-output-stream, "abcd/imm32", msg) +1359 # . . push args +1360 68/push "F - test-convert-data-passes-names-through"/imm32 +1361 68/push "abcd/imm32 "/imm32 +1362 68/push _test-output-stream/imm32 +1363 # . . call +1364 e8/call check-stream-equal/disp32 +1365 # . . discard args +1366 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1367 # . epilog +1368 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1369 5d/pop-to-EBP +1370 c3/return +1371 +1372 test-convert-data-handles-imm32: +1373 # If a word has the /imm32 metadata, emit it in 4 bytes. +1374 # . prolog +1375 55/push-EBP +1376 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1377 # setup +1378 # . clear-stream(_test-input-stream) +1379 # . . push args +1380 68/push _test-input-stream/imm32 +1381 # . . call +1382 e8/call clear-stream/disp32 +1383 # . . discard args +1384 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1385 # . clear-stream(_test-output-stream) +1386 # . . push args +1387 68/push _test-output-stream/imm32 1388 # . . call 1389 e8/call clear-stream/disp32 1390 # . . discard args 1391 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1392 # initialize input -1393 # . write(_test-input-stream, "ab: # cd") -1394 # . . push args -1395 68/push "ab: # cd"/imm32 -1396 68/push _test-input-stream/imm32 +1392 # . clear-stream(_test-output-buffered-file+4) +1393 # . . push args +1394 b8/copy-to-EAX _test-output-buffered-file/imm32 +1395 05/add-to-EAX 4/imm32 +1396 50/push-EAX 1397 # . . call -1398 e8/call write/disp32 +1398 e8/call clear-stream/disp32 1399 # . . discard args -1400 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1401 # convert-data(_test-input-stream, _test-output-buffered-file) -1402 # . . push args -1403 68/push _test-output-buffered-file/imm32 -1404 68/push _test-input-stream/imm32 -1405 # . . call -1406 e8/call convert-data/disp32 -1407 # . . discard args -1408 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1409 # check that the line just passed through -1410 # . flush(_test-output-buffered-file) +1400 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1401 # initialize input +1402 # . write(_test-input-stream, "30/imm32") +1403 # . . push args +1404 68/push "30/imm32"/imm32 +1405 68/push _test-input-stream/imm32 +1406 # . . call +1407 e8/call write/disp32 +1408 # . . discard args +1409 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1410 # convert-data(_test-input-stream, _test-output-buffered-file) 1411 # . . push args -1412 68/push _test-output-buffered-file/imm32 -1413 # . . call -1414 e8/call flush/disp32 -1415 # . . discard args -1416 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1417 # . check-stream-equal(_test-output-stream, "ab: # cd", msg) -1418 # . . push args -1419 68/push "F - test-convert-data-passes-labels-through"/imm32 -1420 68/push "ab: # cd"/imm32 -1421 68/push _test-output-stream/imm32 +1412 68/push _test-output-buffered-file/imm32 +1413 68/push _test-input-stream/imm32 +1414 # . . call +1415 e8/call convert-data/disp32 +1416 # . . discard args +1417 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1418 # check that 4 bytes were written +1419 # . flush(_test-output-buffered-file) +1420 # . . push args +1421 68/push _test-output-buffered-file/imm32 1422 # . . call -1423 e8/call check-stream-equal/disp32 +1423 e8/call flush/disp32 1424 # . . discard args -1425 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1426 # . epilog -1427 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1428 5d/pop-to-EBP -1429 c3/return -1430 -1431 test-convert-data-passes-names-through: -1432 # If a word is a valid name, just emit it unchanged. -1433 # Later phases will deal with it. -1434 # . prolog -1435 55/push-EBP -1436 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1437 # setup -1438 # . clear-stream(_test-input-stream) -1439 # . . push args -1440 68/push _test-input-stream/imm32 -1441 # . . call -1442 e8/call clear-stream/disp32 -1443 # . . discard args -1444 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1445 # . clear-stream(_test-output-stream) -1446 # . . push args -1447 68/push _test-output-stream/imm32 -1448 # . . call -1449 e8/call clear-stream/disp32 -1450 # . . discard args -1451 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1452 # . clear-stream(_test-output-buffered-file+4) -1453 # . . push args -1454 b8/copy-to-EAX _test-output-buffered-file/imm32 -1455 05/add-to-EAX 4/imm32 -1456 50/push-EAX +1425 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1426 # . check-stream-equal(_test-output-stream, "30 00 00 00 ", msg) +1427 # . . push args +1428 68/push "F - test-convert-data-handles-imm32"/imm32 +1429 68/push "30 00 00 00 "/imm32 +1430 68/push _test-output-stream/imm32 +1431 # . . call +1432 e8/call check-stream-equal/disp32 +1433 # . . discard args +1434 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1435 # . epilog +1436 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1437 5d/pop-to-EBP +1438 c3/return +1439 +1440 test-convert-data-handles-single-byte: +1441 # Any metadata but /imm32 will emit a single byte. +1442 # Data segments can't have /disp32, and SubX doesn't support 16-bit operands. +1443 # . prolog +1444 55/push-EBP +1445 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1446 # setup +1447 # . clear-stream(_test-input-stream) +1448 # . . push args +1449 68/push _test-input-stream/imm32 +1450 # . . call +1451 e8/call clear-stream/disp32 +1452 # . . discard args +1453 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1454 # . clear-stream(_test-output-stream) +1455 # . . push args +1456 68/push _test-output-stream/imm32 1457 # . . call 1458 e8/call clear-stream/disp32 1459 # . . discard args 1460 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1461 # initialize input -1462 # . write(_test-input-stream, "abcd/imm32") -1463 # . . push args -1464 68/push "abcd/imm32"/imm32 -1465 68/push _test-input-stream/imm32 +1461 # . clear-stream(_test-output-buffered-file+4) +1462 # . . push args +1463 b8/copy-to-EAX _test-output-buffered-file/imm32 +1464 05/add-to-EAX 4/imm32 +1465 50/push-EAX 1466 # . . call -1467 e8/call write/disp32 +1467 e8/call clear-stream/disp32 1468 # . . discard args -1469 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1470 # convert-data(_test-input-stream, _test-output-buffered-file) -1471 # . . push args -1472 68/push _test-output-buffered-file/imm32 -1473 68/push _test-input-stream/imm32 -1474 # . . call -1475 e8/call convert-data/disp32 -1476 # . . discard args -1477 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1478 # check that the line just passed through -1479 # . flush(_test-output-buffered-file) +1469 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1470 # initialize input +1471 # . write(_test-input-stream, "30/imm16") +1472 # . . push args +1473 68/push "30/imm16"/imm32 +1474 68/push _test-input-stream/imm32 +1475 # . . call +1476 e8/call write/disp32 +1477 # . . discard args +1478 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1479 # convert-data(_test-input-stream, _test-output-buffered-file) 1480 # . . push args -1481 68/push _test-output-buffered-file/imm32 -1482 # . . call -1483 e8/call flush/disp32 -1484 # . . discard args -1485 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1486 # . check-stream-equal(_test-output-stream, "abcd/imm32", msg) -1487 # . . push args -1488 68/push "F - test-convert-data-passes-names-through"/imm32 -1489 68/push "abcd/imm32 "/imm32 -1490 68/push _test-output-stream/imm32 +1481 68/push _test-output-buffered-file/imm32 +1482 68/push _test-input-stream/imm32 +1483 # . . call +1484 e8/call convert-data/disp32 +1485 # . . discard args +1486 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1487 # check that a single byte was written (imm16 is not a valid operand type) +1488 # . flush(_test-output-buffered-file) +1489 # . . push args +1490 68/push _test-output-buffered-file/imm32 1491 # . . call -1492 e8/call check-stream-equal/disp32 +1492 e8/call flush/disp32 1493 # . . discard args -1494 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1495 # . epilog -1496 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1497 5d/pop-to-EBP -1498 c3/return -1499 -1500 test-convert-data-handles-imm32: -1501 # If a word has the /imm32 metadata, emit it in 4 bytes. -1502 # . prolog -1503 55/push-EBP -1504 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1505 # setup -1506 # . clear-stream(_test-input-stream) -1507 # . . push args -1508 68/push _test-input-stream/imm32 -1509 # . . call -1510 e8/call clear-stream/disp32 -1511 # . . discard args -1512 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1513 # . clear-stream(_test-output-stream) -1514 # . . push args -1515 68/push _test-output-stream/imm32 -1516 # . . call -1517 e8/call clear-stream/disp32 -1518 # . . discard args -1519 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1520 # . clear-stream(_test-output-buffered-file+4) -1521 # . . push args -1522 b8/copy-to-EAX _test-output-buffered-file/imm32 -1523 05/add-to-EAX 4/imm32 -1524 50/push-EAX +1494 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1495 # . check-stream-equal(_test-output-stream, "30 ", msg) +1496 # . . push args +1497 68/push "F - test-convert-data-handles-single-byte"/imm32 +1498 68/push "30 "/imm32 +1499 68/push _test-output-stream/imm32 +1500 # . . call +1501 e8/call check-stream-equal/disp32 +1502 # . . discard args +1503 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1504 # . epilog +1505 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1506 5d/pop-to-EBP +1507 c3/return +1508 +1509 test-convert-data-multiple-bytes: +1510 # Multiple single-byte words in input stream get processed one by one. +1511 # . prolog +1512 55/push-EBP +1513 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1514 # setup +1515 # . clear-stream(_test-input-stream) +1516 # . . push args +1517 68/push _test-input-stream/imm32 +1518 # . . call +1519 e8/call clear-stream/disp32 +1520 # . . discard args +1521 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1522 # . clear-stream(_test-output-stream) +1523 # . . push args +1524 68/push _test-output-stream/imm32 1525 # . . call 1526 e8/call clear-stream/disp32 1527 # . . discard args 1528 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1529 # initialize input -1530 # . write(_test-input-stream, "30/imm32") -1531 # . . push args -1532 68/push "30/imm32"/imm32 -1533 68/push _test-input-stream/imm32 +1529 # . clear-stream(_test-output-buffered-file+4) +1530 # . . push args +1531 b8/copy-to-EAX _test-output-buffered-file/imm32 +1532 05/add-to-EAX 4/imm32 +1533 50/push-EAX 1534 # . . call -1535 e8/call write/disp32 +1535 e8/call clear-stream/disp32 1536 # . . discard args -1537 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1538 # convert-data(_test-input-stream, _test-output-buffered-file) -1539 # . . push args -1540 68/push _test-output-buffered-file/imm32 -1541 68/push _test-input-stream/imm32 -1542 # . . call -1543 e8/call convert-data/disp32 -1544 # . . discard args -1545 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1546 # check that 4 bytes were written -1547 # . flush(_test-output-buffered-file) +1537 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1538 # initialize input +1539 # . write(_test-input-stream, "1 2") +1540 # . . push args +1541 68/push "1 2"/imm32 +1542 68/push _test-input-stream/imm32 +1543 # . . call +1544 e8/call write/disp32 +1545 # . . discard args +1546 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1547 # convert-data(_test-input-stream, _test-output-buffered-file) 1548 # . . push args -1549 68/push _test-output-buffered-file/imm32 -1550 # . . call -1551 e8/call flush/disp32 -1552 # . . discard args -1553 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1554 # . check-stream-equal(_test-output-stream, "30 00 00 00 ", msg) -1555 # . . push args -1556 68/push "F - test-convert-data-handles-imm32"/imm32 -1557 68/push "30 00 00 00 "/imm32 -1558 68/push _test-output-stream/imm32 +1549 68/push _test-output-buffered-file/imm32 +1550 68/push _test-input-stream/imm32 +1551 # . . call +1552 e8/call convert-data/disp32 +1553 # . . discard args +1554 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1555 # check output +1556 # . flush(_test-output-buffered-file) +1557 # . . push args +1558 68/push _test-output-buffered-file/imm32 1559 # . . call -1560 e8/call check-stream-equal/disp32 +1560 e8/call flush/disp32 1561 # . . discard args -1562 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1563 # . epilog -1564 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1565 5d/pop-to-EBP -1566 c3/return -1567 -1568 test-convert-data-handles-single-byte: -1569 # Any metadata but /imm32 will emit a single byte. -1570 # Data segments can't have /disp32, and SubX doesn't support 16-bit operands. -1571 # . prolog -1572 55/push-EBP -1573 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1574 # setup -1575 # . clear-stream(_test-input-stream) -1576 # . . push args -1577 68/push _test-input-stream/imm32 -1578 # . . call -1579 e8/call clear-stream/disp32 -1580 # . . discard args -1581 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1582 # . clear-stream(_test-output-stream) -1583 # . . push args -1584 68/push _test-output-stream/imm32 -1585 # . . call -1586 e8/call clear-stream/disp32 -1587 # . . discard args -1588 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1589 # . clear-stream(_test-output-buffered-file+4) -1590 # . . push args -1591 b8/copy-to-EAX _test-output-buffered-file/imm32 -1592 05/add-to-EAX 4/imm32 -1593 50/push-EAX -1594 # . . call -1595 e8/call clear-stream/disp32 -1596 # . . discard args -1597 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1598 # initialize input -1599 # . write(_test-input-stream, "30/imm16") -1600 # . . push args -1601 68/push "30/imm16"/imm32 -1602 68/push _test-input-stream/imm32 -1603 # . . call -1604 e8/call write/disp32 -1605 # . . discard args -1606 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1607 # convert-data(_test-input-stream, _test-output-buffered-file) +1562 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1563 # . check-stream-equal(_test-output-stream, "01 02 ", msg) +1564 # . . push args +1565 68/push "F - test-convert-data-multiple-bytes"/imm32 +1566 68/push "01 02 "/imm32 +1567 68/push _test-output-stream/imm32 +1568 # . . call +1569 e8/call check-stream-equal/disp32 +1570 # . . discard args +1571 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1572 # . epilog +1573 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1574 5d/pop-to-EBP +1575 c3/return +1576 +1577 test-convert-data-byte-then-name: +1578 # Single-byte word followed by valid name get processed one by one. +1579 # . prolog +1580 55/push-EBP +1581 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1582 # setup +1583 # . clear-stream(_test-input-stream) +1584 # . . push args +1585 68/push _test-input-stream/imm32 +1586 # . . call +1587 e8/call clear-stream/disp32 +1588 # . . discard args +1589 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1590 # . clear-stream(_test-output-stream) +1591 # . . push args +1592 68/push _test-output-stream/imm32 +1593 # . . call +1594 e8/call clear-stream/disp32 +1595 # . . discard args +1596 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1597 # . clear-stream(_test-output-buffered-file+4) +1598 # . . push args +1599 b8/copy-to-EAX _test-output-buffered-file/imm32 +1600 05/add-to-EAX 4/imm32 +1601 50/push-EAX +1602 # . . call +1603 e8/call clear-stream/disp32 +1604 # . . discard args +1605 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1606 # initialize input +1607 # . write(_test-input-stream, "30 abcd/o") 1608 # . . push args -1609 68/push _test-output-buffered-file/imm32 -1610 68/push _test-input-stream/imm32 +1609 68/push "30 abcd/o"/imm32 +1610 68/push _test-input-stream/imm32 1611 # . . call -1612 e8/call convert-data/disp32 +1612 e8/call write/disp32 1613 # . . discard args 1614 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1615 # check that a single byte was written (imm16 is not a valid operand type) -1616 # . flush(_test-output-buffered-file) -1617 # . . push args -1618 68/push _test-output-buffered-file/imm32 +1615 # convert-data(_test-input-stream, _test-output-buffered-file) +1616 # . . push args +1617 68/push _test-output-buffered-file/imm32 +1618 68/push _test-input-stream/imm32 1619 # . . call -1620 e8/call flush/disp32 +1620 e8/call convert-data/disp32 1621 # . . discard args -1622 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1623 # . check-stream-equal(_test-output-stream, "30 ", msg) -1624 # . . push args -1625 68/push "F - test-convert-data-handles-single-byte"/imm32 -1626 68/push "30 "/imm32 -1627 68/push _test-output-stream/imm32 -1628 # . . call -1629 e8/call check-stream-equal/disp32 -1630 # . . discard args -1631 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1632 # . epilog -1633 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1634 5d/pop-to-EBP -1635 c3/return -1636 -1637 test-convert-data-multiple-bytes: -1638 # Multiple single-byte words in input stream get processed one by one. -1639 # . prolog -1640 55/push-EBP -1641 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1642 # setup -1643 # . clear-stream(_test-input-stream) -1644 # . . push args -1645 68/push _test-input-stream/imm32 -1646 # . . call -1647 e8/call clear-stream/disp32 -1648 # . . discard args -1649 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1650 # . clear-stream(_test-output-stream) -1651 # . . push args -1652 68/push _test-output-stream/imm32 -1653 # . . call -1654 e8/call clear-stream/disp32 -1655 # . . discard args -1656 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1657 # . clear-stream(_test-output-buffered-file+4) -1658 # . . push args -1659 b8/copy-to-EAX _test-output-buffered-file/imm32 -1660 05/add-to-EAX 4/imm32 -1661 50/push-EAX -1662 # . . call -1663 e8/call clear-stream/disp32 -1664 # . . discard args -1665 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1666 # initialize input -1667 # . write(_test-input-stream, "1 2") -1668 # . . push args -1669 68/push "1 2"/imm32 -1670 68/push _test-input-stream/imm32 -1671 # . . call -1672 e8/call write/disp32 -1673 # . . discard args -1674 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1675 # convert-data(_test-input-stream, _test-output-buffered-file) +1622 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1623 # check output +1624 # . flush(_test-output-buffered-file) +1625 # . . push args +1626 68/push _test-output-buffered-file/imm32 +1627 # . . call +1628 e8/call flush/disp32 +1629 # . . discard args +1630 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1631 # . check-stream-equal(_test-output-stream, "30 abcd/o ", msg) +1632 # . . push args +1633 68/push "F - test-convert-data-byte-then-name"/imm32 +1634 68/push "30 abcd/o "/imm32 +1635 68/push _test-output-stream/imm32 +1636 # . . call +1637 e8/call check-stream-equal/disp32 +1638 # . . discard args +1639 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1640 # . epilog +1641 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1642 5d/pop-to-EBP +1643 c3/return +1644 +1645 test-convert-data-multiple-words: +1646 # Multiple words in input stream get processed one by one. +1647 # . prolog +1648 55/push-EBP +1649 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1650 # setup +1651 # . clear-stream(_test-input-stream) +1652 # . . push args +1653 68/push _test-input-stream/imm32 +1654 # . . call +1655 e8/call clear-stream/disp32 +1656 # . . discard args +1657 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1658 # . clear-stream(_test-output-stream) +1659 # . . push args +1660 68/push _test-output-stream/imm32 +1661 # . . call +1662 e8/call clear-stream/disp32 +1663 # . . discard args +1664 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1665 # . clear-stream(_test-output-buffered-file+4) +1666 # . . push args +1667 b8/copy-to-EAX _test-output-buffered-file/imm32 +1668 05/add-to-EAX 4/imm32 +1669 50/push-EAX +1670 # . . call +1671 e8/call clear-stream/disp32 +1672 # . . discard args +1673 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1674 # initialize input +1675 # . write(_test-input-stream, "30 abcd/o 42e1/imm32") 1676 # . . push args -1677 68/push _test-output-buffered-file/imm32 -1678 68/push _test-input-stream/imm32 +1677 68/push "30 abcd/o 42e1/imm32"/imm32 +1678 68/push _test-input-stream/imm32 1679 # . . call -1680 e8/call convert-data/disp32 +1680 e8/call write/disp32 1681 # . . discard args 1682 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1683 # check output -1684 # . flush(_test-output-buffered-file) -1685 # . . push args -1686 68/push _test-output-buffered-file/imm32 +1683 # convert-data(_test-input-stream, _test-output-buffered-file) +1684 # . . push args +1685 68/push _test-output-buffered-file/imm32 +1686 68/push _test-input-stream/imm32 1687 # . . call -1688 e8/call flush/disp32 +1688 e8/call convert-data/disp32 1689 # . . discard args -1690 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1691 # . check-stream-equal(_test-output-stream, "01 02 ", msg) -1692 # . . push args -1693 68/push "F - test-convert-data-multiple-bytes"/imm32 -1694 68/push "01 02 "/imm32 -1695 68/push _test-output-stream/imm32 -1696 # . . call -1697 e8/call check-stream-equal/disp32 -1698 # . . discard args -1699 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1700 # . epilog -1701 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1702 5d/pop-to-EBP -1703 c3/return -1704 -1705 test-convert-data-byte-then-name: -1706 # Single-byte word followed by valid name get processed one by one. -1707 # . prolog -1708 55/push-EBP -1709 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1710 # setup -1711 # . clear-stream(_test-input-stream) -1712 # . . push args -1713 68/push _test-input-stream/imm32 -1714 # . . call -1715 e8/call clear-stream/disp32 -1716 # . . discard args -1717 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1718 # . clear-stream(_test-output-stream) -1719 # . . push args -1720 68/push _test-output-stream/imm32 -1721 # . . call -1722 e8/call clear-stream/disp32 -1723 # . . discard args -1724 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1725 # . clear-stream(_test-output-buffered-file+4) +1690 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1691 # check output +1692 # . flush(_test-output-buffered-file) +1693 # . . push args +1694 68/push _test-output-buffered-file/imm32 +1695 # . . call +1696 e8/call flush/disp32 +1697 # . . discard args +1698 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1699 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +1725 # . check-stream-equal(_test-output-stream, "30 abcd/o 42 e1 00 00 ", msg) 1726 # . . push args -1727 b8/copy-to-EAX _test-output-buffered-file/imm32 -1728 05/add-to-EAX 4/imm32 -1729 50/push-EAX +1727 68/push "F - test-convert-data-multiple-words"/imm32 +1728 68/push "30 abcd/o e1 42 00 00 "/imm32 +1729 68/push _test-output-stream/imm32 1730 # . . call -1731 e8/call clear-stream/disp32 +1731 e8/call check-stream-equal/disp32 1732 # . . discard args -1733 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1734 # initialize input -1735 # . write(_test-input-stream, "30 abcd/o") -1736 # . . push args -1737 68/push "30 abcd/o"/imm32 -1738 68/push _test-input-stream/imm32 -1739 # . . call -1740 e8/call write/disp32 -1741 # . . discard args -1742 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1743 # convert-data(_test-input-stream, _test-output-buffered-file) -1744 # . . push args -1745 68/push _test-output-buffered-file/imm32 -1746 68/push _test-input-stream/imm32 -1747 # . . call -1748 e8/call convert-data/disp32 -1749 # . . discard args -1750 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1751 # check output -1752 # . flush(_test-output-buffered-file) +1733 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1734 # . epilog +1735 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1736 5d/pop-to-EBP +1737 c3/return +1738 +1739 test-convert-data-trailing-comment: +1740 # Trailing comments in data segment get appropriately ignored. +1741 # . prolog +1742 55/push-EBP +1743 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1744 # setup +1745 # . clear-stream(_test-input-stream) +1746 # . . push args +1747 68/push _test-input-stream/imm32 +1748 # . . call +1749 e8/call clear-stream/disp32 +1750 # . . discard args +1751 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1752 # . clear-stream(_test-output-stream) 1753 # . . push args -1754 68/push _test-output-buffered-file/imm32 +1754 68/push _test-output-stream/imm32 1755 # . . call -1756 e8/call flush/disp32 +1756 e8/call clear-stream/disp32 1757 # . . discard args 1758 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1759 # . check-stream-equal(_test-output-stream, "30 abcd/o ", msg) +1759 # . clear-stream(_test-output-buffered-file+4) 1760 # . . push args -1761 68/push "F - test-convert-data-byte-then-name"/imm32 -1762 68/push "30 abcd/o "/imm32 -1763 68/push _test-output-stream/imm32 +1761 b8/copy-to-EAX _test-output-buffered-file/imm32 +1762 05/add-to-EAX 4/imm32 +1763 50/push-EAX 1764 # . . call -1765 e8/call check-stream-equal/disp32 +1765 e8/call clear-stream/disp32 1766 # . . discard args -1767 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1768 # . epilog -1769 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1770 5d/pop-to-EBP -1771 c3/return -1772 -1773 test-convert-data-multiple-words: -1774 # Multiple words in input stream get processed one by one. -1775 # . prolog -1776 55/push-EBP -1777 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1778 # setup -1779 # . clear-stream(_test-input-stream) -1780 # . . push args -1781 68/push _test-input-stream/imm32 -1782 # . . call -1783 e8/call clear-stream/disp32 -1784 # . . discard args -1785 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1786 # . clear-stream(_test-output-stream) +1767 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1768 # initialize input +1769 # . write(_test-input-stream, "30/imm32 # comment") +1770 # . . push args +1771 68/push "30/imm32 # comment"/imm32 +1772 68/push _test-input-stream/imm32 +1773 # . . call +1774 e8/call write/disp32 +1775 # . . discard args +1776 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1777 # convert-data(_test-input-stream, _test-output-buffered-file) +1778 # . . push args +1779 68/push _test-output-buffered-file/imm32 +1780 68/push _test-input-stream/imm32 +1781 # . . call +1782 e8/call convert-data/disp32 +1783 # . . discard args +1784 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1785 # check output +1786 # . flush(_test-output-buffered-file) 1787 # . . push args -1788 68/push _test-output-stream/imm32 +1788 68/push _test-output-buffered-file/imm32 1789 # . . call -1790 e8/call clear-stream/disp32 +1790 e8/call flush/disp32 1791 # . . discard args 1792 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1793 # . clear-stream(_test-output-buffered-file+4) -1794 # . . push args -1795 b8/copy-to-EAX _test-output-buffered-file/imm32 -1796 05/add-to-EAX 4/imm32 -1797 50/push-EAX -1798 # . . call -1799 e8/call clear-stream/disp32 -1800 # . . discard args -1801 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1802 # initialize input -1803 # . write(_test-input-stream, "30 abcd/o 42e1/imm32") -1804 # . . push args -1805 68/push "30 abcd/o 42e1/imm32"/imm32 -1806 68/push _test-input-stream/imm32 -1807 # . . call -1808 e8/call write/disp32 -1809 # . . discard args -1810 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1811 # convert-data(_test-input-stream, _test-output-buffered-file) -1812 # . . push args -1813 68/push _test-output-buffered-file/imm32 -1814 68/push _test-input-stream/imm32 -1815 # . . call -1816 e8/call convert-data/disp32 -1817 # . . discard args -1818 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1819 # check output -1820 # . flush(_test-output-buffered-file) -1821 # . . push args -1822 68/push _test-output-buffered-file/imm32 -1823 # . . call -1824 e8/call flush/disp32 -1825 # . . discard args -1826 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1827 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -1861 # . check-stream-equal(_test-output-stream, "30 abcd/o 42 e1 00 00 ", msg) -1862 # . . push args -1863 68/push "F - test-convert-data-multiple-words"/imm32 -1864 68/push "30 abcd/o e1 42 00 00 "/imm32 -1865 68/push _test-output-stream/imm32 -1866 # . . call -1867 e8/call check-stream-equal/disp32 -1868 # . . discard args -1869 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1870 # . epilog -1871 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1872 5d/pop-to-EBP -1873 c3/return -1874 -1875 test-convert-data-trailing-comment: -1876 # Trailing comments in data segment get appropriately ignored. -1877 # . prolog -1878 55/push-EBP -1879 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -1880 # setup -1881 # . clear-stream(_test-input-stream) -1882 # . . push args -1883 68/push _test-input-stream/imm32 -1884 # . . call -1885 e8/call clear-stream/disp32 -1886 # . . discard args -1887 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1888 # . clear-stream(_test-output-stream) -1889 # . . push args -1890 68/push _test-output-stream/imm32 -1891 # . . call -1892 e8/call clear-stream/disp32 -1893 # . . discard args -1894 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1895 # . clear-stream(_test-output-buffered-file+4) -1896 # . . push args -1897 b8/copy-to-EAX _test-output-buffered-file/imm32 -1898 05/add-to-EAX 4/imm32 -1899 50/push-EAX -1900 # . . call -1901 e8/call clear-stream/disp32 -1902 # . . discard args -1903 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1904 # initialize input -1905 # . write(_test-input-stream, "30/imm32 # comment") -1906 # . . push args -1907 68/push "30/imm32 # comment"/imm32 -1908 68/push _test-input-stream/imm32 -1909 # . . call -1910 e8/call write/disp32 -1911 # . . discard args -1912 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1913 # convert-data(_test-input-stream, _test-output-buffered-file) -1914 # . . push args -1915 68/push _test-output-buffered-file/imm32 -1916 68/push _test-input-stream/imm32 -1917 # . . call -1918 e8/call convert-data/disp32 -1919 # . . discard args -1920 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -1921 # check output -1922 # . flush(_test-output-buffered-file) -1923 # . . push args -1924 68/push _test-output-buffered-file/imm32 -1925 # . . call -1926 e8/call flush/disp32 -1927 # . . discard args -1928 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -1929 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -1963 # . check-stream-equal(_test-output-stream, "30 00 00 00 # comment", msg) -1964 # . . push args -1965 68/push "F - test-convert-data-trailing-comment"/imm32 -1966 68/push "30 00 00 00 # comment"/imm32 -1967 68/push _test-output-stream/imm32 -1968 # . . call -1969 e8/call check-stream-equal/disp32 -1970 # . . discard args -1971 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -1972 # . epilog -1973 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -1974 5d/pop-to-EBP -1975 c3/return -1976 -1977 # pack an instruction, following the C++ version -1978 # -1979 # zero error handling at the moment (continuing to rely on the C++ version for that): -1980 # missing fields are always 0-filled -1981 # bytes never mentioned are silently dropped; if you don't provide /mod, /rm32 or /r32 you don't get a 0 ModR/M byte. You get *no* ModR/M byte. -1982 # may pick up any of duplicate operands in an instruction -1983 # silently drop extraneous operands -1984 # unceremoniously abort on non-numeric operands except disp or imm -1985 # opcodes must be lowercase and zero padded -1986 # opcodes with misleading operand metadata may get duplicated as operands as well. don't rely on this. -1987 convert-instruction: # line : (address stream byte), out : (address buffered-file) -> <void> -1988 # pseudocode: -1989 # # some early exits -1990 # var word-slice = next-word(line) -1991 # if slice-empty?(word-slice) -1992 # write-stream-data(out, line) -1993 # return -1994 # if slice-starts-with?(word-slice, "#") -1995 # write-stream-data(out, line) -1996 # return -1997 # if slice-ends-with?(word-slice, ":") -1998 # write-stream-data(out, line) -1999 # return -2000 # # really convert -2001 # emit-opcodes(line, out) -2002 # emit-modrm(line, out) -2003 # emit-sib(line, out) -2004 # emit-disp(line, out) -2005 # emit-imm(line, out) -2006 # emit-line-in-comment(line, out) -2007 # -2008 # . prolog -2009 55/push-EBP -2010 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -2011 # . save registers -2012 50/push-EAX -2013 51/push-ECX -2014 52/push-EDX -2015 # var word-slice/ECX = {0, 0} -2016 68/push 0/imm32/end -2017 68/push 0/imm32/start -2018 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -2019 # next-word(line, word-slice) -2020 # . . push args -2021 51/push-ECX -2022 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2023 # . . call -2024 e8/call next-word/disp32 -2025 # . . discard args -2026 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2027 $convert-instruction:check0: -2028 # if (slice-empty?(word-slice)) break -2029 # . EAX = slice-empty?(word-slice) -2030 # . . push args -2031 51/push-ECX -2032 # . . call -2033 e8/call slice-empty?/disp32 -2034 # . . discard args -2035 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2036 # . if (EAX != 0) pass through -2037 3d/compare-EAX-and 0/imm32 -2038 75/jump-if-not-equal $convert-instruction:pass-through/disp8 -2039 $convert-instruction:check1: -2040 # if (slice-starts-with?(word-slice, "#")) write-stream-data(out, line) -2041 # . start/EDX = word-slice->start -2042 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX -2043 # . c/EAX = *start -2044 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -2045 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 0/r32/AL . . # copy byte at *EDX to AL -2046 # . if (EAX == '#') pass through -2047 3d/compare-EAX-and 0x23/imm32/hash -2048 74/jump-if-equal $convert-instruction:pass-through/disp8 -2049 $convert-instruction:check2: -2050 # if (slice-ends-with?(word-slice, ":")) write-stream-data(out, line) -2051 # . end/EDX = word-slice->end -2052 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 2/r32/EDX 4/disp8 . # copy *(ECX+4) to EDX -2053 # . c/EAX = *(end-1) -2054 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -2055 8a/copy-byte 1/mod/*+disp8 2/rm32/EDX . . . 0/r32/AL -1/disp8 . # copy byte at *ECX to AL -2056 # . if (EAX == ':') pass through -2057 3d/compare-EAX-and 0x3a/imm32/colon -2058 75/jump-if-not-equal $convert-instruction:really-convert/disp8 -2059 $convert-instruction:pass-through: -2060 # write-stream-data(out, line) -2061 # . . push args -2062 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2063 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -2064 # . . call -2065 e8/call write-stream-data/disp32 -2066 # . . discard args -2067 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2068 # return -2069 eb/jump $convert-instruction:end/disp8 -2070 $convert-instruction:really-convert: -2071 # emit-opcodes(line, out) -2072 # . . push args -2073 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+8) -2074 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2075 # . . call -2076 e8/call emit-opcodes/disp32 -2077 # . . discard args -2078 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2079 # emit-modrm(line, out) -2080 # . . push args -2081 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+8) -2082 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2083 # . . call -2084 e8/call emit-modrm/disp32 -2085 # . . discard args -2086 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2087 # emit-sib(line, out) -2088 # . . push args -2089 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+8) -2090 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2091 # . . call -2092 e8/call emit-sib/disp32 -2093 # . . discard args -2094 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2095 # emit-disp(line, out) -2096 # . . push args -2097 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+8) -2098 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2099 # . . call -2100 e8/call emit-disp/disp32 -2101 # . . discard args -2102 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2103 # emit-imm(line, out) -2104 # . . push args -2105 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+8) -2106 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2107 # . . call -2108 e8/call emit-imm/disp32 -2109 # . . discard args -2110 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2111 # emit-line-in-comment(line, out) +1793 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +1819 # . check-stream-equal(_test-output-stream, "30 00 00 00 # comment", msg) +1820 # . . push args +1821 68/push "F - test-convert-data-trailing-comment"/imm32 +1822 68/push "30 00 00 00 # comment"/imm32 +1823 68/push _test-output-stream/imm32 +1824 # . . call +1825 e8/call check-stream-equal/disp32 +1826 # . . discard args +1827 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +1828 # . epilog +1829 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1830 5d/pop-to-EBP +1831 c3/return +1832 +1833 # pack an instruction, following the C++ version +1834 # +1835 # zero error handling at the moment (continuing to rely on the C++ version for that): +1836 # missing fields are always 0-filled +1837 # bytes never mentioned are silently dropped; if you don't provide /mod, /rm32 or /r32 you don't get a 0 ModR/M byte. You get *no* ModR/M byte. +1838 # may pick up any of duplicate operands in an instruction +1839 # silently drop extraneous operands +1840 # unceremoniously abort on non-numeric operands except disp or imm +1841 # opcodes must be lowercase and zero padded +1842 # opcodes with misleading operand metadata may get duplicated as operands as well. don't rely on this. +1843 convert-instruction: # line : (address stream byte), out : (address buffered-file) -> <void> +1844 # pseudocode: +1845 # # some early exits +1846 # var word-slice = next-word(line) +1847 # if slice-empty?(word-slice) +1848 # write-stream-data(out, line) +1849 # return +1850 # if slice-starts-with?(word-slice, "#") +1851 # write-stream-data(out, line) +1852 # return +1853 # if slice-ends-with?(word-slice, ":") +1854 # write-stream-data(out, line) +1855 # return +1856 # # really convert +1857 # emit-opcodes(line, out) +1858 # emit-modrm(line, out) +1859 # emit-sib(line, out) +1860 # emit-disp(line, out) +1861 # emit-imm(line, out) +1862 # emit-line-in-comment(line, out) +1863 # +1864 # . prolog +1865 55/push-EBP +1866 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +1867 # . save registers +1868 50/push-EAX +1869 51/push-ECX +1870 52/push-EDX +1871 # var word-slice/ECX = {0, 0} +1872 68/push 0/imm32/end +1873 68/push 0/imm32/start +1874 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +1875 # next-word(line, word-slice) +1876 # . . push args +1877 51/push-ECX +1878 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1879 # . . call +1880 e8/call next-word/disp32 +1881 # . . discard args +1882 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1883 $convert-instruction:check0: +1884 # if (slice-empty?(word-slice)) break +1885 # . EAX = slice-empty?(word-slice) +1886 # . . push args +1887 51/push-ECX +1888 # . . call +1889 e8/call slice-empty?/disp32 +1890 # . . discard args +1891 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +1892 # . if (EAX != 0) pass through +1893 3d/compare-EAX-and 0/imm32 +1894 75/jump-if-not-equal $convert-instruction:pass-through/disp8 +1895 $convert-instruction:check1: +1896 # if (slice-starts-with?(word-slice, "#")) write-stream-data(out, line) +1897 # . start/EDX = word-slice->start +1898 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX +1899 # . c/EAX = *start +1900 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +1901 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 0/r32/AL . . # copy byte at *EDX to AL +1902 # . if (EAX == '#') pass through +1903 3d/compare-EAX-and 0x23/imm32/hash +1904 74/jump-if-equal $convert-instruction:pass-through/disp8 +1905 $convert-instruction:check2: +1906 # if (slice-ends-with?(word-slice, ":")) write-stream-data(out, line) +1907 # . end/EDX = word-slice->end +1908 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 2/r32/EDX 4/disp8 . # copy *(ECX+4) to EDX +1909 # . c/EAX = *(end-1) +1910 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +1911 8a/copy-byte 1/mod/*+disp8 2/rm32/EDX . . . 0/r32/AL -1/disp8 . # copy byte at *ECX to AL +1912 # . if (EAX == ':') pass through +1913 3d/compare-EAX-and 0x3a/imm32/colon +1914 75/jump-if-not-equal $convert-instruction:really-convert/disp8 +1915 $convert-instruction:pass-through: +1916 # write-stream-data(out, line) +1917 # . . push args +1918 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1919 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +1920 # . . call +1921 e8/call write-stream-data/disp32 +1922 # . . discard args +1923 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1924 # return +1925 eb/jump $convert-instruction:end/disp8 +1926 $convert-instruction:really-convert: +1927 # emit-opcodes(line, out) +1928 # . . push args +1929 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +1930 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1931 # . . call +1932 e8/call emit-opcodes/disp32 +1933 # . . discard args +1934 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1935 # emit-modrm(line, out) +1936 # . . push args +1937 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +1938 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1939 # . . call +1940 e8/call emit-modrm/disp32 +1941 # . . discard args +1942 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1943 # emit-sib(line, out) +1944 # . . push args +1945 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +1946 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1947 # . . call +1948 e8/call emit-sib/disp32 +1949 # . . discard args +1950 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1951 # emit-disp(line, out) +1952 # . . push args +1953 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +1954 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1955 # . . call +1956 e8/call emit-disp/disp32 +1957 # . . discard args +1958 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1959 # emit-imm(line, out) +1960 # . . push args +1961 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +1962 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1963 # . . call +1964 e8/call emit-imm/disp32 +1965 # . . discard args +1966 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1967 # emit-line-in-comment(line, out) +1968 # . . push args +1969 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +1970 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +1971 # . . call +1972 e8/call emit-line-in-comment/disp32 +1973 # . . discard args +1974 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1975 $convert-instruction:end: +1976 # . restore locals +1977 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +1978 # . restore registers +1979 5a/pop-to-EDX +1980 59/pop-to-ECX +1981 58/pop-to-EAX +1982 # . epilog +1983 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +1984 5d/pop-to-EBP +1985 c3/return +1986 +1987 emit-opcodes: # line : (address stream byte), out : (address buffered-file) -> <void> +1988 # opcodes occupy 1-3 bytes: +1989 # xx +1990 # 0f xx +1991 # f2 xx +1992 # f3 xx +1993 # f2 0f xx +1994 # f3 0f xx +1995 # +1996 # pseudocode: +1997 # rewind-stream(line) +1998 # +1999 # var op1 = next-word(line) +2000 # if (slice-empty?(op1) || slice-starts-with?(op1, "#")) return +2001 # op1 = next-token-from-slice(op1->start, op1->end, "/") +2002 # write-slice(out, op1) +2003 # if !slice-equal?(op1, "0f") && !slice-equal?(op1, "f2") && !slice-equal?(op1, "f3") +2004 # return +2005 # +2006 # var op2 = next-word(line) +2007 # if (slice-empty?(op2) || slice-starts-with?(op2, "#")) return +2008 # op2 = next-token-from-slice(op2->start, op2->end, "/") +2009 # write-slice(out, op2) +2010 # if slice-equal?(op1, "0f") +2011 # return +2012 # if !slice-equal?(op2, "0f") +2013 # return +2014 # +2015 # var op3 = next-word(line) +2016 # if (slice-empty?(op3) || slice-starts-with?(op3, "#")) return +2017 # op3 = next-token-from-slice(op3->start, op3->end, "/") +2018 # write-slice(out, op3) +2019 # +2020 # . prolog +2021 55/push-EBP +2022 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2023 # . save registers +2024 50/push-EAX +2025 51/push-ECX +2026 52/push-EDX +2027 53/push-EBX +2028 # var op1/ECX = {0, 0} +2029 68/push 0/imm32/end +2030 68/push 0/imm32/start +2031 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2032 # var op2/EDX = {0, 0} +2033 68/push 0/imm32/end +2034 68/push 0/imm32/start +2035 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX +2036 # rewind-stream(line) +2037 # . . push args +2038 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2039 # . . call +2040 e8/call rewind-stream/disp32 +2041 # . . discard args +2042 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2043 $emit-opcodes:op1: +2044 # next-word(line, op1) +2045 # . . push args +2046 51/push-ECX +2047 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2048 # . . call +2049 e8/call next-word/disp32 +2050 # . . discard args +2051 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2052 # if (slice-empty?(op1)) return +2053 # . EAX = slice-empty?(op1) +2054 # . . push args +2055 51/push-ECX +2056 # . . call +2057 e8/call slice-empty?/disp32 +2058 # . . discard args +2059 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2060 # . if (EAX != 0) return +2061 3d/compare-EAX-and 0/imm32 +2062 0f 85/jump-if-not-equal $emit-opcodes:end/disp32 +2063 # if (slice-starts-with?(op1, "#")) return +2064 # . start/EBX = op1->start +2065 8b/copy 0/mod/indirect 1/rm32/ECX . . . 3/r32/EBX . . # copy *ECX to EBX +2066 # . c/EAX = *start +2067 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +2068 8a/copy-byte 0/mod/indirect 3/rm32/EBX . . . 0/r32/AL . . # copy byte at *EBX to AL +2069 # . if (EAX == '#') return +2070 3d/compare-EAX-and 0x23/imm32/hash +2071 0f 84/jump-if-equal $emit-opcodes:end/disp32 +2072 # op1 = next-token-from-slice(op1->start, op1->end, '/') +2073 # . . push args +2074 51/push-ECX +2075 68/push 0x2f/imm32/slash +2076 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) +2077 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX +2078 # . . call +2079 e8/call next-token-from-slice/disp32 +2080 # . . discard args +2081 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +2082 # write-slice(out, op1) +2083 # . . push args +2084 51/push-ECX +2085 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +2086 # . . call +2087 e8/call write-slice/disp32 +2088 # . . discard args +2089 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2090 # write-buffered(out, " ") +2091 # . . push args +2092 68/push " "/imm32 +2093 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +2094 # . . call +2095 e8/call write-buffered/disp32 +2096 # . . discard args +2097 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2098 # if (slice-equal?(op1, "0f")) goto op2 +2099 # . EAX = slice-equal?(op1, "0f") +2100 # . . push args +2101 68/push "0f"/imm32 +2102 51/push-ECX +2103 # . . call +2104 e8/call slice-equal?/disp32 +2105 # . . discard args +2106 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2107 # . if (EAX != 0) goto op2 +2108 3d/compare-EAX-and 0/imm32 +2109 75/jump-if-not-equal $emit-opcodes:op2/disp8 +2110 # if (slice-equal?(op1, "f2")) goto op2 +2111 # . EAX = slice-equal?(op1, "f2") 2112 # . . push args -2113 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+8) -2114 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2113 68/push "f2"/imm32 +2114 51/push-ECX 2115 # . . call -2116 e8/call emit-line-in-comment/disp32 +2116 e8/call slice-equal?/disp32 2117 # . . discard args 2118 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2119 $convert-instruction:end: -2120 # . restore locals -2121 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2122 # . restore registers -2123 5a/pop-to-EDX -2124 59/pop-to-ECX -2125 58/pop-to-EAX -2126 # . epilog -2127 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -2128 5d/pop-to-EBP -2129 c3/return -2130 -2131 emit-opcodes: # line : (address stream byte), out : (address buffered-file) -> <void> -2132 # opcodes occupy 1-3 bytes: -2133 # xx -2134 # 0f xx -2135 # f2 xx -2136 # f3 xx -2137 # f2 0f xx -2138 # f3 0f xx -2139 # -2140 # pseudocode: -2141 # rewind-stream(line) -2142 # -2143 # var op1 = next-word(line) -2144 # if (slice-empty?(op1) || slice-starts-with?(op1, "#")) return -2145 # op1 = next-token-from-slice(op1->start, op1->end, "/") -2146 # write-slice(out, op1) -2147 # if !slice-equal?(op1, "0f") && !slice-equal?(op1, "f2") && !slice-equal?(op1, "f3") -2148 # return -2149 # -2150 # var op2 = next-word(line) -2151 # if (slice-empty?(op2) || slice-starts-with?(op2, "#")) return -2152 # op2 = next-token-from-slice(op2->start, op2->end, "/") -2153 # write-slice(out, op2) -2154 # if slice-equal?(op1, "0f") -2155 # return -2156 # if !slice-equal?(op2, "0f") -2157 # return -2158 # -2159 # var op3 = next-word(line) -2160 # if (slice-empty?(op3) || slice-starts-with?(op3, "#")) return -2161 # op3 = next-token-from-slice(op3->start, op3->end, "/") -2162 # write-slice(out, op3) -2163 # -2164 # . prolog -2165 55/push-EBP -2166 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -2167 # . save registers -2168 50/push-EAX -2169 51/push-ECX -2170 52/push-EDX -2171 53/push-EBX -2172 # var op1/ECX = {0, 0} -2173 68/push 0/imm32/end -2174 68/push 0/imm32/start -2175 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -2176 # var op2/EDX = {0, 0} -2177 68/push 0/imm32/end -2178 68/push 0/imm32/start -2179 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX -2180 # rewind-stream(line) -2181 # . . push args -2182 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2183 # . . call -2184 e8/call rewind-stream/disp32 -2185 # . . discard args -2186 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2187 $emit-opcodes:op1: -2188 # next-word(line, op1) -2189 # . . push args -2190 51/push-ECX -2191 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2192 # . . call -2193 e8/call next-word/disp32 -2194 # . . discard args -2195 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2196 # if (slice-empty?(op1)) return -2197 # . EAX = slice-empty?(op1) -2198 # . . push args -2199 51/push-ECX -2200 # . . call -2201 e8/call slice-empty?/disp32 -2202 # . . discard args -2203 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2204 # . if (EAX != 0) return -2205 3d/compare-EAX-and 0/imm32 -2206 0f 85/jump-if-not-equal $emit-opcodes:end/disp32 -2207 # if (slice-starts-with?(op1, "#")) return -2208 # . start/EBX = op1->start -2209 8b/copy 0/mod/indirect 1/rm32/ECX . . . 3/r32/EBX . . # copy *ECX to EBX -2210 # . c/EAX = *start -2211 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -2212 8a/copy-byte 0/mod/indirect 3/rm32/EBX . . . 0/r32/AL . . # copy byte at *EBX to AL -2213 # . if (EAX == '#') return -2214 3d/compare-EAX-and 0x23/imm32/hash -2215 0f 84/jump-if-equal $emit-opcodes:end/disp32 -2216 # op1 = next-token-from-slice(op1->start, op1->end, '/') +2119 # . if (EAX != 0) goto op2 +2120 3d/compare-EAX-and 0/imm32 +2121 75/jump-if-not-equal $emit-opcodes:op2/disp8 +2122 # if (slice-equal?(op1, "f3")) goto op2 +2123 # . EAX = slice-equal?(op1, "f3") +2124 # . . push args +2125 68/push "f3"/imm32 +2126 51/push-ECX +2127 # . . call +2128 e8/call slice-equal?/disp32 +2129 # . . discard args +2130 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2131 # . if (EAX != 0) goto op2 +2132 3d/compare-EAX-and 0/imm32 +2133 75/jump-if-not-equal $emit-opcodes:op2/disp8 +2134 # otherwise return +2135 e9/jump $emit-opcodes:end/disp32 +2136 $emit-opcodes:op2: +2137 # next-word(line, op2) +2138 # . . push args +2139 52/push-EDX +2140 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2141 # . . call +2142 e8/call next-word/disp32 +2143 # . . discard args +2144 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2145 # if (slice-empty?(op2)) return +2146 # . EAX = slice-empty?(op2) +2147 # . . push args +2148 52/push-EDX +2149 # . . call +2150 e8/call slice-empty?/disp32 +2151 # . . discard args +2152 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2153 # . if (EAX != 0) return +2154 3d/compare-EAX-and 0/imm32 +2155 0f 85/jump-if-not-equal $emit-opcodes:end/disp32 +2156 # if (slice-starts-with?(op2, "#")) return +2157 # . start/EBX = op2->start +2158 8b/copy 0/mod/indirect 2/rm32/EDX . . . 3/r32/EBX . . # copy *EDX to EBX +2159 # . c/EAX = *start +2160 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +2161 8a/copy-byte 0/mod/indirect 3/rm32/EBX . . . 0/r32/AL . . # copy byte at *EBX to AL +2162 # . if (EAX == '#') return +2163 3d/compare-EAX-and 0x23/imm32/hash +2164 0f 84/jump-if-equal $emit-opcodes:end/disp32 +2165 # op2 = next-token-from-slice(op2->start, op2->end, '/') +2166 # . . push args +2167 52/push-EDX +2168 68/push 0x2f/imm32/slash +2169 ff 6/subop/push 1/mod/*+disp8 2/rm32/EDX . . . . 4/disp8 . # push *(EDX+4) +2170 ff 6/subop/push 0/mod/indirect 2/rm32/EDX . . . . . . # push *EDX +2171 # . . call +2172 e8/call next-token-from-slice/disp32 +2173 # . . discard args +2174 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +2175 # write-slice(out, op2) +2176 # . . push args +2177 52/push-EDX +2178 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +2179 # . . call +2180 e8/call write-slice/disp32 +2181 # . . discard args +2182 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2183 # write-buffered(out, " ") +2184 # . . push args +2185 68/push " "/imm32 +2186 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +2187 # . . call +2188 e8/call write-buffered/disp32 +2189 # . . discard args +2190 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2191 # if (slice-equal?(op1, "0f")) return +2192 # . EAX = slice-equal?(op1, "0f") +2193 # . . push args +2194 68/push "0f"/imm32 +2195 51/push-ECX +2196 # . . call +2197 e8/call slice-equal?/disp32 +2198 # . . discard args +2199 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2200 # . if (EAX != 0) return +2201 3d/compare-EAX-and 0/imm32 +2202 0f 85/jump-if-not-equal $emit-opcodes:end/disp32 +2203 # if (!slice-equal?(op2, "0f")) return +2204 # . EAX = slice-equal?(op2, "0f") +2205 # . . push args +2206 68/push "0f"/imm32 +2207 52/push-EDX +2208 # . . call +2209 e8/call slice-equal?/disp32 +2210 # . . discard args +2211 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2212 # . if (EAX == 0) return +2213 3d/compare-EAX-and 0/imm32 +2214 0f 84/jump-if-equal $emit-opcodes:end/disp32 +2215 $emit-opcodes:op3: +2216 # next-word(line, op3) # reuse op2/EDX 2217 # . . push args -2218 51/push-ECX -2219 68/push 0x2f/imm32/slash -2220 ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 4/disp8 . # push *(ECX+4) -2221 ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX -2222 # . . call -2223 e8/call next-token-from-slice/disp32 -2224 # . . discard args -2225 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -2226 # write-slice(out, op1) -2227 # . . push args -2228 51/push-ECX -2229 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -2230 # . . call -2231 e8/call write-slice/disp32 -2232 # . . discard args -2233 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2234 # write-buffered(out, " ") -2235 # . . push args -2236 68/push " "/imm32 -2237 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -2238 # . . call -2239 e8/call write-buffered/disp32 -2240 # . . discard args -2241 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2242 # if (slice-equal?(op1, "0f")) goto op2 -2243 # . EAX = slice-equal?(op1, "0f") -2244 # . . push args -2245 68/push "0f"/imm32 -2246 51/push-ECX -2247 # . . call -2248 e8/call slice-equal?/disp32 -2249 # . . discard args -2250 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2251 # . if (EAX != 0) goto op2 -2252 3d/compare-EAX-and 0/imm32 -2253 75/jump-if-not-equal $emit-opcodes:op2/disp8 -2254 # if (slice-equal?(op1, "f2")) goto op2 -2255 # . EAX = slice-equal?(op1, "f2") -2256 # . . push args -2257 68/push "f2"/imm32 -2258 51/push-ECX -2259 # . . call -2260 e8/call slice-equal?/disp32 -2261 # . . discard args -2262 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2263 # . if (EAX != 0) goto op2 -2264 3d/compare-EAX-and 0/imm32 -2265 75/jump-if-not-equal $emit-opcodes:op2/disp8 -2266 # if (slice-equal?(op1, "f3")) goto op2 -2267 # . EAX = slice-equal?(op1, "f3") -2268 # . . push args -2269 68/push "f3"/imm32 -2270 51/push-ECX -2271 # . . call -2272 e8/call slice-equal?/disp32 -2273 # . . discard args -2274 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2275 # . if (EAX != 0) goto op2 -2276 3d/compare-EAX-and 0/imm32 -2277 75/jump-if-not-equal $emit-opcodes:op2/disp8 -2278 # otherwise return -2279 e9/jump $emit-opcodes:end/disp32 -2280 $emit-opcodes:op2: -2281 # next-word(line, op2) -2282 # . . push args -2283 52/push-EDX -2284 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2285 # . . call -2286 e8/call next-word/disp32 -2287 # . . discard args -2288 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2289 # if (slice-empty?(op2)) return -2290 # . EAX = slice-empty?(op2) -2291 # . . push args -2292 52/push-EDX -2293 # . . call -2294 e8/call slice-empty?/disp32 -2295 # . . discard args -2296 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2297 # . if (EAX != 0) return -2298 3d/compare-EAX-and 0/imm32 -2299 0f 85/jump-if-not-equal $emit-opcodes:end/disp32 -2300 # if (slice-starts-with?(op2, "#")) return -2301 # . start/EBX = op2->start -2302 8b/copy 0/mod/indirect 2/rm32/EDX . . . 3/r32/EBX . . # copy *EDX to EBX -2303 # . c/EAX = *start -2304 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -2305 8a/copy-byte 0/mod/indirect 3/rm32/EBX . . . 0/r32/AL . . # copy byte at *EBX to AL -2306 # . if (EAX == '#') return -2307 3d/compare-EAX-and 0x23/imm32/hash -2308 0f 84/jump-if-equal $emit-opcodes:end/disp32 -2309 # op2 = next-token-from-slice(op2->start, op2->end, '/') -2310 # . . push args -2311 52/push-EDX -2312 68/push 0x2f/imm32/slash -2313 ff 6/subop/push 1/mod/*+disp8 2/rm32/EDX . . . . 4/disp8 . # push *(EDX+4) -2314 ff 6/subop/push 0/mod/indirect 2/rm32/EDX . . . . . . # push *EDX -2315 # . . call -2316 e8/call next-token-from-slice/disp32 -2317 # . . discard args -2318 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -2319 # write-slice(out, op2) -2320 # . . push args -2321 52/push-EDX -2322 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -2323 # . . call -2324 e8/call write-slice/disp32 -2325 # . . discard args -2326 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2327 # write-buffered(out, " ") -2328 # . . push args -2329 68/push " "/imm32 -2330 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -2331 # . . call -2332 e8/call write-buffered/disp32 -2333 # . . discard args -2334 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2335 # if (slice-equal?(op1, "0f")) return -2336 # . EAX = slice-equal?(op1, "0f") -2337 # . . push args -2338 68/push "0f"/imm32 -2339 51/push-ECX -2340 # . . call -2341 e8/call slice-equal?/disp32 -2342 # . . discard args -2343 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2344 # . if (EAX != 0) return -2345 3d/compare-EAX-and 0/imm32 -2346 0f 85/jump-if-not-equal $emit-opcodes:end/disp32 -2347 # if (!slice-equal?(op2, "0f")) return -2348 # . EAX = slice-equal?(op2, "0f") -2349 # . . push args -2350 68/push "0f"/imm32 -2351 52/push-EDX -2352 # . . call -2353 e8/call slice-equal?/disp32 -2354 # . . discard args -2355 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2356 # . if (EAX == 0) return -2357 3d/compare-EAX-and 0/imm32 -2358 0f 84/jump-if-equal $emit-opcodes:end/disp32 -2359 $emit-opcodes:op3: -2360 # next-word(line, op3) # reuse op2/EDX -2361 # . . push args -2362 52/push-EDX -2363 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2364 # . . call -2365 e8/call next-word/disp32 -2366 # . . discard args -2367 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2368 # if (slice-empty?(op3)) return -2369 # . EAX = slice-empty?(op3) -2370 # . . push args -2371 52/push-EDX -2372 # . . call -2373 e8/call slice-empty?/disp32 -2374 # . . discard args -2375 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2376 # . if (EAX != 0) return -2377 3d/compare-EAX-and 0/imm32 -2378 0f 85/jump-if-not-equal $emit-opcodes:end/disp32 -2379 # if (slice-starts-with?(op3, "#")) return -2380 # . start/EBX = op2->start -2381 8b/copy 0/mod/indirect 2/rm32/EDX . . . 3/r32/EBX . . # copy *EDX to EBX -2382 # . c/EAX = *start -2383 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -2384 8a/copy-byte 0/mod/indirect 3/rm32/EBX . . . 0/r32/AL . . # copy byte at *EBX to AL -2385 # . if (EAX == '#') return -2386 3d/compare-EAX-and 0x23/imm32/hash -2387 0f 84/jump-if-equal $emit-opcodes:end/disp32 -2388 # op3 = next-token-from-slice(op3->start, op3->end, '/') -2389 # . . push args -2390 52/push-EDX -2391 68/push 0x2f/imm32/slash -2392 ff 6/subop/push 1/mod/*+disp8 2/rm32/EDX . . . . 4/disp8 . # push *(EDX+4) -2393 ff 6/subop/push 0/mod/indirect 2/rm32/EDX . . . . . . # push *EDX -2394 # . . call -2395 e8/call next-token-from-slice/disp32 -2396 # . . discard args -2397 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -2398 # write-slice(out, op3) -2399 # . . push args -2400 52/push-EDX -2401 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -2402 # . . call -2403 e8/call write-slice/disp32 -2404 # . . discard args -2405 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2406 # write-buffered(out, " ") -2407 # . . push args -2408 68/push " "/imm32 -2409 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -2410 # . . call -2411 e8/call write-buffered/disp32 -2412 # . . discard args -2413 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2414 $emit-opcodes:end: -2415 # . restore locals -2416 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -2417 # . restore registers -2418 5b/pop-to-EBX -2419 5a/pop-to-EDX -2420 59/pop-to-ECX -2421 58/pop-to-EAX -2422 # . epilog -2423 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -2424 5d/pop-to-EBP -2425 c3/return -2426 -2427 emit-modrm: # line : (address stream byte), out : (address buffered-file) -> <void> -2428 # pseudocode: -2429 # rewind-stream(line) -2430 # var has-modrm? = false, mod = 0, rm32 = 0, r32 = 0 -2431 # var word-slice = {0, 0} -2432 # while true -2433 # word-slice = next-word(line) -2434 # if (slice-empty?(word-slice)) break -2435 # if (slice-starts-with?(word-slice, "#")) break -2436 # if (has-metadata?(word-slice, "mod")) -2437 # mod = parse-hex-int(next-token-from-slice(word-slice, "/")) -2438 # has-modrm? = true -2439 # else if (has-metadata?(word-slice, "rm32")) -2440 # rm32 = parse-hex-int(next-token-from-slice(word-slice, "/")) -2441 # has-modrm? = true -2442 # else if (has-metadata?(word-slice, "r32") or has-metadata?(word-slice, "subop")) -2443 # r32 = parse-hex-int(next-token-from-slice(word-slice, "/")) -2444 # has-modrm? = true -2445 # if has-modrm? -2446 # var modrm = mod & 0b11 -2447 # modrm <<= 2 -2448 # modrm |= r32 & 0b111 -2449 # modrm <<= 3 -2450 # modrm |= rm32 & 0b111 -2451 # emit-hex(out, modrm, 1) -2452 # -2453 # . prolog -2454 55/push-EBP -2455 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -2456 # . save registers -2457 50/push-EAX +2218 52/push-EDX +2219 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2220 # . . call +2221 e8/call next-word/disp32 +2222 # . . discard args +2223 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2224 # if (slice-empty?(op3)) return +2225 # . EAX = slice-empty?(op3) +2226 # . . push args +2227 52/push-EDX +2228 # . . call +2229 e8/call slice-empty?/disp32 +2230 # . . discard args +2231 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2232 # . if (EAX != 0) return +2233 3d/compare-EAX-and 0/imm32 +2234 0f 85/jump-if-not-equal $emit-opcodes:end/disp32 +2235 # if (slice-starts-with?(op3, "#")) return +2236 # . start/EBX = op2->start +2237 8b/copy 0/mod/indirect 2/rm32/EDX . . . 3/r32/EBX . . # copy *EDX to EBX +2238 # . c/EAX = *start +2239 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +2240 8a/copy-byte 0/mod/indirect 3/rm32/EBX . . . 0/r32/AL . . # copy byte at *EBX to AL +2241 # . if (EAX == '#') return +2242 3d/compare-EAX-and 0x23/imm32/hash +2243 0f 84/jump-if-equal $emit-opcodes:end/disp32 +2244 # op3 = next-token-from-slice(op3->start, op3->end, '/') +2245 # . . push args +2246 52/push-EDX +2247 68/push 0x2f/imm32/slash +2248 ff 6/subop/push 1/mod/*+disp8 2/rm32/EDX . . . . 4/disp8 . # push *(EDX+4) +2249 ff 6/subop/push 0/mod/indirect 2/rm32/EDX . . . . . . # push *EDX +2250 # . . call +2251 e8/call next-token-from-slice/disp32 +2252 # . . discard args +2253 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +2254 # write-slice(out, op3) +2255 # . . push args +2256 52/push-EDX +2257 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +2258 # . . call +2259 e8/call write-slice/disp32 +2260 # . . discard args +2261 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2262 # write-buffered(out, " ") +2263 # . . push args +2264 68/push " "/imm32 +2265 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +2266 # . . call +2267 e8/call write-buffered/disp32 +2268 # . . discard args +2269 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2270 $emit-opcodes:end: +2271 # . restore locals +2272 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +2273 # . restore registers +2274 5b/pop-to-EBX +2275 5a/pop-to-EDX +2276 59/pop-to-ECX +2277 58/pop-to-EAX +2278 # . epilog +2279 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2280 5d/pop-to-EBP +2281 c3/return +2282 +2283 emit-modrm: # line : (address stream byte), out : (address buffered-file) -> <void> +2284 # pseudocode: +2285 # rewind-stream(line) +2286 # var has-modrm? = false, mod = 0, rm32 = 0, r32 = 0 +2287 # var word-slice = {0, 0} +2288 # while true +2289 # word-slice = next-word(line) +2290 # if (slice-empty?(word-slice)) break +2291 # if (slice-starts-with?(word-slice, "#")) break +2292 # if (has-metadata?(word-slice, "mod")) +2293 # mod = parse-hex-int(next-token-from-slice(word-slice, "/")) +2294 # has-modrm? = true +2295 # else if (has-metadata?(word-slice, "rm32")) +2296 # rm32 = parse-hex-int(next-token-from-slice(word-slice, "/")) +2297 # has-modrm? = true +2298 # else if (has-metadata?(word-slice, "r32") or has-metadata?(word-slice, "subop")) +2299 # r32 = parse-hex-int(next-token-from-slice(word-slice, "/")) +2300 # has-modrm? = true +2301 # if has-modrm? +2302 # var modrm = mod & 0b11 +2303 # modrm <<= 2 +2304 # modrm |= r32 & 0b111 +2305 # modrm <<= 3 +2306 # modrm |= rm32 & 0b111 +2307 # emit-hex(out, modrm, 1) +2308 # +2309 # . prolog +2310 55/push-EBP +2311 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2312 # . save registers +2313 50/push-EAX +2314 51/push-ECX +2315 52/push-EDX +2316 53/push-EBX +2317 56/push-ESI +2318 57/push-EDI +2319 # var word-slice/ECX = {0, 0} +2320 68/push 0/imm32/end +2321 68/push 0/imm32/start +2322 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2323 # var has-modrm?/EDX = false +2324 31/xor 3/mod/direct 2/rm32/EDX . . . 2/r32/EDX . . # clear EDX +2325 # var mod/EBX = 0 +2326 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX +2327 # var rm32/ESI = 0 +2328 31/xor 3/mod/direct 6/rm32/ESI . . . 6/r32/ESI . . # clear ESI +2329 # var r32/EDI = 0 +2330 31/xor 3/mod/direct 7/rm32/EDI . . . 7/r32/EDI . . # clear EDI +2331 # rewind-stream(line) +2332 # . . push args +2333 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2334 # . . call +2335 e8/call rewind-stream/disp32 +2336 # . . discard args +2337 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2338 $emit-modrm:loop: +2339 +-- 26 lines: #? # dump line ----------------------------------------------------------------------------------------------------------------------------- +2365 # next-word(line, word-slice) +2366 # . . push args +2367 51/push-ECX +2368 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2369 # . . call +2370 e8/call next-word/disp32 +2371 # . . discard args +2372 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2373 +-- 42 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- +2415 $emit-modrm:check0: +2416 # if (slice-empty?(word-slice)) break +2417 # . EAX = slice-empty?(word-slice) +2418 # . . push args +2419 51/push-ECX +2420 # . . call +2421 e8/call slice-empty?/disp32 +2422 # . . discard args +2423 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2424 # . if (EAX != 0) pass through +2425 3d/compare-EAX-and 0/imm32 +2426 0f 85/jump-if-not-equal $emit-modrm:break/disp32 +2427 $emit-modrm:check1: +2428 # if (slice-starts-with?(word-slice, "#")) break +2429 # . spill EDX +2430 52/push-EDX +2431 # . start/EDX = word-slice->start +2432 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX +2433 # . c/EAX = *start +2434 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +2435 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 0/r32/AL . . # copy byte at *EDX to AL +2436 # . restore EDX +2437 5a/pop-to-EDX +2438 # . if (EAX == '#') pass through +2439 3d/compare-EAX-and 0x23/imm32/hash +2440 0f 84/jump-if-equal $emit-modrm:break/disp32 +2441 $emit-modrm:check-for-mod: +2442 # if (has-metadata?(word-slice, "mod")) +2443 # . EAX = has-metadata?(ECX, "mod") +2444 # . . push args +2445 68/push "mod"/imm32 +2446 51/push-ECX +2447 # . . call +2448 e8/call has-metadata?/disp32 +2449 # . . discard args +2450 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2451 # . if (EAX == 0) goto next check +2452 3d/compare-EAX-and 0/imm32 +2453 74/jump-if-equal $emit-modrm:check-for-rm32/disp8 +2454 $emit-modrm:mod: +2455 # mod = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) +2456 # . EAX = parse-datum-of-word(word-slice) +2457 # . . push args 2458 51/push-ECX -2459 52/push-EDX -2460 53/push-EBX -2461 56/push-ESI -2462 57/push-EDI -2463 # var word-slice/ECX = {0, 0} -2464 68/push 0/imm32/end -2465 68/push 0/imm32/start -2466 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -2467 # var has-modrm?/EDX = false -2468 31/xor 3/mod/direct 2/rm32/EDX . . . 2/r32/EDX . . # clear EDX -2469 # var mod/EBX = 0 -2470 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX -2471 # var rm32/ESI = 0 -2472 31/xor 3/mod/direct 6/rm32/ESI . . . 6/r32/ESI . . # clear ESI -2473 # var r32/EDI = 0 -2474 31/xor 3/mod/direct 7/rm32/EDI . . . 7/r32/EDI . . # clear EDI -2475 # rewind-stream(line) -2476 # . . push args -2477 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2478 # . . call -2479 e8/call rewind-stream/disp32 -2480 # . . discard args -2481 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2482 $emit-modrm:loop: -2483 +-- 34 lines: #? # dump line ----------------------------------------------------------------------------------------------------------------------------- -2517 # next-word(line, word-slice) -2518 # . . push args -2519 51/push-ECX -2520 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2521 # . . call -2522 e8/call next-word/disp32 -2523 # . . discard args -2524 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2525 +-- 50 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- -2575 $emit-modrm:check0: -2576 # if (slice-empty?(word-slice)) break -2577 # . EAX = slice-empty?(word-slice) -2578 # . . push args -2579 51/push-ECX -2580 # . . call -2581 e8/call slice-empty?/disp32 -2582 # . . discard args -2583 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2584 # . if (EAX != 0) pass through -2585 3d/compare-EAX-and 0/imm32 -2586 0f 85/jump-if-not-equal $emit-modrm:break/disp32 -2587 $emit-modrm:check1: -2588 # if (slice-starts-with?(word-slice, "#")) break -2589 # . spill EDX -2590 52/push-EDX -2591 # . start/EDX = word-slice->start -2592 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX -2593 # . c/EAX = *start -2594 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -2595 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 0/r32/AL . . # copy byte at *EDX to AL -2596 # . restore EDX -2597 5a/pop-to-EDX -2598 # . if (EAX == '#') pass through -2599 3d/compare-EAX-and 0x23/imm32/hash -2600 0f 84/jump-if-equal $emit-modrm:break/disp32 -2601 $emit-modrm:check-for-mod: -2602 # if (has-metadata?(word-slice, "mod")) -2603 # . EAX = has-metadata?(ECX, "mod") -2604 # . . push args -2605 68/push "mod"/imm32 -2606 51/push-ECX -2607 # . . call -2608 e8/call has-metadata?/disp32 -2609 # . . discard args -2610 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2611 # . if (EAX == 0) goto next check -2612 3d/compare-EAX-and 0/imm32 -2613 74/jump-if-equal $emit-modrm:check-for-rm32/disp8 -2614 $emit-modrm:mod: -2615 # mod = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) -2616 # . EAX = parse-datum-of-word(word-slice) -2617 # . . push args -2618 51/push-ECX -2619 # . . call -2620 e8/call parse-datum-of-word/disp32 -2621 # . . discard args -2622 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2623 # . mod = EAX -2624 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX -2625 # has-modrm? = true -2626 ba/copy-to-EDX 1/imm32/true -2627 # continue -2628 e9/jump $emit-modrm:loop/disp32 -2629 $emit-modrm:check-for-rm32: -2630 # if (has-metadata?(word-slice, "rm32")) -2631 # . EAX = has-metadata?(ECX, "rm32") -2632 # . . push args -2633 68/push "rm32"/imm32 -2634 51/push-ECX -2635 # . . call -2636 e8/call has-metadata?/disp32 -2637 # . . discard args -2638 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2639 # . if (EAX == 0) goto next check -2640 3d/compare-EAX-and 0/imm32 -2641 74/jump-if-equal $emit-modrm:check-for-r32/disp8 -2642 $emit-modrm:rm32: -2643 # rm32 = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) -2644 # . EAX = parse-datum-of-word(word-slice) -2645 # . . push args -2646 51/push-ECX -2647 # . . call -2648 e8/call parse-datum-of-word/disp32 -2649 # . . discard args -2650 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2651 # . rm32 = EAX -2652 89/copy 3/mod/direct 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to ESI -2653 # has-modrm? = true -2654 ba/copy-to-EDX 1/imm32/true -2655 # continue -2656 e9/jump $emit-modrm:loop/disp32 -2657 $emit-modrm:check-for-r32: -2658 # if (has-metadata?(word-slice, "r32")) -2659 # . EAX = has-metadata?(ECX, "r32") -2660 # . . push args -2661 68/push "r32"/imm32 -2662 51/push-ECX -2663 # . . call -2664 e8/call has-metadata?/disp32 -2665 # . . discard args -2666 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2667 # . if (EAX == 0) goto next check -2668 3d/compare-EAX-and 0/imm32 -2669 74/jump-if-equal $emit-modrm:check-for-subop/disp8 -2670 $emit-modrm:r32: -2671 # r32 = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) -2672 # . EAX = parse-datum-of-word(word-slice) -2673 # . . push args -2674 51/push-ECX -2675 # . . call -2676 e8/call parse-datum-of-word/disp32 -2677 # . . discard args -2678 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2679 # . r32 = EAX -2680 89/copy 3/mod/direct 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to EDI -2681 # has-modrm? = true -2682 ba/copy-to-EDX 1/imm32/true -2683 # continue -2684 e9/jump $emit-modrm:loop/disp32 -2685 $emit-modrm:check-for-subop: -2686 # if (has-metadata?(word-slice, "subop")) -2687 # . EAX = has-metadata?(ECX, "subop") -2688 # . . push args -2689 68/push "subop"/imm32 -2690 51/push-ECX -2691 # . . call -2692 e8/call has-metadata?/disp32 -2693 # . . discard args -2694 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2695 # . if (EAX == 0) loop -2696 3d/compare-EAX-and 0/imm32 -2697 0f 84/jump-if-equal $emit-modrm:loop/disp32 -2698 $emit-modrm:subop: -2699 # r32 = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) -2700 # . EAX = parse-datum-of-word(word-slice) -2701 # . . push args -2702 51/push-ECX -2703 # . . call -2704 e8/call parse-datum-of-word/disp32 -2705 # . . discard args -2706 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2707 # . r32 = EAX -2708 89/copy 3/mod/direct 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to EDI -2709 # has-modrm? = true -2710 ba/copy-to-EDX 1/imm32/true -2711 # continue -2712 e9/jump $emit-modrm:loop/disp32 -2713 $emit-modrm:break: -2714 # if (!has-modrm?) return -2715 81 7/subop/compare 3/mod/direct 2/rm32/EDX . . . . . 0/imm32 # compare EDX -2716 74/jump-if-equal $emit-modrm:end/disp8 -2717 $emit-modrm:calculate: -2718 # modrm/EBX = mod & 0b11 -2719 81 4/subop/and 3/mod/direct 3/rm32/EBX . . . . . 3/imm32/0b11 # bitwise and of EBX -2720 # modrm <<= 2 -2721 c1/shift 4/subop/left 3/mod/direct 3/rm32/EBX . . . . . 2/imm8 # shift EBX left by 2 bits -2722 # modrm |= r32 & 0b111 -2723 81 4/subop/and 3/mod/direct 7/rm32/EDI . . . . . 7/imm32/0b111 # bitwise and of EDI -2724 09/or 3/mod/direct 3/rm32/EBX . . . 7/r32/EDI . . # EBX = bitwise OR with EDI -2725 # modrm <<= 3 -2726 c1/shift 4/subop/left 3/mod/direct 3/rm32/EBX . . . . . 3/imm8 # shift EBX left by 3 bits -2727 # modrm |= rm32 & 0b111 -2728 81 4/subop/and 3/mod/direct 6/rm32/ESI . . . . . 7/imm32/0b111 # bitwise and of ESI -2729 09/or 3/mod/direct 3/rm32/EBX . . . 6/r32/ESI . . # EBX = bitwise OR with ESI -2730 $emit-modrm:emit: -2731 # emit-hex(out, modrm, 1) -2732 # . . push args -2733 68/push 1/imm32 -2734 53/push-EBX -2735 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -2736 # . . call -2737 e8/call emit-hex/disp32 -2738 # . . discard args -2739 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -2740 $emit-modrm:end: -2741 # . restore locals -2742 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2743 # . restore registers -2744 5f/pop-to-EDI -2745 5e/pop-to-ESI -2746 5b/pop-to-EBX -2747 5a/pop-to-EDX -2748 59/pop-to-ECX -2749 58/pop-to-EAX -2750 # . epilog -2751 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -2752 5d/pop-to-EBP -2753 c3/return -2754 -2755 emit-sib: # line : (address stream byte), out : (address buffered-file) -> <void> -2756 # pseudocode: -2757 # var has-sib? = false, base = 0, index = 0, scale = 0 -2758 # var word-slice = {0, 0} -2759 # while true -2760 # word-slice = next-word(line) -2761 # if (slice-empty?(word-slice)) break -2762 # if (slice-starts-with?(word-slice, "#")) break -2763 # if (has-metadata?(word-slice, "base") -2764 # base = parse-hex-int(next-token-from-slice(word-slice, "/")) -2765 # has-sib? = true -2766 # else if (has-metadata?(word-slice, "index") -2767 # index = parse-hex-int(next-token-from-slice(word-slice, "/")) -2768 # has-sib? = true -2769 # else if (has-metadata?(word-slice, "scale") -2770 # scale = parse-hex-int(next-token-from-slice(word-slice, "/")) -2771 # has-sib? = true -2772 # if has-sib? -2773 # var sib = scale & 0b11 -2774 # sib <<= 2 -2775 # sib |= index & 0b111 -2776 # sib <<= 3 -2777 # sib |= base & 0b111 -2778 # emit-hex(out, sib, 1) -2779 # -2780 # . prolog -2781 55/push-EBP -2782 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -2783 # . save registers -2784 50/push-EAX +2459 # . . call +2460 e8/call parse-datum-of-word/disp32 +2461 # . . discard args +2462 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2463 # . mod = EAX +2464 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX +2465 # has-modrm? = true +2466 ba/copy-to-EDX 1/imm32/true +2467 # continue +2468 e9/jump $emit-modrm:loop/disp32 +2469 $emit-modrm:check-for-rm32: +2470 # if (has-metadata?(word-slice, "rm32")) +2471 # . EAX = has-metadata?(ECX, "rm32") +2472 # . . push args +2473 68/push "rm32"/imm32 +2474 51/push-ECX +2475 # . . call +2476 e8/call has-metadata?/disp32 +2477 # . . discard args +2478 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2479 # . if (EAX == 0) goto next check +2480 3d/compare-EAX-and 0/imm32 +2481 74/jump-if-equal $emit-modrm:check-for-r32/disp8 +2482 $emit-modrm:rm32: +2483 # rm32 = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) +2484 # . EAX = parse-datum-of-word(word-slice) +2485 # . . push args +2486 51/push-ECX +2487 # . . call +2488 e8/call parse-datum-of-word/disp32 +2489 # . . discard args +2490 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2491 # . rm32 = EAX +2492 89/copy 3/mod/direct 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to ESI +2493 # has-modrm? = true +2494 ba/copy-to-EDX 1/imm32/true +2495 # continue +2496 e9/jump $emit-modrm:loop/disp32 +2497 $emit-modrm:check-for-r32: +2498 # if (has-metadata?(word-slice, "r32")) +2499 # . EAX = has-metadata?(ECX, "r32") +2500 # . . push args +2501 68/push "r32"/imm32 +2502 51/push-ECX +2503 # . . call +2504 e8/call has-metadata?/disp32 +2505 # . . discard args +2506 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2507 # . if (EAX == 0) goto next check +2508 3d/compare-EAX-and 0/imm32 +2509 74/jump-if-equal $emit-modrm:check-for-subop/disp8 +2510 $emit-modrm:r32: +2511 # r32 = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) +2512 # . EAX = parse-datum-of-word(word-slice) +2513 # . . push args +2514 51/push-ECX +2515 # . . call +2516 e8/call parse-datum-of-word/disp32 +2517 # . . discard args +2518 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2519 # . r32 = EAX +2520 89/copy 3/mod/direct 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to EDI +2521 # has-modrm? = true +2522 ba/copy-to-EDX 1/imm32/true +2523 # continue +2524 e9/jump $emit-modrm:loop/disp32 +2525 $emit-modrm:check-for-subop: +2526 # if (has-metadata?(word-slice, "subop")) +2527 # . EAX = has-metadata?(ECX, "subop") +2528 # . . push args +2529 68/push "subop"/imm32 +2530 51/push-ECX +2531 # . . call +2532 e8/call has-metadata?/disp32 +2533 # . . discard args +2534 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2535 # . if (EAX == 0) loop +2536 3d/compare-EAX-and 0/imm32 +2537 0f 84/jump-if-equal $emit-modrm:loop/disp32 +2538 $emit-modrm:subop: +2539 # r32 = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) +2540 # . EAX = parse-datum-of-word(word-slice) +2541 # . . push args +2542 51/push-ECX +2543 # . . call +2544 e8/call parse-datum-of-word/disp32 +2545 # . . discard args +2546 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2547 # . r32 = EAX +2548 89/copy 3/mod/direct 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to EDI +2549 # has-modrm? = true +2550 ba/copy-to-EDX 1/imm32/true +2551 # continue +2552 e9/jump $emit-modrm:loop/disp32 +2553 $emit-modrm:break: +2554 # if (!has-modrm?) return +2555 81 7/subop/compare 3/mod/direct 2/rm32/EDX . . . . . 0/imm32 # compare EDX +2556 74/jump-if-equal $emit-modrm:end/disp8 +2557 $emit-modrm:calculate: +2558 # modrm/EBX = mod & 0b11 +2559 81 4/subop/and 3/mod/direct 3/rm32/EBX . . . . . 3/imm32/0b11 # bitwise and of EBX +2560 # modrm <<= 2 +2561 c1/shift 4/subop/left 3/mod/direct 3/rm32/EBX . . . . . 2/imm8 # shift EBX left by 2 bits +2562 # modrm |= r32 & 0b111 +2563 81 4/subop/and 3/mod/direct 7/rm32/EDI . . . . . 7/imm32/0b111 # bitwise and of EDI +2564 09/or 3/mod/direct 3/rm32/EBX . . . 7/r32/EDI . . # EBX = bitwise OR with EDI +2565 # modrm <<= 3 +2566 c1/shift 4/subop/left 3/mod/direct 3/rm32/EBX . . . . . 3/imm8 # shift EBX left by 3 bits +2567 # modrm |= rm32 & 0b111 +2568 81 4/subop/and 3/mod/direct 6/rm32/ESI . . . . . 7/imm32/0b111 # bitwise and of ESI +2569 09/or 3/mod/direct 3/rm32/EBX . . . 6/r32/ESI . . # EBX = bitwise OR with ESI +2570 $emit-modrm:emit: +2571 # emit-hex(out, modrm, 1) +2572 # . . push args +2573 68/push 1/imm32 +2574 53/push-EBX +2575 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +2576 # . . call +2577 e8/call emit-hex/disp32 +2578 # . . discard args +2579 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2580 $emit-modrm:end: +2581 # . restore locals +2582 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2583 # . restore registers +2584 5f/pop-to-EDI +2585 5e/pop-to-ESI +2586 5b/pop-to-EBX +2587 5a/pop-to-EDX +2588 59/pop-to-ECX +2589 58/pop-to-EAX +2590 # . epilog +2591 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2592 5d/pop-to-EBP +2593 c3/return +2594 +2595 emit-sib: # line : (address stream byte), out : (address buffered-file) -> <void> +2596 # pseudocode: +2597 # var has-sib? = false, base = 0, index = 0, scale = 0 +2598 # var word-slice = {0, 0} +2599 # while true +2600 # word-slice = next-word(line) +2601 # if (slice-empty?(word-slice)) break +2602 # if (slice-starts-with?(word-slice, "#")) break +2603 # if (has-metadata?(word-slice, "base") +2604 # base = parse-hex-int(next-token-from-slice(word-slice, "/")) +2605 # has-sib? = true +2606 # else if (has-metadata?(word-slice, "index") +2607 # index = parse-hex-int(next-token-from-slice(word-slice, "/")) +2608 # has-sib? = true +2609 # else if (has-metadata?(word-slice, "scale") +2610 # scale = parse-hex-int(next-token-from-slice(word-slice, "/")) +2611 # has-sib? = true +2612 # if has-sib? +2613 # var sib = scale & 0b11 +2614 # sib <<= 2 +2615 # sib |= index & 0b111 +2616 # sib <<= 3 +2617 # sib |= base & 0b111 +2618 # emit-hex(out, sib, 1) +2619 # +2620 # . prolog +2621 55/push-EBP +2622 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2623 # . save registers +2624 50/push-EAX +2625 51/push-ECX +2626 52/push-EDX +2627 53/push-EBX +2628 56/push-ESI +2629 57/push-EDI +2630 # var word-slice/ECX = {0, 0} +2631 68/push 0/imm32/end +2632 68/push 0/imm32/start +2633 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2634 # var has-sib?/EDX = false +2635 31/xor 3/mod/direct 2/rm32/EDX . . . 2/r32/EDX . . # clear EDX +2636 # var scale/EBX = 0 +2637 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX +2638 # var base/ESI = 0 +2639 31/xor 3/mod/direct 6/rm32/ESI . . . 6/r32/ESI . . # clear ESI +2640 # var index/EDI = 0 +2641 31/xor 3/mod/direct 7/rm32/EDI . . . 7/r32/EDI . . # clear EDI +2642 # rewind-stream(line) +2643 # . . push args +2644 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2645 # . . call +2646 e8/call rewind-stream/disp32 +2647 # . . discard args +2648 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2649 $emit-sib:loop: +2650 +-- 26 lines: #? # dump line ----------------------------------------------------------------------------------------------------------------------------- +2676 # next-word(line, word-slice) +2677 # . . push args +2678 51/push-ECX +2679 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2680 # . . call +2681 e8/call next-word/disp32 +2682 # . . discard args +2683 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2684 +-- 42 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- +2726 $emit-sib:check0: +2727 # if (slice-empty?(word-slice)) break +2728 # . EAX = slice-empty?(word-slice) +2729 # . . push args +2730 51/push-ECX +2731 # . . call +2732 e8/call slice-empty?/disp32 +2733 # . . discard args +2734 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2735 # . if (EAX != 0) pass through +2736 3d/compare-EAX-and 0/imm32 +2737 0f 85/jump-if-not-equal $emit-sib:break/disp32 +2738 $emit-sib:check1: +2739 # if (slice-starts-with?(word-slice, "#")) break +2740 # . spill EDX +2741 52/push-EDX +2742 # . start/EDX = word-slice->start +2743 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX +2744 # . c/EAX = *start +2745 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +2746 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 0/r32/AL . . # copy byte at *EDX to AL +2747 # . restore EDX +2748 5a/pop-to-EDX +2749 # . if (EAX == '#') pass through +2750 3d/compare-EAX-and 0x23/imm32/hash +2751 0f 84/jump-if-equal $emit-sib:break/disp32 +2752 $emit-sib:check-for-scale: +2753 # if (has-metadata?(word-slice, "scale")) +2754 # . EAX = has-metadata?(ECX, "scale") +2755 # . . push args +2756 68/push "scale"/imm32 +2757 51/push-ECX +2758 # . . call +2759 e8/call has-metadata?/disp32 +2760 # . . discard args +2761 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2762 # . if (EAX == 0) goto next check +2763 3d/compare-EAX-and 0/imm32 +2764 74/jump-if-equal $emit-sib:check-for-base/disp8 +2765 $emit-sib:scale: +2766 # scale = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) +2767 # . EAX = parse-datum-of-word(word-slice) +2768 # . . push args +2769 51/push-ECX +2770 # . . call +2771 e8/call parse-datum-of-word/disp32 +2772 # . . discard args +2773 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2774 # . scale = EAX +2775 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX +2776 # has-sib? = true +2777 ba/copy-to-EDX 1/imm32/true +2778 # continue +2779 e9/jump $emit-sib:loop/disp32 +2780 $emit-sib:check-for-base: +2781 # if (has-metadata?(word-slice, "base")) +2782 # . EAX = has-metadata?(ECX, "base") +2783 # . . push args +2784 68/push "base"/imm32 2785 51/push-ECX -2786 52/push-EDX -2787 53/push-EBX -2788 56/push-ESI -2789 57/push-EDI -2790 # var word-slice/ECX = {0, 0} -2791 68/push 0/imm32/end -2792 68/push 0/imm32/start -2793 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -2794 # var has-sib?/EDX = false -2795 31/xor 3/mod/direct 2/rm32/EDX . . . 2/r32/EDX . . # clear EDX -2796 # var scale/EBX = 0 -2797 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX -2798 # var base/ESI = 0 -2799 31/xor 3/mod/direct 6/rm32/ESI . . . 6/r32/ESI . . # clear ESI -2800 # var index/EDI = 0 -2801 31/xor 3/mod/direct 7/rm32/EDI . . . 7/r32/EDI . . # clear EDI -2802 # rewind-stream(line) -2803 # . . push args -2804 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2805 # . . call -2806 e8/call rewind-stream/disp32 -2807 # . . discard args -2808 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2809 $emit-sib:loop: -2810 +-- 34 lines: #? # dump line ----------------------------------------------------------------------------------------------------------------------------- -2844 # next-word(line, word-slice) -2845 # . . push args -2846 51/push-ECX -2847 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -2848 # . . call -2849 e8/call next-word/disp32 -2850 # . . discard args -2851 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2852 +-- 50 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- -2902 $emit-sib:check0: -2903 # if (slice-empty?(word-slice)) break -2904 # . EAX = slice-empty?(word-slice) -2905 # . . push args -2906 51/push-ECX -2907 # . . call -2908 e8/call slice-empty?/disp32 -2909 # . . discard args -2910 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2911 # . if (EAX != 0) pass through -2912 3d/compare-EAX-and 0/imm32 -2913 0f 85/jump-if-not-equal $emit-sib:break/disp32 -2914 $emit-sib:check1: -2915 # if (slice-starts-with?(word-slice, "#")) break -2916 # . spill EDX -2917 52/push-EDX -2918 # . start/EDX = word-slice->start -2919 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX -2920 # . c/EAX = *start -2921 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -2922 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 0/r32/AL . . # copy byte at *EDX to AL -2923 # . restore EDX -2924 5a/pop-to-EDX -2925 # . if (EAX == '#') pass through -2926 3d/compare-EAX-and 0x23/imm32/hash -2927 0f 84/jump-if-equal $emit-sib:break/disp32 -2928 $emit-sib:check-for-scale: -2929 # if (has-metadata?(word-slice, "scale")) -2930 # . EAX = has-metadata?(ECX, "scale") -2931 # . . push args -2932 68/push "scale"/imm32 -2933 51/push-ECX -2934 # . . call -2935 e8/call has-metadata?/disp32 -2936 # . . discard args -2937 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2938 # . if (EAX == 0) goto next check -2939 3d/compare-EAX-and 0/imm32 -2940 74/jump-if-equal $emit-sib:check-for-base/disp8 -2941 $emit-sib:scale: -2942 # scale = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) -2943 # . EAX = parse-datum-of-word(word-slice) -2944 # . . push args -2945 51/push-ECX -2946 # . . call -2947 e8/call parse-datum-of-word/disp32 -2948 # . . discard args -2949 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2950 # . scale = EAX -2951 89/copy 3/mod/direct 3/rm32/EBX . . . 0/r32/EAX . . # copy EAX to EBX -2952 # has-sib? = true -2953 ba/copy-to-EDX 1/imm32/true -2954 # continue -2955 e9/jump $emit-sib:loop/disp32 -2956 $emit-sib:check-for-base: -2957 # if (has-metadata?(word-slice, "base")) -2958 # . EAX = has-metadata?(ECX, "base") -2959 # . . push args -2960 68/push "base"/imm32 -2961 51/push-ECX -2962 # . . call -2963 e8/call has-metadata?/disp32 -2964 # . . discard args -2965 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2966 # . if (EAX == 0) goto next check -2967 3d/compare-EAX-and 0/imm32 -2968 74/jump-if-equal $emit-sib:check-for-index/disp8 -2969 $emit-sib:base: -2970 # base = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) -2971 # . EAX = parse-datum-of-word(word-slice) -2972 # . . push args -2973 51/push-ECX -2974 # . . call -2975 e8/call parse-datum-of-word/disp32 -2976 # . . discard args -2977 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -2978 # . base = EAX -2979 89/copy 3/mod/direct 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to ESI -2980 # has-sib? = true -2981 ba/copy-to-EDX 1/imm32/true -2982 # continue -2983 e9/jump $emit-sib:loop/disp32 -2984 $emit-sib:check-for-index: -2985 # if (has-metadata?(word-slice, "index")) -2986 # . EAX = has-metadata?(ECX, "index") -2987 # . . push args -2988 68/push "index"/imm32 -2989 51/push-ECX -2990 # . . call -2991 e8/call has-metadata?/disp32 -2992 # . . discard args -2993 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -2994 # . if (EAX == 0) loop -2995 3d/compare-EAX-and 0/imm32 -2996 0f 84/jump-if-equal $emit-sib:loop/disp32 -2997 $emit-sib:index: -2998 # index = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) -2999 # . EAX = parse-datum-of-word(word-slice) -3000 # . . push args -3001 51/push-ECX -3002 # . . call -3003 e8/call parse-datum-of-word/disp32 -3004 # . . discard args -3005 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3006 # . index = EAX -3007 89/copy 3/mod/direct 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to EDI -3008 # has-sib? = true -3009 ba/copy-to-EDX 1/imm32/true -3010 # continue -3011 e9/jump $emit-sib:loop/disp32 -3012 $emit-sib:break: -3013 # if (!has-sib?) return -3014 81 7/subop/compare 3/mod/direct 2/rm32/EDX . . . . . 0/imm32 # compare EDX -3015 74/jump-if-equal $emit-sib:end/disp8 -3016 $emit-sib:calculate: -3017 # sib/EBX = scale & 0b11 -3018 81 4/subop/and 3/mod/direct 3/rm32/EBX . . . . . 3/imm32/0b11 # bitwise and of EBX -3019 # sib <<= 2 -3020 c1/shift 4/subop/left 3/mod/direct 3/rm32/EBX . . . . . 2/imm8 # shift EBX left by 2 bits -3021 # sib |= index & 0b111 -3022 81 4/subop/and 3/mod/direct 7/rm32/EDI . . . . . 7/imm32/0b111 # bitwise and of EDI -3023 09/or 3/mod/direct 3/rm32/EBX . . . 7/r32/EDI . . # EBX = bitwise OR with EDI -3024 # sib <<= 3 -3025 c1/shift 4/subop/left 3/mod/direct 3/rm32/EBX . . . . . 3/imm8 # shift EBX left by 3 bits -3026 # sib |= base & 0b111 -3027 81 4/subop/and 3/mod/direct 6/rm32/ESI . . . . . 7/imm32/0b111 # bitwise and of ESI -3028 09/or 3/mod/direct 3/rm32/EBX . . . 6/r32/ESI . . # EBX = bitwise OR with ESI -3029 $emit-sib:emit: -3030 # emit-hex(out, sib, 1) -3031 # . . push args -3032 68/push 1/imm32 -3033 53/push-EBX -3034 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -3035 # . . call -3036 e8/call emit-hex/disp32 -3037 # . . discard args -3038 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3039 $emit-sib:end: -3040 # . restore locals -3041 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3042 # . restore registers -3043 5f/pop-to-EDI -3044 5e/pop-to-ESI -3045 5b/pop-to-EBX -3046 5a/pop-to-EDX -3047 59/pop-to-ECX -3048 58/pop-to-EAX -3049 # . epilog -3050 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3051 5d/pop-to-EBP -3052 c3/return -3053 -3054 emit-disp: # line : (address stream byte), out : (address buffered-file) -> <void> -3055 # pseudocode: -3056 # rewind-stream(line) -3057 # var word-slice = {0, 0} -3058 # while true -3059 # word-slice = next-word(line) -3060 # if (slice-empty?(word-slice)) break -3061 # if (slice-starts-with?(word-slice, "#")) break -3062 # if has-metadata?(word-slice, "disp32") -3063 # emit(out, word-slice, 4) -3064 # break -3065 # if has-metadata?(word-slice, "disp16") -3066 # emit(out, word-slice, 2) -3067 # break -3068 # if has-metadata?(word-slice, "disp8") -3069 # emit(out, word-slice, 1) -3070 # break -3071 # -3072 # . prolog -3073 55/push-EBP -3074 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3075 # . save registers -3076 50/push-EAX -3077 51/push-ECX -3078 52/push-EDX -3079 # var word-slice/ECX = {0, 0} -3080 68/push 0/imm32/end -3081 68/push 0/imm32/start -3082 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -3083 # rewind-stream(line) -3084 # . . push args -3085 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -3086 # . . call -3087 e8/call rewind-stream/disp32 -3088 # . . discard args -3089 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3090 +-- 34 lines: #? # dump line ----------------------------------------------------------------------------------------------------------------------------- -3124 $emit-disp:loop: -3125 # next-word(line, word-slice) -3126 # . . push args -3127 51/push-ECX -3128 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -3129 # . . call -3130 e8/call next-word/disp32 -3131 # . . discard args -3132 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3133 +-- 50 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- -3183 $emit-disp:check0: -3184 # if (slice-empty?(word-slice)) break -3185 # . EAX = slice-empty?(word-slice) -3186 # . . push args -3187 51/push-ECX -3188 # . . call -3189 e8/call slice-empty?/disp32 -3190 # . . discard args -3191 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3192 # . if (EAX != 0) pass through -3193 3d/compare-EAX-and 0/imm32 -3194 0f 85/jump-if-not-equal $emit-disp:break/disp32 -3195 $emit-disp:check1: -3196 # if (slice-starts-with?(word-slice, "#")) break -3197 # . start/EDX = word-slice->start -3198 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX -3199 # . c/EAX = *start -3200 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -3201 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 0/r32/AL . . # copy byte at *EDX to AL -3202 # . if (EAX == '#') break -3203 3d/compare-EAX-and 0x23/imm32/hash -3204 0f 84/jump-if-equal $emit-disp:break/disp32 -3205 $emit-disp:check-for-disp32: -3206 # if (has-metadata?(word-slice, "disp32")) -3207 # . EAX = has-metadata?(ECX, "disp32") -3208 # . . push args -3209 68/push "disp32"/imm32 -3210 51/push-ECX -3211 # . . call -3212 e8/call has-metadata?/disp32 -3213 # . . discard args -3214 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3215 # . if (EAX == 0) goto next check -3216 3d/compare-EAX-and 0/imm32 -3217 74/jump-if-equal $emit-disp:check-for-disp16/disp8 -3218 $emit-disp:disp32: -3219 # emit(out, word-slice, 4) -3220 # . . push args -3221 68/push 4/imm32 -3222 51/push-ECX -3223 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -3224 # . . call -3225 e8/call emit/disp32 -3226 # . . discard args -3227 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3228 # break -3229 e9/jump $emit-disp:break/disp32 -3230 $emit-disp:check-for-disp16: -3231 # else if (has-metadata?(word-slice, "disp16")) -3232 # . EAX = has-metadata?(ECX, "disp16") -3233 # . . push args -3234 68/push "disp16"/imm32 -3235 51/push-ECX -3236 # . . call -3237 e8/call has-metadata?/disp32 -3238 # . . discard args -3239 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3240 # . if (EAX == 0) goto next check -3241 3d/compare-EAX-and 0/imm32 -3242 74/jump-if-equal $emit-disp:check-for-disp8/disp8 -3243 $emit-disp:disp16: -3244 # emit(out, word-slice, 2) -3245 # . . push args -3246 68/push 2/imm32 -3247 51/push-ECX -3248 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -3249 # . . call -3250 e8/call emit/disp32 -3251 # . . discard args -3252 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3253 # break -3254 e9/jump $emit-disp:break/disp32 -3255 $emit-disp:check-for-disp8: -3256 # if (has-metadata?(word-slice, "disp8")) -3257 # . EAX = has-metadata?(ECX, "disp8") -3258 # . . push args -3259 68/push "disp8"/imm32 -3260 51/push-ECX -3261 # . . call -3262 e8/call has-metadata?/disp32 -3263 # . . discard args -3264 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3265 # . if (EAX == 0) loop -3266 3d/compare-EAX-and 0/imm32 -3267 0f 84/jump-if-equal $emit-disp:loop/disp32 -3268 $emit-disp:disp8: -3269 # emit(out, word-slice, 1) -3270 # . . push args -3271 68/push 1/imm32 -3272 51/push-ECX -3273 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -3274 # . . call -3275 e8/call emit/disp32 -3276 # . . discard args -3277 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3278 # break -3279 $emit-disp:break: -3280 # . restore locals -3281 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3282 # . restore registers -3283 5a/pop-to-EDX -3284 59/pop-to-ECX -3285 58/pop-to-EAX -3286 # . epilog -3287 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3288 5d/pop-to-EBP -3289 c3/return -3290 -3291 emit-imm: # line : (address stream byte), out : (address buffered-file) -> <void> -3292 # pseudocode: -3293 # rewind-stream(line) -3294 # var word-slice = {0, 0} -3295 # while true -3296 # word-slice = next-word(line) -3297 # if (slice-empty?(word-slice)) break -3298 # if (slice-starts-with?(word-slice, "#")) break -3299 # if has-metadata?(word-slice, "imm32") -3300 # emit(out, word-slice, 4) -3301 # break -3302 # if has-metadata?(word-slice, "imm16") -3303 # emit(out, word-slice, 2) -3304 # break -3305 # if has-metadata?(word-slice, "imm8") -3306 # emit(out, word-slice, 1) -3307 # break -3308 # -3309 # . prolog -3310 55/push-EBP -3311 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3312 # . save registers -3313 50/push-EAX -3314 51/push-ECX -3315 52/push-EDX -3316 # var word-slice/ECX = {0, 0} -3317 68/push 0/imm32/end -3318 68/push 0/imm32/start -3319 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -3320 # rewind-stream(line) -3321 # . . push args -3322 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -3323 # . . call -3324 e8/call rewind-stream/disp32 -3325 # . . discard args -3326 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3327 +-- 34 lines: #? # dump line ----------------------------------------------------------------------------------------------------------------------------- -3361 $emit-imm:loop: -3362 # next-word(line, word-slice) -3363 # . . push args -3364 51/push-ECX -3365 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -3366 # . . call -3367 e8/call next-word/disp32 -3368 # . . discard args -3369 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3370 +-- 50 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- -3420 $emit-imm:check0: -3421 # if (slice-empty?(word-slice)) break -3422 # . EAX = slice-empty?(word-slice) -3423 # . . push args -3424 51/push-ECX -3425 # . . call -3426 e8/call slice-empty?/disp32 -3427 # . . discard args -3428 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3429 # . if (EAX != 0) pass through -3430 3d/compare-EAX-and 0/imm32 -3431 0f 85/jump-if-not-equal $emit-imm:break/disp32 -3432 $emit-imm:check1: -3433 # if (slice-starts-with?(word-slice, "#")) break -3434 # . start/EDX = slice->start -3435 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX -3436 # . c/EAX = *start -3437 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -3438 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 0/r32/AL . . # copy byte at *EDX to AL -3439 # . if (EAX == '#') break -3440 3d/compare-EAX-and 0x23/imm32/hash -3441 0f 84/jump-if-equal $emit-imm:break/disp32 -3442 $emit-imm:check-for-imm32: -3443 # if (has-metadata?(word-slice, "imm32")) -3444 # . EAX = has-metadata?(ECX, "imm32") +2786 # . . call +2787 e8/call has-metadata?/disp32 +2788 # . . discard args +2789 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2790 # . if (EAX == 0) goto next check +2791 3d/compare-EAX-and 0/imm32 +2792 74/jump-if-equal $emit-sib:check-for-index/disp8 +2793 $emit-sib:base: +2794 # base = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) +2795 # . EAX = parse-datum-of-word(word-slice) +2796 # . . push args +2797 51/push-ECX +2798 # . . call +2799 e8/call parse-datum-of-word/disp32 +2800 # . . discard args +2801 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2802 # . base = EAX +2803 89/copy 3/mod/direct 6/rm32/ESI . . . 0/r32/EAX . . # copy EAX to ESI +2804 # has-sib? = true +2805 ba/copy-to-EDX 1/imm32/true +2806 # continue +2807 e9/jump $emit-sib:loop/disp32 +2808 $emit-sib:check-for-index: +2809 # if (has-metadata?(word-slice, "index")) +2810 # . EAX = has-metadata?(ECX, "index") +2811 # . . push args +2812 68/push "index"/imm32 +2813 51/push-ECX +2814 # . . call +2815 e8/call has-metadata?/disp32 +2816 # . . discard args +2817 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2818 # . if (EAX == 0) loop +2819 3d/compare-EAX-and 0/imm32 +2820 0f 84/jump-if-equal $emit-sib:loop/disp32 +2821 $emit-sib:index: +2822 # index = parse-hex-int(next-token-from-slice(word-slice->start, word-slice->end, '/')) +2823 # . EAX = parse-datum-of-word(word-slice) +2824 # . . push args +2825 51/push-ECX +2826 # . . call +2827 e8/call parse-datum-of-word/disp32 +2828 # . . discard args +2829 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2830 # . index = EAX +2831 89/copy 3/mod/direct 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to EDI +2832 # has-sib? = true +2833 ba/copy-to-EDX 1/imm32/true +2834 # continue +2835 e9/jump $emit-sib:loop/disp32 +2836 $emit-sib:break: +2837 # if (!has-sib?) return +2838 81 7/subop/compare 3/mod/direct 2/rm32/EDX . . . . . 0/imm32 # compare EDX +2839 74/jump-if-equal $emit-sib:end/disp8 +2840 $emit-sib:calculate: +2841 # sib/EBX = scale & 0b11 +2842 81 4/subop/and 3/mod/direct 3/rm32/EBX . . . . . 3/imm32/0b11 # bitwise and of EBX +2843 # sib <<= 2 +2844 c1/shift 4/subop/left 3/mod/direct 3/rm32/EBX . . . . . 2/imm8 # shift EBX left by 2 bits +2845 # sib |= index & 0b111 +2846 81 4/subop/and 3/mod/direct 7/rm32/EDI . . . . . 7/imm32/0b111 # bitwise and of EDI +2847 09/or 3/mod/direct 3/rm32/EBX . . . 7/r32/EDI . . # EBX = bitwise OR with EDI +2848 # sib <<= 3 +2849 c1/shift 4/subop/left 3/mod/direct 3/rm32/EBX . . . . . 3/imm8 # shift EBX left by 3 bits +2850 # sib |= base & 0b111 +2851 81 4/subop/and 3/mod/direct 6/rm32/ESI . . . . . 7/imm32/0b111 # bitwise and of ESI +2852 09/or 3/mod/direct 3/rm32/EBX . . . 6/r32/ESI . . # EBX = bitwise OR with ESI +2853 $emit-sib:emit: +2854 # emit-hex(out, sib, 1) +2855 # . . push args +2856 68/push 1/imm32 +2857 53/push-EBX +2858 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +2859 # . . call +2860 e8/call emit-hex/disp32 +2861 # . . discard args +2862 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +2863 $emit-sib:end: +2864 # . restore locals +2865 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2866 # . restore registers +2867 5f/pop-to-EDI +2868 5e/pop-to-ESI +2869 5b/pop-to-EBX +2870 5a/pop-to-EDX +2871 59/pop-to-ECX +2872 58/pop-to-EAX +2873 # . epilog +2874 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +2875 5d/pop-to-EBP +2876 c3/return +2877 +2878 emit-disp: # line : (address stream byte), out : (address buffered-file) -> <void> +2879 # pseudocode: +2880 # rewind-stream(line) +2881 # var word-slice = {0, 0} +2882 # while true +2883 # word-slice = next-word(line) +2884 # if (slice-empty?(word-slice)) break +2885 # if (slice-starts-with?(word-slice, "#")) break +2886 # if has-metadata?(word-slice, "disp32") +2887 # emit(out, word-slice, 4) +2888 # break +2889 # if has-metadata?(word-slice, "disp16") +2890 # emit(out, word-slice, 2) +2891 # break +2892 # if has-metadata?(word-slice, "disp8") +2893 # emit(out, word-slice, 1) +2894 # break +2895 # +2896 # . prolog +2897 55/push-EBP +2898 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +2899 # . save registers +2900 50/push-EAX +2901 51/push-ECX +2902 52/push-EDX +2903 # var word-slice/ECX = {0, 0} +2904 68/push 0/imm32/end +2905 68/push 0/imm32/start +2906 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +2907 # rewind-stream(line) +2908 # . . push args +2909 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2910 # . . call +2911 e8/call rewind-stream/disp32 +2912 # . . discard args +2913 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +2914 +-- 26 lines: #? # dump line ----------------------------------------------------------------------------------------------------------------------------- +2940 $emit-disp:loop: +2941 # next-word(line, word-slice) +2942 # . . push args +2943 51/push-ECX +2944 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +2945 # . . call +2946 e8/call next-word/disp32 +2947 # . . discard args +2948 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +2949 +-- 42 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- +2991 $emit-disp:check0: +2992 # if (slice-empty?(word-slice)) break +2993 # . EAX = slice-empty?(word-slice) +2994 # . . push args +2995 51/push-ECX +2996 # . . call +2997 e8/call slice-empty?/disp32 +2998 # . . discard args +2999 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3000 # . if (EAX != 0) pass through +3001 3d/compare-EAX-and 0/imm32 +3002 0f 85/jump-if-not-equal $emit-disp:break/disp32 +3003 $emit-disp:check1: +3004 # if (slice-starts-with?(word-slice, "#")) break +3005 # . start/EDX = word-slice->start +3006 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX +3007 # . c/EAX = *start +3008 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +3009 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 0/r32/AL . . # copy byte at *EDX to AL +3010 # . if (EAX == '#') break +3011 3d/compare-EAX-and 0x23/imm32/hash +3012 0f 84/jump-if-equal $emit-disp:break/disp32 +3013 $emit-disp:check-for-disp32: +3014 # if (has-metadata?(word-slice, "disp32")) +3015 # . EAX = has-metadata?(ECX, "disp32") +3016 # . . push args +3017 68/push "disp32"/imm32 +3018 51/push-ECX +3019 # . . call +3020 e8/call has-metadata?/disp32 +3021 # . . discard args +3022 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3023 # . if (EAX == 0) goto next check +3024 3d/compare-EAX-and 0/imm32 +3025 74/jump-if-equal $emit-disp:check-for-disp16/disp8 +3026 $emit-disp:disp32: +3027 # emit(out, word-slice, 4) +3028 # . . push args +3029 68/push 4/imm32 +3030 51/push-ECX +3031 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +3032 # . . call +3033 e8/call emit/disp32 +3034 # . . discard args +3035 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3036 # break +3037 e9/jump $emit-disp:break/disp32 +3038 $emit-disp:check-for-disp16: +3039 # else if (has-metadata?(word-slice, "disp16")) +3040 # . EAX = has-metadata?(ECX, "disp16") +3041 # . . push args +3042 68/push "disp16"/imm32 +3043 51/push-ECX +3044 # . . call +3045 e8/call has-metadata?/disp32 +3046 # . . discard args +3047 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3048 # . if (EAX == 0) goto next check +3049 3d/compare-EAX-and 0/imm32 +3050 74/jump-if-equal $emit-disp:check-for-disp8/disp8 +3051 $emit-disp:disp16: +3052 # emit(out, word-slice, 2) +3053 # . . push args +3054 68/push 2/imm32 +3055 51/push-ECX +3056 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +3057 # . . call +3058 e8/call emit/disp32 +3059 # . . discard args +3060 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3061 # break +3062 e9/jump $emit-disp:break/disp32 +3063 $emit-disp:check-for-disp8: +3064 # if (has-metadata?(word-slice, "disp8")) +3065 # . EAX = has-metadata?(ECX, "disp8") +3066 # . . push args +3067 68/push "disp8"/imm32 +3068 51/push-ECX +3069 # . . call +3070 e8/call has-metadata?/disp32 +3071 # . . discard args +3072 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3073 # . if (EAX == 0) loop +3074 3d/compare-EAX-and 0/imm32 +3075 0f 84/jump-if-equal $emit-disp:loop/disp32 +3076 $emit-disp:disp8: +3077 # emit(out, word-slice, 1) +3078 # . . push args +3079 68/push 1/imm32 +3080 51/push-ECX +3081 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +3082 # . . call +3083 e8/call emit/disp32 +3084 # . . discard args +3085 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3086 # break +3087 $emit-disp:break: +3088 # . restore locals +3089 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3090 # . restore registers +3091 5a/pop-to-EDX +3092 59/pop-to-ECX +3093 58/pop-to-EAX +3094 # . epilog +3095 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3096 5d/pop-to-EBP +3097 c3/return +3098 +3099 emit-imm: # line : (address stream byte), out : (address buffered-file) -> <void> +3100 # pseudocode: +3101 # rewind-stream(line) +3102 # var word-slice = {0, 0} +3103 # while true +3104 # word-slice = next-word(line) +3105 # if (slice-empty?(word-slice)) break +3106 # if (slice-starts-with?(word-slice, "#")) break +3107 # if has-metadata?(word-slice, "imm32") +3108 # emit(out, word-slice, 4) +3109 # break +3110 # if has-metadata?(word-slice, "imm16") +3111 # emit(out, word-slice, 2) +3112 # break +3113 # if has-metadata?(word-slice, "imm8") +3114 # emit(out, word-slice, 1) +3115 # break +3116 # +3117 # . prolog +3118 55/push-EBP +3119 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3120 # . save registers +3121 50/push-EAX +3122 51/push-ECX +3123 52/push-EDX +3124 # var word-slice/ECX = {0, 0} +3125 68/push 0/imm32/end +3126 68/push 0/imm32/start +3127 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +3128 # rewind-stream(line) +3129 # . . push args +3130 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +3131 # . . call +3132 e8/call rewind-stream/disp32 +3133 # . . discard args +3134 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3135 +-- 26 lines: #? # dump line ----------------------------------------------------------------------------------------------------------------------------- +3161 $emit-imm:loop: +3162 # next-word(line, word-slice) +3163 # . . push args +3164 51/push-ECX +3165 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +3166 # . . call +3167 e8/call next-word/disp32 +3168 # . . discard args +3169 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3170 +-- 42 lines: #? # dump word-slice ----------------------------------------------------------------------------------------------------------------------- +3212 $emit-imm:check0: +3213 # if (slice-empty?(word-slice)) break +3214 # . EAX = slice-empty?(word-slice) +3215 # . . push args +3216 51/push-ECX +3217 # . . call +3218 e8/call slice-empty?/disp32 +3219 # . . discard args +3220 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3221 # . if (EAX != 0) pass through +3222 3d/compare-EAX-and 0/imm32 +3223 0f 85/jump-if-not-equal $emit-imm:break/disp32 +3224 $emit-imm:check1: +3225 # if (slice-starts-with?(word-slice, "#")) break +3226 # . start/EDX = slice->start +3227 8b/copy 0/mod/indirect 1/rm32/ECX . . . 2/r32/EDX . . # copy *ECX to EDX +3228 # . c/EAX = *start +3229 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +3230 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 0/r32/AL . . # copy byte at *EDX to AL +3231 # . if (EAX == '#') break +3232 3d/compare-EAX-and 0x23/imm32/hash +3233 0f 84/jump-if-equal $emit-imm:break/disp32 +3234 $emit-imm:check-for-imm32: +3235 # if (has-metadata?(word-slice, "imm32")) +3236 # . EAX = has-metadata?(ECX, "imm32") +3237 # . . push args +3238 68/push "imm32"/imm32 +3239 51/push-ECX +3240 # . . call +3241 e8/call has-metadata?/disp32 +3242 # . . discard args +3243 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3244 # . if (EAX == 0) goto next check +3245 3d/compare-EAX-and 0/imm32 +3246 74/jump-if-equal $emit-imm:check-for-imm16/disp8 +3247 $emit-imm:imm32: +3248 # emit(out, word-slice, 4) +3249 # . . push args +3250 68/push 4/imm32 +3251 51/push-ECX +3252 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +3253 # . . call +3254 e8/call emit/disp32 +3255 # . . discard args +3256 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3257 # break +3258 e9/jump $emit-imm:break/disp32 +3259 $emit-imm:check-for-imm16: +3260 # if (has-metadata?(word-slice, "imm16")) +3261 # . EAX = has-metadata?(ECX, "imm16") +3262 # . . push args +3263 68/push "imm16"/imm32 +3264 51/push-ECX +3265 # . . call +3266 e8/call has-metadata?/disp32 +3267 # . . discard args +3268 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3269 # . if (EAX == 0) goto next check +3270 3d/compare-EAX-and 0/imm32 +3271 74/jump-if-equal $emit-imm:check-for-imm8/disp8 +3272 $emit-imm:imm16: +3273 # emit(out, word-slice, 2) +3274 # . . push args +3275 68/push 2/imm32 +3276 51/push-ECX +3277 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +3278 # . . call +3279 e8/call emit/disp32 +3280 # . . discard args +3281 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3282 # break +3283 e9/jump $emit-imm:break/disp32 +3284 $emit-imm:check-for-imm8: +3285 # if (has-metadata?(word-slice, "imm8")) +3286 # . EAX = has-metadata?(ECX, "imm8") +3287 # . . push args +3288 68/push "imm8"/imm32 +3289 51/push-ECX +3290 # . . call +3291 e8/call has-metadata?/disp32 +3292 # . . discard args +3293 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3294 # . if (EAX == 0) loop +3295 3d/compare-EAX-and 0/imm32 +3296 0f 84/jump-if-equal $emit-imm:loop/disp32 +3297 $emit-imm:imm8: +3298 # emit(out, word-slice, 1) +3299 # . . push args +3300 68/push 1/imm32 +3301 51/push-ECX +3302 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +3303 # . . call +3304 e8/call emit/disp32 +3305 # . . discard args +3306 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3307 # break +3308 $emit-imm:break: +3309 # . restore locals +3310 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3311 # . restore registers +3312 5a/pop-to-EDX +3313 59/pop-to-ECX +3314 58/pop-to-EAX +3315 # . epilog +3316 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3317 5d/pop-to-EBP +3318 c3/return +3319 +3320 emit-line-in-comment: # line : (address stream byte), out : (address buffered-file) -> <void> +3321 # . prolog +3322 55/push-EBP +3323 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3324 # write-buffered(out, " # ") +3325 # . . push args +3326 68/push " # "/imm32 +3327 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +3328 # . . call +3329 e8/call write-buffered/disp32 +3330 # . . discard args +3331 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3332 # write-stream-data(out, line) +3333 # . . push args +3334 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +3335 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +3336 # . . call +3337 e8/call write-stream-data/disp32 +3338 # . . discard args +3339 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3340 $emit-line-in-comment:end: +3341 # . epilog +3342 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3343 5d/pop-to-EBP +3344 c3/return +3345 +3346 test-convert-instruction-passes-comments-through: +3347 # if a line starts with '#', pass it along unchanged +3348 # . prolog +3349 55/push-EBP +3350 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3351 # setup +3352 # . clear-stream(_test-input-stream) +3353 # . . push args +3354 68/push _test-input-stream/imm32 +3355 # . . call +3356 e8/call clear-stream/disp32 +3357 # . . discard args +3358 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3359 # . clear-stream(_test-output-stream) +3360 # . . push args +3361 68/push _test-output-stream/imm32 +3362 # . . call +3363 e8/call clear-stream/disp32 +3364 # . . discard args +3365 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3366 # . clear-stream(_test-output-buffered-file+4) +3367 # . . push args +3368 b8/copy-to-EAX _test-output-buffered-file/imm32 +3369 05/add-to-EAX 4/imm32 +3370 50/push-EAX +3371 # . . call +3372 e8/call clear-stream/disp32 +3373 # . . discard args +3374 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3375 # initialize input +3376 # . write(_test-input-stream, "# abcd") +3377 # . . push args +3378 68/push "# abcd"/imm32 +3379 68/push _test-input-stream/imm32 +3380 # . . call +3381 e8/call write/disp32 +3382 # . . discard args +3383 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3384 # convert-instruction(_test-input-stream, _test-output-buffered-file) +3385 # . . push args +3386 68/push _test-output-buffered-file/imm32 +3387 68/push _test-input-stream/imm32 +3388 # . . call +3389 e8/call convert-instruction/disp32 +3390 # . . discard args +3391 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3392 # check that the line just passed through +3393 # . flush(_test-output-buffered-file) +3394 # . . push args +3395 68/push _test-output-buffered-file/imm32 +3396 # . . call +3397 e8/call flush/disp32 +3398 # . . discard args +3399 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3400 # . check-stream-equal(_test-output-stream, "# abcd", msg) +3401 # . . push args +3402 68/push "F - test-convert-instruction-passes-comments-through"/imm32 +3403 68/push "# abcd"/imm32 +3404 68/push _test-output-stream/imm32 +3405 # . . call +3406 e8/call check-stream-equal/disp32 +3407 # . . discard args +3408 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3409 # . epilog +3410 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3411 5d/pop-to-EBP +3412 c3/return +3413 +3414 test-convert-instruction-passes-labels-through: +3415 # if the first word ends with ':', pass along the entire line unchanged +3416 # . prolog +3417 55/push-EBP +3418 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3419 # setup +3420 # . clear-stream(_test-input-stream) +3421 # . . push args +3422 68/push _test-input-stream/imm32 +3423 # . . call +3424 e8/call clear-stream/disp32 +3425 # . . discard args +3426 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3427 # . clear-stream(_test-output-stream) +3428 # . . push args +3429 68/push _test-output-stream/imm32 +3430 # . . call +3431 e8/call clear-stream/disp32 +3432 # . . discard args +3433 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3434 # . clear-stream(_test-output-buffered-file+4) +3435 # . . push args +3436 b8/copy-to-EAX _test-output-buffered-file/imm32 +3437 05/add-to-EAX 4/imm32 +3438 50/push-EAX +3439 # . . call +3440 e8/call clear-stream/disp32 +3441 # . . discard args +3442 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3443 # initialize input +3444 # . write(_test-input-stream, "ab: # cd") 3445 # . . push args -3446 68/push "imm32"/imm32 -3447 51/push-ECX +3446 68/push "ab: # cd"/imm32 +3447 68/push _test-input-stream/imm32 3448 # . . call -3449 e8/call has-metadata?/disp32 +3449 e8/call write/disp32 3450 # . . discard args 3451 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3452 # . if (EAX == 0) goto next check -3453 3d/compare-EAX-and 0/imm32 -3454 74/jump-if-equal $emit-imm:check-for-imm16/disp8 -3455 $emit-imm:imm32: -3456 # emit(out, word-slice, 4) -3457 # . . push args -3458 68/push 4/imm32 -3459 51/push-ECX -3460 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -3461 # . . call -3462 e8/call emit/disp32 -3463 # . . discard args -3464 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3465 # break -3466 e9/jump $emit-imm:break/disp32 -3467 $emit-imm:check-for-imm16: -3468 # if (has-metadata?(word-slice, "imm16")) -3469 # . EAX = has-metadata?(ECX, "imm16") -3470 # . . push args -3471 68/push "imm16"/imm32 -3472 51/push-ECX +3452 # convert-instruction(_test-input-stream, _test-output-buffered-file) +3453 # . . push args +3454 68/push _test-output-buffered-file/imm32 +3455 68/push _test-input-stream/imm32 +3456 # . . call +3457 e8/call convert-instruction/disp32 +3458 # . . discard args +3459 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3460 # check that the line just passed through +3461 # . flush(_test-output-buffered-file) +3462 # . . push args +3463 68/push _test-output-buffered-file/imm32 +3464 # . . call +3465 e8/call flush/disp32 +3466 # . . discard args +3467 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3468 # . check-stream-equal(_test-output-stream, "ab: # cd", msg) +3469 # . . push args +3470 68/push "F - test-convert-instruction-passes-labels-through"/imm32 +3471 68/push "ab: # cd"/imm32 +3472 68/push _test-output-stream/imm32 3473 # . . call -3474 e8/call has-metadata?/disp32 +3474 e8/call check-stream-equal/disp32 3475 # . . discard args -3476 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3477 # . if (EAX == 0) goto next check -3478 3d/compare-EAX-and 0/imm32 -3479 74/jump-if-equal $emit-imm:check-for-imm8/disp8 -3480 $emit-imm:imm16: -3481 # emit(out, word-slice, 2) -3482 # . . push args -3483 68/push 2/imm32 -3484 51/push-ECX -3485 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -3486 # . . call -3487 e8/call emit/disp32 -3488 # . . discard args -3489 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3490 # break -3491 e9/jump $emit-imm:break/disp32 -3492 $emit-imm:check-for-imm8: -3493 # if (has-metadata?(word-slice, "imm8")) -3494 # . EAX = has-metadata?(ECX, "imm8") -3495 # . . push args -3496 68/push "imm8"/imm32 -3497 51/push-ECX +3476 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3477 # . epilog +3478 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3479 5d/pop-to-EBP +3480 c3/return +3481 +3482 test-convert-instruction-handles-single-opcode: +3483 # if the instruction consists of a single opcode, strip its metadata and pass it along +3484 # . prolog +3485 55/push-EBP +3486 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3487 # setup +3488 # . clear-stream(_test-input-stream) +3489 # . . push args +3490 68/push _test-input-stream/imm32 +3491 # . . call +3492 e8/call clear-stream/disp32 +3493 # . . discard args +3494 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3495 # . clear-stream(_test-output-stream) +3496 # . . push args +3497 68/push _test-output-stream/imm32 3498 # . . call -3499 e8/call has-metadata?/disp32 +3499 e8/call clear-stream/disp32 3500 # . . discard args -3501 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3502 # . if (EAX == 0) loop -3503 3d/compare-EAX-and 0/imm32 -3504 0f 84/jump-if-equal $emit-imm:loop/disp32 -3505 $emit-imm:imm8: -3506 # emit(out, word-slice, 1) -3507 # . . push args -3508 68/push 1/imm32 -3509 51/push-ECX -3510 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -3511 # . . call -3512 e8/call emit/disp32 -3513 # . . discard args -3514 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3515 # break -3516 $emit-imm:break: -3517 # . restore locals -3518 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3519 # . restore registers -3520 5a/pop-to-EDX -3521 59/pop-to-ECX -3522 58/pop-to-EAX -3523 # . epilog -3524 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3525 5d/pop-to-EBP -3526 c3/return -3527 -3528 emit-line-in-comment: # line : (address stream byte), out : (address buffered-file) -> <void> -3529 # . prolog -3530 55/push-EBP -3531 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3532 # write-buffered(out, " # ") -3533 # . . push args -3534 68/push " # "/imm32 -3535 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -3536 # . . call -3537 e8/call write-buffered/disp32 -3538 # . . discard args -3539 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3540 # write-stream-data(out, line) -3541 # . . push args -3542 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -3543 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -3544 # . . call -3545 e8/call write-stream-data/disp32 -3546 # . . discard args -3547 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3548 $emit-line-in-comment:end: -3549 # . epilog -3550 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3551 5d/pop-to-EBP -3552 c3/return -3553 -3554 test-convert-instruction-passes-comments-through: -3555 # if a line starts with '#', pass it along unchanged -3556 # . prolog -3557 55/push-EBP -3558 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3559 # setup -3560 # . clear-stream(_test-input-stream) -3561 # . . push args -3562 68/push _test-input-stream/imm32 -3563 # . . call -3564 e8/call clear-stream/disp32 -3565 # . . discard args -3566 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3567 # . clear-stream(_test-output-stream) -3568 # . . push args -3569 68/push _test-output-stream/imm32 -3570 # . . call -3571 e8/call clear-stream/disp32 -3572 # . . discard args -3573 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3574 # . clear-stream(_test-output-buffered-file+4) -3575 # . . push args -3576 b8/copy-to-EAX _test-output-buffered-file/imm32 -3577 05/add-to-EAX 4/imm32 -3578 50/push-EAX -3579 # . . call -3580 e8/call clear-stream/disp32 -3581 # . . discard args -3582 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3583 # initialize input -3584 # . write(_test-input-stream, "# abcd") -3585 # . . push args -3586 68/push "# abcd"/imm32 -3587 68/push _test-input-stream/imm32 -3588 # . . call -3589 e8/call write/disp32 -3590 # . . discard args -3591 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3592 # convert-instruction(_test-input-stream, _test-output-buffered-file) -3593 # . . push args -3594 68/push _test-output-buffered-file/imm32 -3595 68/push _test-input-stream/imm32 -3596 # . . call -3597 e8/call convert-instruction/disp32 -3598 # . . discard args -3599 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3600 # check that the line just passed through -3601 # . flush(_test-output-buffered-file) -3602 # . . push args -3603 68/push _test-output-buffered-file/imm32 -3604 # . . call -3605 e8/call flush/disp32 -3606 # . . discard args -3607 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3608 # . check-stream-equal(_test-output-stream, "# abcd", msg) -3609 # . . push args -3610 68/push "F - test-convert-instruction-passes-comments-through"/imm32 -3611 68/push "# abcd"/imm32 -3612 68/push _test-output-stream/imm32 -3613 # . . call -3614 e8/call check-stream-equal/disp32 -3615 # . . discard args -3616 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3617 # . epilog -3618 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3619 5d/pop-to-EBP -3620 c3/return -3621 -3622 test-convert-instruction-passes-labels-through: -3623 # if the first word ends with ':', pass along the entire line unchanged -3624 # . prolog -3625 55/push-EBP -3626 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3627 # setup -3628 # . clear-stream(_test-input-stream) -3629 # . . push args -3630 68/push _test-input-stream/imm32 -3631 # . . call -3632 e8/call clear-stream/disp32 -3633 # . . discard args -3634 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3635 # . clear-stream(_test-output-stream) -3636 # . . push args -3637 68/push _test-output-stream/imm32 -3638 # . . call -3639 e8/call clear-stream/disp32 -3640 # . . discard args -3641 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3642 # . clear-stream(_test-output-buffered-file+4) -3643 # . . push args -3644 b8/copy-to-EAX _test-output-buffered-file/imm32 -3645 05/add-to-EAX 4/imm32 -3646 50/push-EAX -3647 # . . call -3648 e8/call clear-stream/disp32 -3649 # . . discard args -3650 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3651 # initialize input -3652 # . write(_test-input-stream, "ab: # cd") -3653 # . . push args -3654 68/push "ab: # cd"/imm32 -3655 68/push _test-input-stream/imm32 -3656 # . . call -3657 e8/call write/disp32 -3658 # . . discard args -3659 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3660 # convert-instruction(_test-input-stream, _test-output-buffered-file) -3661 # . . push args -3662 68/push _test-output-buffered-file/imm32 -3663 68/push _test-input-stream/imm32 -3664 # . . call -3665 e8/call convert-instruction/disp32 -3666 # . . discard args -3667 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3668 # check that the line just passed through -3669 # . flush(_test-output-buffered-file) -3670 # . . push args -3671 68/push _test-output-buffered-file/imm32 -3672 # . . call -3673 e8/call flush/disp32 -3674 # . . discard args -3675 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3676 # . check-stream-equal(_test-output-stream, "ab: # cd", msg) +3501 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3502 # . clear-stream(_test-output-buffered-file+4) +3503 # . . push args +3504 b8/copy-to-EAX _test-output-buffered-file/imm32 +3505 05/add-to-EAX 4/imm32 +3506 50/push-EAX +3507 # . . call +3508 e8/call clear-stream/disp32 +3509 # . . discard args +3510 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3511 # initialize input +3512 # . write(_test-input-stream, "ab/cd # comment") +3513 # . . push args +3514 68/push "ab/cd # comment"/imm32 +3515 68/push _test-input-stream/imm32 +3516 # . . call +3517 e8/call write/disp32 +3518 # . . discard args +3519 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3520 # convert-instruction(_test-input-stream, _test-output-buffered-file) +3521 # . . push args +3522 68/push _test-output-buffered-file/imm32 +3523 68/push _test-input-stream/imm32 +3524 # . . call +3525 e8/call convert-instruction/disp32 +3526 # . . discard args +3527 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3528 # check output +3529 # . flush(_test-output-buffered-file) +3530 # . . push args +3531 68/push _test-output-buffered-file/imm32 +3532 # . . call +3533 e8/call flush/disp32 +3534 # . . discard args +3535 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3536 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +3562 # . check-stream-equal(_test-output-stream, "ab # ab/cd # comment", msg) +3563 # . . push args +3564 68/push "F - test-convert-instruction-handles-single-opcode"/imm32 +3565 68/push "ab # ab/cd # comment"/imm32 +3566 68/push _test-output-stream/imm32 +3567 # . . call +3568 e8/call check-stream-equal/disp32 +3569 # . . discard args +3570 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3571 # . epilog +3572 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3573 5d/pop-to-EBP +3574 c3/return +3575 +3576 test-convert-instruction-handles-0f-opcode: +3577 # if the instruction starts with 0f opcode, include a second opcode +3578 # . prolog +3579 55/push-EBP +3580 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3581 # setup +3582 # . clear-stream(_test-input-stream) +3583 # . . push args +3584 68/push _test-input-stream/imm32 +3585 # . . call +3586 e8/call clear-stream/disp32 +3587 # . . discard args +3588 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3589 # . clear-stream(_test-output-stream) +3590 # . . push args +3591 68/push _test-output-stream/imm32 +3592 # . . call +3593 e8/call clear-stream/disp32 +3594 # . . discard args +3595 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3596 # . clear-stream(_test-output-buffered-file+4) +3597 # . . push args +3598 b8/copy-to-EAX _test-output-buffered-file/imm32 +3599 05/add-to-EAX 4/imm32 +3600 50/push-EAX +3601 # . . call +3602 e8/call clear-stream/disp32 +3603 # . . discard args +3604 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3605 # initialize input +3606 # . write(_test-input-stream, "0f/m1 ab/m2 # comment") +3607 # . . push args +3608 68/push "0f/m1 ab/m2 # comment"/imm32 +3609 68/push _test-input-stream/imm32 +3610 # . . call +3611 e8/call write/disp32 +3612 # . . discard args +3613 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3614 # convert-instruction(_test-input-stream, _test-output-buffered-file) +3615 # . . push args +3616 68/push _test-output-buffered-file/imm32 +3617 68/push _test-input-stream/imm32 +3618 # . . call +3619 e8/call convert-instruction/disp32 +3620 # . . discard args +3621 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3622 # check output +3623 # . flush(_test-output-buffered-file) +3624 # . . push args +3625 68/push _test-output-buffered-file/imm32 +3626 # . . call +3627 e8/call flush/disp32 +3628 # . . discard args +3629 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3630 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +3656 # . check-stream-equal(_test-output-stream, "0f ab # 0f/m1 ab/m2 # comment", msg) +3657 # . . push args +3658 68/push "F - test-convert-instruction-handles-0f-opcode"/imm32 +3659 68/push "0f ab # 0f/m1 ab/m2 # comment"/imm32 +3660 68/push _test-output-stream/imm32 +3661 # . . call +3662 e8/call check-stream-equal/disp32 +3663 # . . discard args +3664 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3665 # . epilog +3666 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3667 5d/pop-to-EBP +3668 c3/return +3669 +3670 test-convert-instruction-handles-f2-opcode: +3671 # if the instruction starts with f2 opcode, include a second opcode +3672 # . prolog +3673 55/push-EBP +3674 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3675 # setup +3676 # . clear-stream(_test-input-stream) 3677 # . . push args -3678 68/push "F - test-convert-instruction-passes-labels-through"/imm32 -3679 68/push "ab: # cd"/imm32 -3680 68/push _test-output-stream/imm32 -3681 # . . call -3682 e8/call check-stream-equal/disp32 -3683 # . . discard args -3684 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3685 # . epilog -3686 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3687 5d/pop-to-EBP -3688 c3/return -3689 -3690 test-convert-instruction-handles-single-opcode: -3691 # if the instruction consists of a single opcode, strip its metadata and pass it along -3692 # . prolog -3693 55/push-EBP -3694 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3695 # setup -3696 # . clear-stream(_test-input-stream) -3697 # . . push args -3698 68/push _test-input-stream/imm32 -3699 # . . call -3700 e8/call clear-stream/disp32 -3701 # . . discard args -3702 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3703 # . clear-stream(_test-output-stream) -3704 # . . push args -3705 68/push _test-output-stream/imm32 -3706 # . . call -3707 e8/call clear-stream/disp32 -3708 # . . discard args -3709 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3710 # . clear-stream(_test-output-buffered-file+4) -3711 # . . push args -3712 b8/copy-to-EAX _test-output-buffered-file/imm32 -3713 05/add-to-EAX 4/imm32 -3714 50/push-EAX -3715 # . . call -3716 e8/call clear-stream/disp32 -3717 # . . discard args -3718 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3719 # initialize input -3720 # . write(_test-input-stream, "ab/cd # comment") -3721 # . . push args -3722 68/push "ab/cd # comment"/imm32 -3723 68/push _test-input-stream/imm32 -3724 # . . call -3725 e8/call write/disp32 -3726 # . . discard args -3727 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3728 # convert-instruction(_test-input-stream, _test-output-buffered-file) -3729 # . . push args -3730 68/push _test-output-buffered-file/imm32 -3731 68/push _test-input-stream/imm32 -3732 # . . call -3733 e8/call convert-instruction/disp32 -3734 # . . discard args -3735 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3736 # check output -3737 # . flush(_test-output-buffered-file) -3738 # . . push args -3739 68/push _test-output-buffered-file/imm32 -3740 # . . call -3741 e8/call flush/disp32 -3742 # . . discard args -3743 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3744 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -3778 # . check-stream-equal(_test-output-stream, "ab # ab/cd # comment", msg) -3779 # . . push args -3780 68/push "F - test-convert-instruction-handles-single-opcode"/imm32 -3781 68/push "ab # ab/cd # comment"/imm32 -3782 68/push _test-output-stream/imm32 -3783 # . . call -3784 e8/call check-stream-equal/disp32 -3785 # . . discard args -3786 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3787 # . epilog -3788 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3789 5d/pop-to-EBP -3790 c3/return -3791 -3792 test-convert-instruction-handles-0f-opcode: -3793 # if the instruction starts with 0f opcode, include a second opcode -3794 # . prolog -3795 55/push-EBP -3796 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3797 # setup -3798 # . clear-stream(_test-input-stream) -3799 # . . push args -3800 68/push _test-input-stream/imm32 -3801 # . . call -3802 e8/call clear-stream/disp32 -3803 # . . discard args -3804 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3805 # . clear-stream(_test-output-stream) -3806 # . . push args -3807 68/push _test-output-stream/imm32 -3808 # . . call -3809 e8/call clear-stream/disp32 -3810 # . . discard args -3811 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3812 # . clear-stream(_test-output-buffered-file+4) -3813 # . . push args -3814 b8/copy-to-EAX _test-output-buffered-file/imm32 -3815 05/add-to-EAX 4/imm32 -3816 50/push-EAX -3817 # . . call -3818 e8/call clear-stream/disp32 -3819 # . . discard args -3820 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3821 # initialize input -3822 # . write(_test-input-stream, "0f/m1 ab/m2 # comment") -3823 # . . push args -3824 68/push "0f/m1 ab/m2 # comment"/imm32 -3825 68/push _test-input-stream/imm32 -3826 # . . call -3827 e8/call write/disp32 -3828 # . . discard args -3829 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3830 # convert-instruction(_test-input-stream, _test-output-buffered-file) -3831 # . . push args -3832 68/push _test-output-buffered-file/imm32 -3833 68/push _test-input-stream/imm32 -3834 # . . call -3835 e8/call convert-instruction/disp32 -3836 # . . discard args -3837 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3838 # check output -3839 # . flush(_test-output-buffered-file) -3840 # . . push args -3841 68/push _test-output-buffered-file/imm32 -3842 # . . call -3843 e8/call flush/disp32 -3844 # . . discard args -3845 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3846 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -3880 # . check-stream-equal(_test-output-stream, "0f ab # 0f/m1 ab/m2 # comment", msg) -3881 # . . push args -3882 68/push "F - test-convert-instruction-handles-0f-opcode"/imm32 -3883 68/push "0f ab # 0f/m1 ab/m2 # comment"/imm32 -3884 68/push _test-output-stream/imm32 -3885 # . . call -3886 e8/call check-stream-equal/disp32 -3887 # . . discard args -3888 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3889 # . epilog -3890 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3891 5d/pop-to-EBP -3892 c3/return -3893 -3894 test-convert-instruction-handles-f2-opcode: -3895 # if the instruction starts with f2 opcode, include a second opcode -3896 # . prolog -3897 55/push-EBP -3898 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -3899 # setup -3900 # . clear-stream(_test-input-stream) -3901 # . . push args -3902 68/push _test-input-stream/imm32 -3903 # . . call -3904 e8/call clear-stream/disp32 -3905 # . . discard args -3906 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3907 # . clear-stream(_test-output-stream) -3908 # . . push args -3909 68/push _test-output-stream/imm32 -3910 # . . call -3911 e8/call clear-stream/disp32 -3912 # . . discard args -3913 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3914 # . clear-stream(_test-output-buffered-file+4) -3915 # . . push args -3916 b8/copy-to-EAX _test-output-buffered-file/imm32 -3917 05/add-to-EAX 4/imm32 -3918 50/push-EAX -3919 # . . call -3920 e8/call clear-stream/disp32 -3921 # . . discard args -3922 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3923 # initialize input -3924 # . write(_test-input-stream, "f2/m1 ab/m2 # comment") -3925 # . . push args -3926 68/push "f2/m1 ab/m2 # comment"/imm32 -3927 68/push _test-input-stream/imm32 -3928 # . . call -3929 e8/call write/disp32 -3930 # . . discard args -3931 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3932 # convert-instruction(_test-input-stream, _test-output-buffered-file) -3933 # . . push args -3934 68/push _test-output-buffered-file/imm32 -3935 68/push _test-input-stream/imm32 -3936 # . . call -3937 e8/call convert-instruction/disp32 -3938 # . . discard args -3939 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -3940 # check output -3941 # . flush(_test-output-buffered-file) -3942 # . . push args -3943 68/push _test-output-buffered-file/imm32 -3944 # . . call -3945 e8/call flush/disp32 -3946 # . . discard args -3947 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -3948 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -3982 # . check-stream-equal(_test-output-stream, "f2 ab # f2/m1 ab/m2 # comment", msg) +3678 68/push _test-input-stream/imm32 +3679 # . . call +3680 e8/call clear-stream/disp32 +3681 # . . discard args +3682 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3683 # . clear-stream(_test-output-stream) +3684 # . . push args +3685 68/push _test-output-stream/imm32 +3686 # . . call +3687 e8/call clear-stream/disp32 +3688 # . . discard args +3689 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3690 # . clear-stream(_test-output-buffered-file+4) +3691 # . . push args +3692 b8/copy-to-EAX _test-output-buffered-file/imm32 +3693 05/add-to-EAX 4/imm32 +3694 50/push-EAX +3695 # . . call +3696 e8/call clear-stream/disp32 +3697 # . . discard args +3698 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3699 # initialize input +3700 # . write(_test-input-stream, "f2/m1 ab/m2 # comment") +3701 # . . push args +3702 68/push "f2/m1 ab/m2 # comment"/imm32 +3703 68/push _test-input-stream/imm32 +3704 # . . call +3705 e8/call write/disp32 +3706 # . . discard args +3707 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3708 # convert-instruction(_test-input-stream, _test-output-buffered-file) +3709 # . . push args +3710 68/push _test-output-buffered-file/imm32 +3711 68/push _test-input-stream/imm32 +3712 # . . call +3713 e8/call convert-instruction/disp32 +3714 # . . discard args +3715 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3716 # check output +3717 # . flush(_test-output-buffered-file) +3718 # . . push args +3719 68/push _test-output-buffered-file/imm32 +3720 # . . call +3721 e8/call flush/disp32 +3722 # . . discard args +3723 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3724 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +3750 # . check-stream-equal(_test-output-stream, "f2 ab # f2/m1 ab/m2 # comment", msg) +3751 # . . push args +3752 68/push "F - test-convert-instruction-handles-f2-opcode"/imm32 +3753 68/push "f2 ab # f2/m1 ab/m2 # comment"/imm32 +3754 68/push _test-output-stream/imm32 +3755 # . . call +3756 e8/call check-stream-equal/disp32 +3757 # . . discard args +3758 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3759 # . epilog +3760 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3761 5d/pop-to-EBP +3762 c3/return +3763 +3764 test-convert-instruction-handles-f3-opcode: +3765 # if the instruction starts with f3 opcode, include a second opcode +3766 # . prolog +3767 55/push-EBP +3768 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3769 # setup +3770 # . clear-stream(_test-input-stream) +3771 # . . push args +3772 68/push _test-input-stream/imm32 +3773 # . . call +3774 e8/call clear-stream/disp32 +3775 # . . discard args +3776 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3777 # . clear-stream(_test-output-stream) +3778 # . . push args +3779 68/push _test-output-stream/imm32 +3780 # . . call +3781 e8/call clear-stream/disp32 +3782 # . . discard args +3783 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3784 # . clear-stream(_test-output-buffered-file+4) +3785 # . . push args +3786 b8/copy-to-EAX _test-output-buffered-file/imm32 +3787 05/add-to-EAX 4/imm32 +3788 50/push-EAX +3789 # . . call +3790 e8/call clear-stream/disp32 +3791 # . . discard args +3792 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3793 # initialize input +3794 # . write(_test-input-stream, "f3/m1 ab/m2 # comment") +3795 # . . push args +3796 68/push "f3/m1 ab/m2 # comment"/imm32 +3797 68/push _test-input-stream/imm32 +3798 # . . call +3799 e8/call write/disp32 +3800 # . . discard args +3801 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3802 # convert-instruction(_test-input-stream, _test-output-buffered-file) +3803 # . . push args +3804 68/push _test-output-buffered-file/imm32 +3805 68/push _test-input-stream/imm32 +3806 # . . call +3807 e8/call convert-instruction/disp32 +3808 # . . discard args +3809 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3810 # check output +3811 # . flush(_test-output-buffered-file) +3812 # . . push args +3813 68/push _test-output-buffered-file/imm32 +3814 # . . call +3815 e8/call flush/disp32 +3816 # . . discard args +3817 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3818 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +3844 # . check-stream-equal(_test-output-stream, "f3 ab # f3/m1 ab/m2 # comment", msg) +3845 # . . push args +3846 68/push "F - test-convert-instruction-handles-f3-opcode"/imm32 +3847 68/push "f3 ab # f3/m1 ab/m2 # comment"/imm32 +3848 68/push _test-output-stream/imm32 +3849 # . . call +3850 e8/call check-stream-equal/disp32 +3851 # . . discard args +3852 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3853 # . epilog +3854 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3855 5d/pop-to-EBP +3856 c3/return +3857 +3858 test-convert-instruction-handles-f2-0f-opcode: +3859 # if the instruction starts with f2 0f opcode, include a second opcode +3860 # . prolog +3861 55/push-EBP +3862 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3863 # setup +3864 # . clear-stream(_test-input-stream) +3865 # . . push args +3866 68/push _test-input-stream/imm32 +3867 # . . call +3868 e8/call clear-stream/disp32 +3869 # . . discard args +3870 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3871 # . clear-stream(_test-output-stream) +3872 # . . push args +3873 68/push _test-output-stream/imm32 +3874 # . . call +3875 e8/call clear-stream/disp32 +3876 # . . discard args +3877 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3878 # . clear-stream(_test-output-buffered-file+4) +3879 # . . push args +3880 b8/copy-to-EAX _test-output-buffered-file/imm32 +3881 05/add-to-EAX 4/imm32 +3882 50/push-EAX +3883 # . . call +3884 e8/call clear-stream/disp32 +3885 # . . discard args +3886 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3887 # initialize input +3888 # . write(_test-input-stream, "f2/m1 0f/m2 ab/m3 # comment") +3889 # . . push args +3890 68/push "f2/m1 0f/m2 ab/m3 # comment"/imm32 +3891 68/push _test-input-stream/imm32 +3892 # . . call +3893 e8/call write/disp32 +3894 # . . discard args +3895 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3896 # convert-instruction(_test-input-stream, _test-output-buffered-file) +3897 # . . push args +3898 68/push _test-output-buffered-file/imm32 +3899 68/push _test-input-stream/imm32 +3900 # . . call +3901 e8/call convert-instruction/disp32 +3902 # . . discard args +3903 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3904 # check output +3905 # . flush(_test-output-buffered-file) +3906 # . . push args +3907 68/push _test-output-buffered-file/imm32 +3908 # . . call +3909 e8/call flush/disp32 +3910 # . . discard args +3911 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3912 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +3938 # . check-stream-equal(_test-output-stream, "f2 0f ab # f2/m1 0f/m2 ab/m3 # comment", msg) +3939 # . . push args +3940 68/push "F - test-convert-instruction-handles-f2-0f-opcode"/imm32 +3941 68/push "f2 0f ab # f2/m1 0f/m2 ab/m3 # comment"/imm32 +3942 68/push _test-output-stream/imm32 +3943 # . . call +3944 e8/call check-stream-equal/disp32 +3945 # . . discard args +3946 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +3947 # . epilog +3948 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +3949 5d/pop-to-EBP +3950 c3/return +3951 +3952 test-convert-instruction-handles-f3-0f-opcode: +3953 # if the instruction starts with f3 0f opcode, include a second opcode +3954 # . prolog +3955 55/push-EBP +3956 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +3957 # setup +3958 # . clear-stream(_test-input-stream) +3959 # . . push args +3960 68/push _test-input-stream/imm32 +3961 # . . call +3962 e8/call clear-stream/disp32 +3963 # . . discard args +3964 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3965 # . clear-stream(_test-output-stream) +3966 # . . push args +3967 68/push _test-output-stream/imm32 +3968 # . . call +3969 e8/call clear-stream/disp32 +3970 # . . discard args +3971 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3972 # . clear-stream(_test-output-buffered-file+4) +3973 # . . push args +3974 b8/copy-to-EAX _test-output-buffered-file/imm32 +3975 05/add-to-EAX 4/imm32 +3976 50/push-EAX +3977 # . . call +3978 e8/call clear-stream/disp32 +3979 # . . discard args +3980 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +3981 # initialize input +3982 # . write(_test-input-stream, "f3/m1 0f/m2 ab/m3 # comment") 3983 # . . push args -3984 68/push "F - test-convert-instruction-handles-f2-opcode"/imm32 -3985 68/push "f2 ab # f2/m1 ab/m2 # comment"/imm32 -3986 68/push _test-output-stream/imm32 -3987 # . . call -3988 e8/call check-stream-equal/disp32 -3989 # . . discard args -3990 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -3991 # . epilog -3992 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -3993 5d/pop-to-EBP -3994 c3/return -3995 -3996 test-convert-instruction-handles-f3-opcode: -3997 # if the instruction starts with f3 opcode, include a second opcode -3998 # . prolog -3999 55/push-EBP -4000 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -4001 # setup -4002 # . clear-stream(_test-input-stream) -4003 # . . push args -4004 68/push _test-input-stream/imm32 -4005 # . . call -4006 e8/call clear-stream/disp32 -4007 # . . discard args -4008 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4009 # . clear-stream(_test-output-stream) -4010 # . . push args -4011 68/push _test-output-stream/imm32 -4012 # . . call -4013 e8/call clear-stream/disp32 -4014 # . . discard args -4015 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4016 # . clear-stream(_test-output-buffered-file+4) -4017 # . . push args -4018 b8/copy-to-EAX _test-output-buffered-file/imm32 -4019 05/add-to-EAX 4/imm32 -4020 50/push-EAX -4021 # . . call -4022 e8/call clear-stream/disp32 -4023 # . . discard args -4024 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4025 # initialize input -4026 # . write(_test-input-stream, "f3/m1 ab/m2 # comment") -4027 # . . push args -4028 68/push "f3/m1 ab/m2 # comment"/imm32 -4029 68/push _test-input-stream/imm32 -4030 # . . call -4031 e8/call write/disp32 -4032 # . . discard args -4033 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4034 # convert-instruction(_test-input-stream, _test-output-buffered-file) -4035 # . . push args -4036 68/push _test-output-buffered-file/imm32 -4037 68/push _test-input-stream/imm32 -4038 # . . call -4039 e8/call convert-instruction/disp32 -4040 # . . discard args -4041 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4042 # check output -4043 # . flush(_test-output-buffered-file) -4044 # . . push args -4045 68/push _test-output-buffered-file/imm32 -4046 # . . call -4047 e8/call flush/disp32 -4048 # . . discard args -4049 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4050 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -4084 # . check-stream-equal(_test-output-stream, "f3 ab # f3/m1 ab/m2 # comment", msg) +3984 68/push "f3/m1 0f/m2 ab/m3 # comment"/imm32 +3985 68/push _test-input-stream/imm32 +3986 # . . call +3987 e8/call write/disp32 +3988 # . . discard args +3989 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3990 # convert-instruction(_test-input-stream, _test-output-buffered-file) +3991 # . . push args +3992 68/push _test-output-buffered-file/imm32 +3993 68/push _test-input-stream/imm32 +3994 # . . call +3995 e8/call convert-instruction/disp32 +3996 # . . discard args +3997 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +3998 # check output +3999 # . flush(_test-output-buffered-file) +4000 # . . push args +4001 68/push _test-output-buffered-file/imm32 +4002 # . . call +4003 e8/call flush/disp32 +4004 # . . discard args +4005 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4006 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +4032 # . check-stream-equal(_test-output-stream, "f3 0f ab # f3/m1 0f/m2 ab/m3 # comment", msg) +4033 # . . push args +4034 68/push "F - test-convert-instruction-handles-f3-0f-opcode"/imm32 +4035 68/push "f3 0f ab # f3/m1 0f/m2 ab/m3 # comment"/imm32 +4036 68/push _test-output-stream/imm32 +4037 # . . call +4038 e8/call check-stream-equal/disp32 +4039 # . . discard args +4040 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4041 # . epilog +4042 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4043 5d/pop-to-EBP +4044 c3/return +4045 +4046 test-convert-instruction-handles-unused-opcodes: +4047 # if the instruction doesn't start with f2, f3 or 0f, don't include other opcodes +4048 # . prolog +4049 55/push-EBP +4050 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4051 # setup +4052 # . clear-stream(_test-input-stream) +4053 # . . push args +4054 68/push _test-input-stream/imm32 +4055 # . . call +4056 e8/call clear-stream/disp32 +4057 # . . discard args +4058 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4059 # . clear-stream(_test-output-stream) +4060 # . . push args +4061 68/push _test-output-stream/imm32 +4062 # . . call +4063 e8/call clear-stream/disp32 +4064 # . . discard args +4065 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4066 # . clear-stream(_test-output-buffered-file+4) +4067 # . . push args +4068 b8/copy-to-EAX _test-output-buffered-file/imm32 +4069 05/add-to-EAX 4/imm32 +4070 50/push-EAX +4071 # . . call +4072 e8/call clear-stream/disp32 +4073 # . . discard args +4074 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4075 # initialize input +4076 # . write(_test-input-stream, "ab/m1 cd/m2 # comment") +4077 # . . push args +4078 68/push "ab/m1 cd/m2 # comment"/imm32 +4079 68/push _test-input-stream/imm32 +4080 # . . call +4081 e8/call write/disp32 +4082 # . . discard args +4083 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4084 # convert-instruction(_test-input-stream, _test-output-buffered-file) 4085 # . . push args -4086 68/push "F - test-convert-instruction-handles-f3-opcode"/imm32 -4087 68/push "f3 ab # f3/m1 ab/m2 # comment"/imm32 -4088 68/push _test-output-stream/imm32 -4089 # . . call -4090 e8/call check-stream-equal/disp32 -4091 # . . discard args -4092 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -4093 # . epilog -4094 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -4095 5d/pop-to-EBP -4096 c3/return -4097 -4098 test-convert-instruction-handles-f2-0f-opcode: -4099 # if the instruction starts with f2 0f opcode, include a second opcode -4100 # . prolog -4101 55/push-EBP -4102 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -4103 # setup -4104 # . clear-stream(_test-input-stream) -4105 # . . push args -4106 68/push _test-input-stream/imm32 -4107 # . . call -4108 e8/call clear-stream/disp32 -4109 # . . discard args -4110 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4111 # . clear-stream(_test-output-stream) -4112 # . . push args -4113 68/push _test-output-stream/imm32 -4114 # . . call -4115 e8/call clear-stream/disp32 -4116 # . . discard args -4117 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4118 # . clear-stream(_test-output-buffered-file+4) -4119 # . . push args -4120 b8/copy-to-EAX _test-output-buffered-file/imm32 -4121 05/add-to-EAX 4/imm32 -4122 50/push-EAX -4123 # . . call -4124 e8/call clear-stream/disp32 -4125 # . . discard args -4126 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4127 # initialize input -4128 # . write(_test-input-stream, "f2/m1 0f/m2 ab/m3 # comment") -4129 # . . push args -4130 68/push "f2/m1 0f/m2 ab/m3 # comment"/imm32 -4131 68/push _test-input-stream/imm32 -4132 # . . call -4133 e8/call write/disp32 -4134 # . . discard args -4135 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4136 # convert-instruction(_test-input-stream, _test-output-buffered-file) -4137 # . . push args -4138 68/push _test-output-buffered-file/imm32 -4139 68/push _test-input-stream/imm32 -4140 # . . call -4141 e8/call convert-instruction/disp32 -4142 # . . discard args -4143 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4144 # check output -4145 # . flush(_test-output-buffered-file) -4146 # . . push args -4147 68/push _test-output-buffered-file/imm32 -4148 # . . call -4149 e8/call flush/disp32 -4150 # . . discard args -4151 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4152 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -4186 # . check-stream-equal(_test-output-stream, "f2 0f ab # f2/m1 0f/m2 ab/m3 # comment", msg) -4187 # . . push args -4188 68/push "F - test-convert-instruction-handles-f2-0f-opcode"/imm32 -4189 68/push "f2 0f ab # f2/m1 0f/m2 ab/m3 # comment"/imm32 -4190 68/push _test-output-stream/imm32 -4191 # . . call -4192 e8/call check-stream-equal/disp32 -4193 # . . discard args -4194 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -4195 # . epilog -4196 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -4197 5d/pop-to-EBP -4198 c3/return -4199 -4200 test-convert-instruction-handles-f3-0f-opcode: -4201 # if the instruction starts with f3 0f opcode, include a second opcode -4202 # . prolog -4203 55/push-EBP -4204 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -4205 # setup -4206 # . clear-stream(_test-input-stream) -4207 # . . push args -4208 68/push _test-input-stream/imm32 -4209 # . . call -4210 e8/call clear-stream/disp32 -4211 # . . discard args -4212 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4213 # . clear-stream(_test-output-stream) -4214 # . . push args -4215 68/push _test-output-stream/imm32 -4216 # . . call -4217 e8/call clear-stream/disp32 -4218 # . . discard args -4219 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4220 # . clear-stream(_test-output-buffered-file+4) +4086 68/push _test-output-buffered-file/imm32 +4087 68/push _test-input-stream/imm32 +4088 # . . call +4089 e8/call convert-instruction/disp32 +4090 # . . discard args +4091 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4092 # check output +4093 # . flush(_test-output-buffered-file) +4094 # . . push args +4095 68/push _test-output-buffered-file/imm32 +4096 # . . call +4097 e8/call flush/disp32 +4098 # . . discard args +4099 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4100 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +4126 # . check-stream-equal(_test-output-stream, "ab # f3/m1 0f/m2 ab/m3 # comment", msg) +4127 # . . push args +4128 68/push "F - test-convert-instruction-handles-unused-opcodes"/imm32 +4129 68/push "ab # ab/m1 cd/m2 # comment"/imm32 +4130 68/push _test-output-stream/imm32 +4131 # . . call +4132 e8/call check-stream-equal/disp32 +4133 # . . discard args +4134 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4135 # . epilog +4136 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4137 5d/pop-to-EBP +4138 c3/return +4139 +4140 test-convert-instruction-handles-unused-second-opcodes: +4141 # if the second opcode isn't 0f, don't include further opcodes +4142 # . prolog +4143 55/push-EBP +4144 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4145 # setup +4146 # . clear-stream(_test-input-stream) +4147 # . . push args +4148 68/push _test-input-stream/imm32 +4149 # . . call +4150 e8/call clear-stream/disp32 +4151 # . . discard args +4152 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4153 # . clear-stream(_test-output-stream) +4154 # . . push args +4155 68/push _test-output-stream/imm32 +4156 # . . call +4157 e8/call clear-stream/disp32 +4158 # . . discard args +4159 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4160 # . clear-stream(_test-output-buffered-file+4) +4161 # . . push args +4162 b8/copy-to-EAX _test-output-buffered-file/imm32 +4163 05/add-to-EAX 4/imm32 +4164 50/push-EAX +4165 # . . call +4166 e8/call clear-stream/disp32 +4167 # . . discard args +4168 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4169 # initialize input +4170 # . write(_test-input-stream, "f2/m1 ab/m2 cd/m3 # comment") +4171 # . . push args +4172 68/push "f2/m1 ab/m2 cd/m3 # comment"/imm32 +4173 68/push _test-input-stream/imm32 +4174 # . . call +4175 e8/call write/disp32 +4176 # . . discard args +4177 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4178 # convert-instruction(_test-input-stream, _test-output-buffered-file) +4179 # . . push args +4180 68/push _test-output-buffered-file/imm32 +4181 68/push _test-input-stream/imm32 +4182 # . . call +4183 e8/call convert-instruction/disp32 +4184 # . . discard args +4185 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4186 # check output +4187 # . flush(_test-output-buffered-file) +4188 # . . push args +4189 68/push _test-output-buffered-file/imm32 +4190 # . . call +4191 e8/call flush/disp32 +4192 # . . discard args +4193 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4194 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +4220 # . check-stream-equal(_test-output-stream, "f2 ab # f2/m1 ab/m2 cd/m3 # comment", msg) 4221 # . . push args -4222 b8/copy-to-EAX _test-output-buffered-file/imm32 -4223 05/add-to-EAX 4/imm32 -4224 50/push-EAX +4222 68/push "F - test-convert-instruction-handles-unused-second-opcodes"/imm32 +4223 68/push "f2 ab # f2/m1 ab/m2 cd/m3 # comment"/imm32 +4224 68/push _test-output-stream/imm32 4225 # . . call -4226 e8/call clear-stream/disp32 +4226 e8/call check-stream-equal/disp32 4227 # . . discard args -4228 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4229 # initialize input -4230 # . write(_test-input-stream, "f3/m1 0f/m2 ab/m3 # comment") -4231 # . . push args -4232 68/push "f3/m1 0f/m2 ab/m3 # comment"/imm32 -4233 68/push _test-input-stream/imm32 -4234 # . . call -4235 e8/call write/disp32 -4236 # . . discard args -4237 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4238 # convert-instruction(_test-input-stream, _test-output-buffered-file) -4239 # . . push args -4240 68/push _test-output-buffered-file/imm32 -4241 68/push _test-input-stream/imm32 -4242 # . . call -4243 e8/call convert-instruction/disp32 -4244 # . . discard args -4245 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4246 # check output -4247 # . flush(_test-output-buffered-file) +4228 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4229 # . epilog +4230 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4231 5d/pop-to-EBP +4232 c3/return +4233 +4234 test-convert-instruction-handles-unused-second-opcodes-2: +4235 # if the second opcode isn't 0f, don't include further opcodes +4236 # . prolog +4237 55/push-EBP +4238 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4239 # setup +4240 # . clear-stream(_test-input-stream) +4241 # . . push args +4242 68/push _test-input-stream/imm32 +4243 # . . call +4244 e8/call clear-stream/disp32 +4245 # . . discard args +4246 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4247 # . clear-stream(_test-output-stream) 4248 # . . push args -4249 68/push _test-output-buffered-file/imm32 +4249 68/push _test-output-stream/imm32 4250 # . . call -4251 e8/call flush/disp32 +4251 e8/call clear-stream/disp32 4252 # . . discard args 4253 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4254 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -4288 # . check-stream-equal(_test-output-stream, "f3 0f ab # f3/m1 0f/m2 ab/m3 # comment", msg) -4289 # . . push args -4290 68/push "F - test-convert-instruction-handles-f3-0f-opcode"/imm32 -4291 68/push "f3 0f ab # f3/m1 0f/m2 ab/m3 # comment"/imm32 -4292 68/push _test-output-stream/imm32 -4293 # . . call -4294 e8/call check-stream-equal/disp32 -4295 # . . discard args -4296 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -4297 # . epilog -4298 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -4299 5d/pop-to-EBP -4300 c3/return -4301 -4302 test-convert-instruction-handles-unused-opcodes: -4303 # if the instruction doesn't start with f2, f3 or 0f, don't include other opcodes -4304 # . prolog -4305 55/push-EBP -4306 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -4307 # setup -4308 # . clear-stream(_test-input-stream) -4309 # . . push args -4310 68/push _test-input-stream/imm32 -4311 # . . call -4312 e8/call clear-stream/disp32 -4313 # . . discard args -4314 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4315 # . clear-stream(_test-output-stream) -4316 # . . push args -4317 68/push _test-output-stream/imm32 -4318 # . . call -4319 e8/call clear-stream/disp32 -4320 # . . discard args -4321 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4322 # . clear-stream(_test-output-buffered-file+4) -4323 # . . push args -4324 b8/copy-to-EAX _test-output-buffered-file/imm32 -4325 05/add-to-EAX 4/imm32 -4326 50/push-EAX -4327 # . . call -4328 e8/call clear-stream/disp32 -4329 # . . discard args -4330 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4331 # initialize input -4332 # . write(_test-input-stream, "ab/m1 cd/m2 # comment") -4333 # . . push args -4334 68/push "ab/m1 cd/m2 # comment"/imm32 -4335 68/push _test-input-stream/imm32 -4336 # . . call -4337 e8/call write/disp32 -4338 # . . discard args -4339 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4340 # convert-instruction(_test-input-stream, _test-output-buffered-file) -4341 # . . push args -4342 68/push _test-output-buffered-file/imm32 -4343 68/push _test-input-stream/imm32 +4254 # . clear-stream(_test-output-buffered-file+4) +4255 # . . push args +4256 b8/copy-to-EAX _test-output-buffered-file/imm32 +4257 05/add-to-EAX 4/imm32 +4258 50/push-EAX +4259 # . . call +4260 e8/call clear-stream/disp32 +4261 # . . discard args +4262 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4263 # initialize input +4264 # . write(_test-input-stream, "f3/m1 ab/m2 cd/m3 # comment") +4265 # . . push args +4266 68/push "f3/m1 ab/m2 cd/m3 # comment"/imm32 +4267 68/push _test-input-stream/imm32 +4268 # . . call +4269 e8/call write/disp32 +4270 # . . discard args +4271 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4272 # convert-instruction(_test-input-stream, _test-output-buffered-file) +4273 # . . push args +4274 68/push _test-output-buffered-file/imm32 +4275 68/push _test-input-stream/imm32 +4276 # . . call +4277 e8/call convert-instruction/disp32 +4278 # . . discard args +4279 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4280 # check output +4281 # . flush(_test-output-buffered-file) +4282 # . . push args +4283 68/push _test-output-buffered-file/imm32 +4284 # . . call +4285 e8/call flush/disp32 +4286 # . . discard args +4287 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4288 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +4314 # . check-stream-equal(_test-output-stream, "f3 ab # f3/m1 ab/m2 cd/m3 # comment", msg) +4315 # . . push args +4316 68/push "F - test-convert-instruction-handles-unused-second-opcodes"/imm32 +4317 68/push "f3 ab # f3/m1 ab/m2 cd/m3 # comment"/imm32 +4318 68/push _test-output-stream/imm32 +4319 # . . call +4320 e8/call check-stream-equal/disp32 +4321 # . . discard args +4322 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4323 # . epilog +4324 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4325 5d/pop-to-EBP +4326 c3/return +4327 +4328 test-convert-instruction-emits-modrm-byte: +4329 # pack mod, rm32 and r32 operands into ModR/M byte +4330 # . prolog +4331 55/push-EBP +4332 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4333 # setup +4334 # . clear-stream(_test-input-stream) +4335 # . . push args +4336 68/push _test-input-stream/imm32 +4337 # . . call +4338 e8/call clear-stream/disp32 +4339 # . . discard args +4340 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4341 # . clear-stream(_test-output-stream) +4342 # . . push args +4343 68/push _test-output-stream/imm32 4344 # . . call -4345 e8/call convert-instruction/disp32 +4345 e8/call clear-stream/disp32 4346 # . . discard args -4347 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4348 # check output -4349 # . flush(_test-output-buffered-file) -4350 # . . push args -4351 68/push _test-output-buffered-file/imm32 -4352 # . . call -4353 e8/call flush/disp32 -4354 # . . discard args -4355 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4356 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -4390 # . check-stream-equal(_test-output-stream, "ab # f3/m1 0f/m2 ab/m3 # comment", msg) -4391 # . . push args -4392 68/push "F - test-convert-instruction-handles-unused-opcodes"/imm32 -4393 68/push "ab # ab/m1 cd/m2 # comment"/imm32 -4394 68/push _test-output-stream/imm32 -4395 # . . call -4396 e8/call check-stream-equal/disp32 -4397 # . . discard args -4398 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -4399 # . epilog -4400 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -4401 5d/pop-to-EBP -4402 c3/return -4403 -4404 test-convert-instruction-handles-unused-second-opcodes: -4405 # if the second opcode isn't 0f, don't include further opcodes -4406 # . prolog -4407 55/push-EBP -4408 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -4409 # setup -4410 # . clear-stream(_test-input-stream) -4411 # . . push args -4412 68/push _test-input-stream/imm32 +4347 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4348 # . clear-stream(_test-output-buffered-file+4) +4349 # . . push args +4350 b8/copy-to-EAX _test-output-buffered-file/imm32 +4351 05/add-to-EAX 4/imm32 +4352 50/push-EAX +4353 # . . call +4354 e8/call clear-stream/disp32 +4355 # . . discard args +4356 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4357 # initialize input +4358 # . write(_test-input-stream, "8b/copy 0/mod 0/rm32 1/r32") +4359 # . . push args +4360 68/push "8b/copy 0/mod 0/rm32 1/r32"/imm32 +4361 68/push _test-input-stream/imm32 +4362 # . . call +4363 e8/call write/disp32 +4364 # . . discard args +4365 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4366 # convert-instruction(_test-input-stream, _test-output-buffered-file) +4367 # . . push args +4368 68/push _test-output-buffered-file/imm32 +4369 68/push _test-input-stream/imm32 +4370 # . . call +4371 e8/call convert-instruction/disp32 +4372 # . . discard args +4373 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4374 # check output +4375 # . flush(_test-output-buffered-file) +4376 # . . push args +4377 68/push _test-output-buffered-file/imm32 +4378 # . . call +4379 e8/call flush/disp32 +4380 # . . discard args +4381 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4382 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +4408 # . check-stream-equal(_test-output-stream, "8b 08 # 8b/copy 0/mod 0/rm32 1/r32", msg) +4409 # . . push args +4410 68/push "F - test-convert-instruction-emits-modrm-byte"/imm32 +4411 68/push "8b 08 # 8b/copy 0/mod 0/rm32 1/r32"/imm32 +4412 68/push _test-output-stream/imm32 4413 # . . call -4414 e8/call clear-stream/disp32 +4414 e8/call check-stream-equal/disp32 4415 # . . discard args -4416 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4417 # . clear-stream(_test-output-stream) -4418 # . . push args -4419 68/push _test-output-stream/imm32 -4420 # . . call -4421 e8/call clear-stream/disp32 -4422 # . . discard args -4423 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4424 # . clear-stream(_test-output-buffered-file+4) -4425 # . . push args -4426 b8/copy-to-EAX _test-output-buffered-file/imm32 -4427 05/add-to-EAX 4/imm32 -4428 50/push-EAX -4429 # . . call -4430 e8/call clear-stream/disp32 -4431 # . . discard args -4432 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4433 # initialize input -4434 # . write(_test-input-stream, "f2/m1 ab/m2 cd/m3 # comment") -4435 # . . push args -4436 68/push "f2/m1 ab/m2 cd/m3 # comment"/imm32 -4437 68/push _test-input-stream/imm32 +4416 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4417 # . epilog +4418 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4419 5d/pop-to-EBP +4420 c3/return +4421 +4422 test-convert-instruction-emits-modrm-byte-from-subop: +4423 # pack mod, rm32 and subop operands into ModR/M byte +4424 # . prolog +4425 55/push-EBP +4426 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4427 # setup +4428 # . clear-stream(_test-input-stream) +4429 # . . push args +4430 68/push _test-input-stream/imm32 +4431 # . . call +4432 e8/call clear-stream/disp32 +4433 # . . discard args +4434 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4435 # . clear-stream(_test-output-stream) +4436 # . . push args +4437 68/push _test-output-stream/imm32 4438 # . . call -4439 e8/call write/disp32 +4439 e8/call clear-stream/disp32 4440 # . . discard args -4441 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4442 # convert-instruction(_test-input-stream, _test-output-buffered-file) +4441 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4442 # . clear-stream(_test-output-buffered-file+4) 4443 # . . push args -4444 68/push _test-output-buffered-file/imm32 -4445 68/push _test-input-stream/imm32 -4446 # . . call -4447 e8/call convert-instruction/disp32 -4448 # . . discard args -4449 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4450 # check output -4451 # . flush(_test-output-buffered-file) -4452 # . . push args -4453 68/push _test-output-buffered-file/imm32 -4454 # . . call -4455 e8/call flush/disp32 -4456 # . . discard args -4457 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4458 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -4492 # . check-stream-equal(_test-output-stream, "f2 ab # f2/m1 ab/m2 cd/m3 # comment", msg) -4493 # . . push args -4494 68/push "F - test-convert-instruction-handles-unused-second-opcodes"/imm32 -4495 68/push "f2 ab # f2/m1 ab/m2 cd/m3 # comment"/imm32 -4496 68/push _test-output-stream/imm32 -4497 # . . call -4498 e8/call check-stream-equal/disp32 -4499 # . . discard args -4500 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -4501 # . epilog -4502 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -4503 5d/pop-to-EBP -4504 c3/return -4505 -4506 test-convert-instruction-handles-unused-second-opcodes-2: -4507 # if the second opcode isn't 0f, don't include further opcodes -4508 # . prolog -4509 55/push-EBP -4510 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -4511 # setup -4512 # . clear-stream(_test-input-stream) -4513 # . . push args -4514 68/push _test-input-stream/imm32 -4515 # . . call -4516 e8/call clear-stream/disp32 -4517 # . . discard args -4518 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4519 # . clear-stream(_test-output-stream) -4520 # . . push args -4521 68/push _test-output-stream/imm32 -4522 # . . call -4523 e8/call clear-stream/disp32 -4524 # . . discard args -4525 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4526 # . clear-stream(_test-output-buffered-file+4) -4527 # . . push args -4528 b8/copy-to-EAX _test-output-buffered-file/imm32 -4529 05/add-to-EAX 4/imm32 -4530 50/push-EAX -4531 # . . call -4532 e8/call clear-stream/disp32 -4533 # . . discard args -4534 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4535 # initialize input -4536 # . write(_test-input-stream, "f3/m1 ab/m2 cd/m3 # comment") +4444 b8/copy-to-EAX _test-output-buffered-file/imm32 +4445 05/add-to-EAX 4/imm32 +4446 50/push-EAX +4447 # . . call +4448 e8/call clear-stream/disp32 +4449 # . . discard args +4450 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4451 # initialize input +4452 # . write(_test-input-stream, "ff 6/subop/push 0/mod 0/rm32") +4453 # . . push args +4454 68/push "ff 6/subop/push 0/mod 0/rm32"/imm32 +4455 68/push _test-input-stream/imm32 +4456 # . . call +4457 e8/call write/disp32 +4458 # . . discard args +4459 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4460 # convert-instruction(_test-input-stream, _test-output-buffered-file) +4461 # . . push args +4462 68/push _test-output-buffered-file/imm32 +4463 68/push _test-input-stream/imm32 +4464 # . . call +4465 e8/call convert-instruction/disp32 +4466 # . . discard args +4467 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4468 # check output +4469 # . flush(_test-output-buffered-file) +4470 # . . push args +4471 68/push _test-output-buffered-file/imm32 +4472 # . . call +4473 e8/call flush/disp32 +4474 # . . discard args +4475 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4476 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +4502 # . check-stream-equal(_test-output-stream, "ff 30 # ff 6/subop/push 0/mod 0/rm32", msg) +4503 # . . push args +4504 68/push "F - test-convert-instruction-emits-modrm-byte-from-subop"/imm32 +4505 68/push "ff 30 # ff 6/subop/push 0/mod 0/rm32"/imm32 +4506 68/push _test-output-stream/imm32 +4507 # . . call +4508 e8/call check-stream-equal/disp32 +4509 # . . discard args +4510 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4511 # . epilog +4512 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4513 5d/pop-to-EBP +4514 c3/return +4515 +4516 test-convert-instruction-emits-modrm-byte-with-missing-mod: +4517 # pack rm32 and r32 operands into ModR/M byte +4518 # . prolog +4519 55/push-EBP +4520 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4521 # setup +4522 # . clear-stream(_test-input-stream) +4523 # . . push args +4524 68/push _test-input-stream/imm32 +4525 # . . call +4526 e8/call clear-stream/disp32 +4527 # . . discard args +4528 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4529 # . clear-stream(_test-output-stream) +4530 # . . push args +4531 68/push _test-output-stream/imm32 +4532 # . . call +4533 e8/call clear-stream/disp32 +4534 # . . discard args +4535 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4536 # . clear-stream(_test-output-buffered-file+4) 4537 # . . push args -4538 68/push "f3/m1 ab/m2 cd/m3 # comment"/imm32 -4539 68/push _test-input-stream/imm32 -4540 # . . call -4541 e8/call write/disp32 -4542 # . . discard args -4543 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4544 # convert-instruction(_test-input-stream, _test-output-buffered-file) -4545 # . . push args -4546 68/push _test-output-buffered-file/imm32 -4547 68/push _test-input-stream/imm32 -4548 # . . call -4549 e8/call convert-instruction/disp32 -4550 # . . discard args -4551 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4552 # check output -4553 # . flush(_test-output-buffered-file) -4554 # . . push args -4555 68/push _test-output-buffered-file/imm32 -4556 # . . call -4557 e8/call flush/disp32 -4558 # . . discard args -4559 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4560 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -4594 # . check-stream-equal(_test-output-stream, "f3 ab # f3/m1 ab/m2 cd/m3 # comment", msg) -4595 # . . push args -4596 68/push "F - test-convert-instruction-handles-unused-second-opcodes"/imm32 -4597 68/push "f3 ab # f3/m1 ab/m2 cd/m3 # comment"/imm32 -4598 68/push _test-output-stream/imm32 -4599 # . . call -4600 e8/call check-stream-equal/disp32 -4601 # . . discard args -4602 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -4603 # . epilog -4604 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -4605 5d/pop-to-EBP -4606 c3/return -4607 -4608 test-convert-instruction-emits-modrm-byte: -4609 # pack mod, rm32 and r32 operands into ModR/M byte -4610 # . prolog -4611 55/push-EBP -4612 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -4613 # setup -4614 # . clear-stream(_test-input-stream) -4615 # . . push args -4616 68/push _test-input-stream/imm32 -4617 # . . call -4618 e8/call clear-stream/disp32 -4619 # . . discard args -4620 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4621 # . clear-stream(_test-output-stream) -4622 # . . push args -4623 68/push _test-output-stream/imm32 -4624 # . . call -4625 e8/call clear-stream/disp32 -4626 # . . discard args -4627 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4628 # . clear-stream(_test-output-buffered-file+4) -4629 # . . push args -4630 b8/copy-to-EAX _test-output-buffered-file/imm32 -4631 05/add-to-EAX 4/imm32 -4632 50/push-EAX -4633 # . . call -4634 e8/call clear-stream/disp32 -4635 # . . discard args -4636 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4637 # initialize input -4638 # . write(_test-input-stream, "8b/copy 0/mod 0/rm32 1/r32") -4639 # . . push args -4640 68/push "8b/copy 0/mod 0/rm32 1/r32"/imm32 -4641 68/push _test-input-stream/imm32 -4642 # . . call -4643 e8/call write/disp32 -4644 # . . discard args -4645 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4646 # convert-instruction(_test-input-stream, _test-output-buffered-file) -4647 # . . push args -4648 68/push _test-output-buffered-file/imm32 -4649 68/push _test-input-stream/imm32 -4650 # . . call -4651 e8/call convert-instruction/disp32 -4652 # . . discard args -4653 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4654 # check output -4655 # . flush(_test-output-buffered-file) -4656 # . . push args -4657 68/push _test-output-buffered-file/imm32 -4658 # . . call -4659 e8/call flush/disp32 -4660 # . . discard args -4661 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4662 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -4696 # . check-stream-equal(_test-output-stream, "8b 08 # 8b/copy 0/mod 0/rm32 1/r32", msg) -4697 # . . push args -4698 68/push "F - test-convert-instruction-emits-modrm-byte"/imm32 -4699 68/push "8b 08 # 8b/copy 0/mod 0/rm32 1/r32"/imm32 -4700 68/push _test-output-stream/imm32 -4701 # . . call -4702 e8/call check-stream-equal/disp32 -4703 # . . discard args -4704 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -4705 # . epilog -4706 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -4707 5d/pop-to-EBP -4708 c3/return -4709 -4710 test-convert-instruction-emits-modrm-byte-from-subop: -4711 # pack mod, rm32 and subop operands into ModR/M byte -4712 # . prolog -4713 55/push-EBP -4714 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -4715 # setup -4716 # . clear-stream(_test-input-stream) -4717 # . . push args -4718 68/push _test-input-stream/imm32 -4719 # . . call -4720 e8/call clear-stream/disp32 -4721 # . . discard args -4722 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4723 # . clear-stream(_test-output-stream) -4724 # . . push args -4725 68/push _test-output-stream/imm32 -4726 # . . call -4727 e8/call clear-stream/disp32 -4728 # . . discard args -4729 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4730 # . clear-stream(_test-output-buffered-file+4) -4731 # . . push args -4732 b8/copy-to-EAX _test-output-buffered-file/imm32 -4733 05/add-to-EAX 4/imm32 -4734 50/push-EAX -4735 # . . call -4736 e8/call clear-stream/disp32 -4737 # . . discard args -4738 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4739 # initialize input -4740 # . write(_test-input-stream, "ff 6/subop/push 0/mod 0/rm32") -4741 # . . push args -4742 68/push "ff 6/subop/push 0/mod 0/rm32"/imm32 -4743 68/push _test-input-stream/imm32 -4744 # . . call -4745 e8/call write/disp32 -4746 # . . discard args -4747 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4748 # convert-instruction(_test-input-stream, _test-output-buffered-file) -4749 # . . push args -4750 68/push _test-output-buffered-file/imm32 -4751 68/push _test-input-stream/imm32 -4752 # . . call -4753 e8/call convert-instruction/disp32 -4754 # . . discard args -4755 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4756 # check output -4757 # . flush(_test-output-buffered-file) -4758 # . . push args -4759 68/push _test-output-buffered-file/imm32 -4760 # . . call -4761 e8/call flush/disp32 -4762 # . . discard args -4763 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4764 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -4798 # . check-stream-equal(_test-output-stream, "ff 30 # ff 6/subop/push 0/mod 0/rm32", msg) -4799 # . . push args -4800 68/push "F - test-convert-instruction-emits-modrm-byte-from-subop"/imm32 -4801 68/push "ff 30 # ff 6/subop/push 0/mod 0/rm32"/imm32 -4802 68/push _test-output-stream/imm32 -4803 # . . call -4804 e8/call check-stream-equal/disp32 -4805 # . . discard args -4806 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -4807 # . epilog -4808 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -4809 5d/pop-to-EBP -4810 c3/return -4811 -4812 test-convert-instruction-emits-modrm-byte-with-missing-mod: -4813 # pack rm32 and r32 operands into ModR/M byte -4814 # . prolog -4815 55/push-EBP -4816 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -4817 # setup -4818 # . clear-stream(_test-input-stream) +4538 b8/copy-to-EAX _test-output-buffered-file/imm32 +4539 05/add-to-EAX 4/imm32 +4540 50/push-EAX +4541 # . . call +4542 e8/call clear-stream/disp32 +4543 # . . discard args +4544 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4545 # initialize input +4546 # . write(_test-input-stream, "8b/copy 0/rm32 1/r32") +4547 # . . push args +4548 68/push "8b/copy 0/rm32 1/r32"/imm32 +4549 68/push _test-input-stream/imm32 +4550 # . . call +4551 e8/call write/disp32 +4552 # . . discard args +4553 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4554 # convert-instruction(_test-input-stream, _test-output-buffered-file) +4555 # . . push args +4556 68/push _test-output-buffered-file/imm32 +4557 68/push _test-input-stream/imm32 +4558 # . . call +4559 e8/call convert-instruction/disp32 +4560 # . . discard args +4561 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4562 # check output +4563 # . flush(_test-output-buffered-file) +4564 # . . push args +4565 68/push _test-output-buffered-file/imm32 +4566 # . . call +4567 e8/call flush/disp32 +4568 # . . discard args +4569 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4570 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +4596 # . check-stream-equal(_test-output-stream, "8b 08 # 8b/copy 0/rm32 1/r32", msg) +4597 # . . push args +4598 68/push "F - test-convert-instruction-emits-modrm-byte-with-missing-mod"/imm32 +4599 68/push "8b 08 # 8b/copy 0/rm32 1/r32"/imm32 +4600 68/push _test-output-stream/imm32 +4601 # . . call +4602 e8/call check-stream-equal/disp32 +4603 # . . discard args +4604 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4605 # . epilog +4606 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4607 5d/pop-to-EBP +4608 c3/return +4609 +4610 test-convert-instruction-emits-modrm-byte-with-missing-rm32: +4611 # pack mod and r32 operands into ModR/M byte +4612 # . prolog +4613 55/push-EBP +4614 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4615 # setup +4616 # . clear-stream(_test-input-stream) +4617 # . . push args +4618 68/push _test-input-stream/imm32 +4619 # . . call +4620 e8/call clear-stream/disp32 +4621 # . . discard args +4622 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4623 # . clear-stream(_test-output-stream) +4624 # . . push args +4625 68/push _test-output-stream/imm32 +4626 # . . call +4627 e8/call clear-stream/disp32 +4628 # . . discard args +4629 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4630 # . clear-stream(_test-output-buffered-file+4) +4631 # . . push args +4632 b8/copy-to-EAX _test-output-buffered-file/imm32 +4633 05/add-to-EAX 4/imm32 +4634 50/push-EAX +4635 # . . call +4636 e8/call clear-stream/disp32 +4637 # . . discard args +4638 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4639 # initialize input +4640 # . write(_test-input-stream, "8b/copy 0/mod 1/r32") +4641 # . . push args +4642 68/push "8b/copy 0/mod 1/r32"/imm32 +4643 68/push _test-input-stream/imm32 +4644 # . . call +4645 e8/call write/disp32 +4646 # . . discard args +4647 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4648 # convert-instruction(_test-input-stream, _test-output-buffered-file) +4649 # . . push args +4650 68/push _test-output-buffered-file/imm32 +4651 68/push _test-input-stream/imm32 +4652 # . . call +4653 e8/call convert-instruction/disp32 +4654 # . . discard args +4655 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4656 # check output +4657 # . flush(_test-output-buffered-file) +4658 # . . push args +4659 68/push _test-output-buffered-file/imm32 +4660 # . . call +4661 e8/call flush/disp32 +4662 # . . discard args +4663 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4664 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +4690 # . check-stream-equal(_test-output-stream, "8b 08 # 8b/copy 0/mod 1/r32", msg) +4691 # . . push args +4692 68/push "F - test-convert-instruction-emits-modrm-byte-with-missing-rm32"/imm32 +4693 68/push "8b 08 # 8b/copy 0/mod 1/r32"/imm32 +4694 68/push _test-output-stream/imm32 +4695 # . . call +4696 e8/call check-stream-equal/disp32 +4697 # . . discard args +4698 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4699 # . epilog +4700 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4701 5d/pop-to-EBP +4702 c3/return +4703 +4704 test-convert-instruction-emits-modrm-byte-with-missing-r32: +4705 # pack mod and rm32 operands into ModR/M byte +4706 # . prolog +4707 55/push-EBP +4708 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4709 # setup +4710 # . clear-stream(_test-input-stream) +4711 # . . push args +4712 68/push _test-input-stream/imm32 +4713 # . . call +4714 e8/call clear-stream/disp32 +4715 # . . discard args +4716 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4717 # . clear-stream(_test-output-stream) +4718 # . . push args +4719 68/push _test-output-stream/imm32 +4720 # . . call +4721 e8/call clear-stream/disp32 +4722 # . . discard args +4723 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4724 # . clear-stream(_test-output-buffered-file+4) +4725 # . . push args +4726 b8/copy-to-EAX _test-output-buffered-file/imm32 +4727 05/add-to-EAX 4/imm32 +4728 50/push-EAX +4729 # . . call +4730 e8/call clear-stream/disp32 +4731 # . . discard args +4732 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4733 # initialize input +4734 # . write(_test-input-stream, "8b/copy 0/mod 0/rm32") +4735 # . . push args +4736 68/push "8b/copy 0/mod 0/rm32"/imm32 +4737 68/push _test-input-stream/imm32 +4738 # . . call +4739 e8/call write/disp32 +4740 # . . discard args +4741 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4742 # convert-instruction(_test-input-stream, _test-output-buffered-file) +4743 # . . push args +4744 68/push _test-output-buffered-file/imm32 +4745 68/push _test-input-stream/imm32 +4746 # . . call +4747 e8/call convert-instruction/disp32 +4748 # . . discard args +4749 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4750 # check output +4751 # . flush(_test-output-buffered-file) +4752 # . . push args +4753 68/push _test-output-buffered-file/imm32 +4754 # . . call +4755 e8/call flush/disp32 +4756 # . . discard args +4757 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4758 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +4784 # . check-stream-equal(_test-output-stream, "8b 00 # 8b/copy 0/mod 0/rm32", msg) +4785 # . . push args +4786 68/push "F - test-convert-instruction-emits-modrm-byte-with-missing-r32"/imm32 +4787 68/push "8b 00 # 8b/copy 0/mod 0/rm32"/imm32 +4788 68/push _test-output-stream/imm32 +4789 # . . call +4790 e8/call check-stream-equal/disp32 +4791 # . . discard args +4792 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4793 # . epilog +4794 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4795 5d/pop-to-EBP +4796 c3/return +4797 +4798 test-convert-instruction-emits-sib-byte: +4799 # pack base, index and scale operands into SIB byte +4800 # . prolog +4801 55/push-EBP +4802 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4803 # setup +4804 # . clear-stream(_test-input-stream) +4805 # . . push args +4806 68/push _test-input-stream/imm32 +4807 # . . call +4808 e8/call clear-stream/disp32 +4809 # . . discard args +4810 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4811 # . clear-stream(_test-output-stream) +4812 # . . push args +4813 68/push _test-output-stream/imm32 +4814 # . . call +4815 e8/call clear-stream/disp32 +4816 # . . discard args +4817 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4818 # . clear-stream(_test-output-buffered-file+4) 4819 # . . push args -4820 68/push _test-input-stream/imm32 -4821 # . . call -4822 e8/call clear-stream/disp32 -4823 # . . discard args -4824 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4825 # . clear-stream(_test-output-stream) -4826 # . . push args -4827 68/push _test-output-stream/imm32 -4828 # . . call -4829 e8/call clear-stream/disp32 -4830 # . . discard args -4831 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4832 # . clear-stream(_test-output-buffered-file+4) -4833 # . . push args -4834 b8/copy-to-EAX _test-output-buffered-file/imm32 -4835 05/add-to-EAX 4/imm32 -4836 50/push-EAX -4837 # . . call -4838 e8/call clear-stream/disp32 -4839 # . . discard args -4840 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4841 # initialize input -4842 # . write(_test-input-stream, "8b/copy 0/rm32 1/r32") -4843 # . . push args -4844 68/push "8b/copy 0/rm32 1/r32"/imm32 -4845 68/push _test-input-stream/imm32 -4846 # . . call -4847 e8/call write/disp32 -4848 # . . discard args -4849 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4850 # convert-instruction(_test-input-stream, _test-output-buffered-file) -4851 # . . push args -4852 68/push _test-output-buffered-file/imm32 -4853 68/push _test-input-stream/imm32 -4854 # . . call -4855 e8/call convert-instruction/disp32 -4856 # . . discard args -4857 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4858 # check output -4859 # . flush(_test-output-buffered-file) -4860 # . . push args -4861 68/push _test-output-buffered-file/imm32 -4862 # . . call -4863 e8/call flush/disp32 -4864 # . . discard args -4865 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4866 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -4900 # . check-stream-equal(_test-output-stream, "8b 08 # 8b/copy 0/rm32 1/r32", msg) -4901 # . . push args -4902 68/push "F - test-convert-instruction-emits-modrm-byte-with-missing-mod"/imm32 -4903 68/push "8b 08 # 8b/copy 0/rm32 1/r32"/imm32 -4904 68/push _test-output-stream/imm32 -4905 # . . call -4906 e8/call check-stream-equal/disp32 -4907 # . . discard args -4908 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -4909 # . epilog -4910 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -4911 5d/pop-to-EBP -4912 c3/return -4913 -4914 test-convert-instruction-emits-modrm-byte-with-missing-rm32: -4915 # pack mod and r32 operands into ModR/M byte -4916 # . prolog -4917 55/push-EBP -4918 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -4919 # setup -4920 # . clear-stream(_test-input-stream) -4921 # . . push args -4922 68/push _test-input-stream/imm32 -4923 # . . call -4924 e8/call clear-stream/disp32 -4925 # . . discard args -4926 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4927 # . clear-stream(_test-output-stream) -4928 # . . push args -4929 68/push _test-output-stream/imm32 -4930 # . . call -4931 e8/call clear-stream/disp32 -4932 # . . discard args -4933 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4934 # . clear-stream(_test-output-buffered-file+4) -4935 # . . push args -4936 b8/copy-to-EAX _test-output-buffered-file/imm32 -4937 05/add-to-EAX 4/imm32 -4938 50/push-EAX -4939 # . . call -4940 e8/call clear-stream/disp32 -4941 # . . discard args -4942 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4943 # initialize input -4944 # . write(_test-input-stream, "8b/copy 0/mod 1/r32") -4945 # . . push args -4946 68/push "8b/copy 0/mod 1/r32"/imm32 -4947 68/push _test-input-stream/imm32 -4948 # . . call -4949 e8/call write/disp32 -4950 # . . discard args -4951 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4952 # convert-instruction(_test-input-stream, _test-output-buffered-file) -4953 # . . push args -4954 68/push _test-output-buffered-file/imm32 -4955 68/push _test-input-stream/imm32 -4956 # . . call -4957 e8/call convert-instruction/disp32 -4958 # . . discard args -4959 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -4960 # check output -4961 # . flush(_test-output-buffered-file) -4962 # . . push args -4963 68/push _test-output-buffered-file/imm32 -4964 # . . call -4965 e8/call flush/disp32 -4966 # . . discard args -4967 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -4968 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -5002 # . check-stream-equal(_test-output-stream, "8b 08 # 8b/copy 0/mod 1/r32", msg) -5003 # . . push args -5004 68/push "F - test-convert-instruction-emits-modrm-byte-with-missing-rm32"/imm32 -5005 68/push "8b 08 # 8b/copy 0/mod 1/r32"/imm32 -5006 68/push _test-output-stream/imm32 -5007 # . . call -5008 e8/call check-stream-equal/disp32 -5009 # . . discard args -5010 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -5011 # . epilog -5012 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -5013 5d/pop-to-EBP -5014 c3/return -5015 -5016 test-convert-instruction-emits-modrm-byte-with-missing-r32: -5017 # pack mod and rm32 operands into ModR/M byte -5018 # . prolog -5019 55/push-EBP -5020 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -5021 # setup -5022 # . clear-stream(_test-input-stream) -5023 # . . push args -5024 68/push _test-input-stream/imm32 -5025 # . . call -5026 e8/call clear-stream/disp32 -5027 # . . discard args -5028 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5029 # . clear-stream(_test-output-stream) -5030 # . . push args -5031 68/push _test-output-stream/imm32 -5032 # . . call -5033 e8/call clear-stream/disp32 -5034 # . . discard args -5035 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5036 # . clear-stream(_test-output-buffered-file+4) -5037 # . . push args -5038 b8/copy-to-EAX _test-output-buffered-file/imm32 -5039 05/add-to-EAX 4/imm32 -5040 50/push-EAX -5041 # . . call -5042 e8/call clear-stream/disp32 -5043 # . . discard args -5044 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5045 # initialize input -5046 # . write(_test-input-stream, "8b/copy 0/mod 0/rm32") -5047 # . . push args -5048 68/push "8b/copy 0/mod 0/rm32"/imm32 -5049 68/push _test-input-stream/imm32 -5050 # . . call -5051 e8/call write/disp32 -5052 # . . discard args -5053 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5054 # convert-instruction(_test-input-stream, _test-output-buffered-file) -5055 # . . push args -5056 68/push _test-output-buffered-file/imm32 -5057 68/push _test-input-stream/imm32 -5058 # . . call -5059 e8/call convert-instruction/disp32 -5060 # . . discard args -5061 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5062 # check output -5063 # . flush(_test-output-buffered-file) -5064 # . . push args -5065 68/push _test-output-buffered-file/imm32 -5066 # . . call -5067 e8/call flush/disp32 -5068 # . . discard args -5069 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5070 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -5104 # . check-stream-equal(_test-output-stream, "8b 00 # 8b/copy 0/mod 0/rm32", msg) -5105 # . . push args -5106 68/push "F - test-convert-instruction-emits-modrm-byte-with-missing-r32"/imm32 -5107 68/push "8b 00 # 8b/copy 0/mod 0/rm32"/imm32 -5108 68/push _test-output-stream/imm32 -5109 # . . call -5110 e8/call check-stream-equal/disp32 -5111 # . . discard args -5112 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -5113 # . epilog -5114 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -5115 5d/pop-to-EBP -5116 c3/return -5117 -5118 test-convert-instruction-emits-sib-byte: -5119 # pack base, index and scale operands into SIB byte -5120 # . prolog -5121 55/push-EBP -5122 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -5123 # setup -5124 # . clear-stream(_test-input-stream) -5125 # . . push args -5126 68/push _test-input-stream/imm32 -5127 # . . call -5128 e8/call clear-stream/disp32 -5129 # . . discard args -5130 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5131 # . clear-stream(_test-output-stream) -5132 # . . push args -5133 68/push _test-output-stream/imm32 -5134 # . . call -5135 e8/call clear-stream/disp32 -5136 # . . discard args -5137 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5138 # . clear-stream(_test-output-buffered-file+4) -5139 # . . push args -5140 b8/copy-to-EAX _test-output-buffered-file/imm32 -5141 05/add-to-EAX 4/imm32 -5142 50/push-EAX -5143 # . . call -5144 e8/call clear-stream/disp32 -5145 # . . discard args -5146 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5147 # initialize input -5148 # . write(_test-input-stream, "8b/copy 0/mod 4/rm32 1/r32 0/base 1/index 0/scale") -5149 # . . push args -5150 68/push "8b/copy 0/mod 4/rm32 1/r32 0/base 1/index 0/scale"/imm32 -5151 68/push _test-input-stream/imm32 -5152 # . . call -5153 e8/call write/disp32 -5154 # . . discard args -5155 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5156 # convert-instruction(_test-input-stream, _test-output-buffered-file) -5157 # . . push args -5158 68/push _test-output-buffered-file/imm32 -5159 68/push _test-input-stream/imm32 -5160 # . . call -5161 e8/call convert-instruction/disp32 -5162 # . . discard args -5163 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5164 # check output -5165 # . flush(_test-output-buffered-file) -5166 # . . push args -5167 68/push _test-output-buffered-file/imm32 -5168 # . . call -5169 e8/call flush/disp32 -5170 # . . discard args -5171 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5172 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -5206 # . check-stream-equal(_test-output-stream, "8b 08 # 8b/copy 0/mod 4/rm32 1/r32 0/base 1/index 0/scale", msg) -5207 # . . push args -5208 68/push "F - test-convert-instruction-emits-sib-byte"/imm32 -5209 68/push "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 0/base 1/index 0/scale"/imm32 -5210 68/push _test-output-stream/imm32 -5211 # . . call -5212 e8/call check-stream-equal/disp32 -5213 # . . discard args -5214 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -5215 # . epilog -5216 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -5217 5d/pop-to-EBP -5218 c3/return -5219 -5220 test-convert-instruction-emits-sib-byte-with-missing-base: -5221 # pack index and scale operands into SIB byte -5222 # . prolog -5223 55/push-EBP -5224 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -5225 # setup -5226 # . clear-stream(_test-input-stream) -5227 # . . push args -5228 68/push _test-input-stream/imm32 -5229 # . . call -5230 e8/call clear-stream/disp32 -5231 # . . discard args -5232 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5233 # . clear-stream(_test-output-stream) -5234 # . . push args -5235 68/push _test-output-stream/imm32 -5236 # . . call -5237 e8/call clear-stream/disp32 -5238 # . . discard args -5239 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5240 # . clear-stream(_test-output-buffered-file+4) -5241 # . . push args -5242 b8/copy-to-EAX _test-output-buffered-file/imm32 -5243 05/add-to-EAX 4/imm32 -5244 50/push-EAX -5245 # . . call -5246 e8/call clear-stream/disp32 -5247 # . . discard args -5248 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5249 # initialize input -5250 # . write(_test-input-stream, "8b/copy 0/mod 4/rm32 1/r32 1/index 0/scale") -5251 # . . push args -5252 68/push "8b/copy 0/mod 4/rm32 1/r32 1/index 0/scale"/imm32 -5253 68/push _test-input-stream/imm32 -5254 # . . call -5255 e8/call write/disp32 -5256 # . . discard args -5257 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5258 # convert-instruction(_test-input-stream, _test-output-buffered-file) -5259 # . . push args -5260 68/push _test-output-buffered-file/imm32 -5261 68/push _test-input-stream/imm32 -5262 # . . call -5263 e8/call convert-instruction/disp32 -5264 # . . discard args -5265 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5266 # check output -5267 # . flush(_test-output-buffered-file) -5268 # . . push args -5269 68/push _test-output-buffered-file/imm32 -5270 # . . call -5271 e8/call flush/disp32 -5272 # . . discard args -5273 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5274 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -5308 # . check-stream-equal(_test-output-stream, "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 1/index 0/scale", msg) -5309 # . . push args -5310 68/push "F - test-convert-instruction-emits-sib-byte-with-missing-base"/imm32 -5311 68/push "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 1/index 0/scale"/imm32 -5312 68/push _test-output-stream/imm32 -5313 # . . call -5314 e8/call check-stream-equal/disp32 -5315 # . . discard args -5316 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -5317 # . epilog -5318 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -5319 5d/pop-to-EBP -5320 c3/return -5321 -5322 test-convert-instruction-emits-sib-byte-with-missing-index: -5323 # pack base and scale operands into SIB byte -5324 # . prolog -5325 55/push-EBP -5326 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -5327 # setup -5328 # . clear-stream(_test-input-stream) -5329 # . . push args -5330 68/push _test-input-stream/imm32 -5331 # . . call -5332 e8/call clear-stream/disp32 -5333 # . . discard args -5334 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5335 # . clear-stream(_test-output-stream) -5336 # . . push args -5337 68/push _test-output-stream/imm32 -5338 # . . call -5339 e8/call clear-stream/disp32 -5340 # . . discard args -5341 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5342 # . clear-stream(_test-output-buffered-file+4) -5343 # . . push args -5344 b8/copy-to-EAX _test-output-buffered-file/imm32 -5345 05/add-to-EAX 4/imm32 -5346 50/push-EAX -5347 # . . call -5348 e8/call clear-stream/disp32 -5349 # . . discard args -5350 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5351 # initialize input -5352 # . write(_test-input-stream, "8b/copy 0/mod 4/rm32 1/r32 0/base 0/scale") -5353 # . . push args -5354 68/push "8b/copy 0/mod 4/rm32 1/r32 0/base 0/scale"/imm32 -5355 68/push _test-input-stream/imm32 -5356 # . . call -5357 e8/call write/disp32 -5358 # . . discard args -5359 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5360 # convert-instruction(_test-input-stream, _test-output-buffered-file) -5361 # . . push args -5362 68/push _test-output-buffered-file/imm32 -5363 68/push _test-input-stream/imm32 -5364 # . . call -5365 e8/call convert-instruction/disp32 -5366 # . . discard args -5367 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5368 # check output -5369 # . flush(_test-output-buffered-file) -5370 # . . push args -5371 68/push _test-output-buffered-file/imm32 -5372 # . . call -5373 e8/call flush/disp32 -5374 # . . discard args -5375 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5376 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -5410 # . check-stream-equal(_test-output-stream, "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 0/base 0/scale", msg) -5411 # . . push args -5412 68/push "F - test-convert-instruction-emits-sib-byte-with-missing-index"/imm32 -5413 68/push "8b 0c 00 # 8b/copy 0/mod 4/rm32 1/r32 0/base 0/scale"/imm32 -5414 68/push _test-output-stream/imm32 -5415 # . . call -5416 e8/call check-stream-equal/disp32 -5417 # . . discard args -5418 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -5419 # . epilog -5420 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -5421 5d/pop-to-EBP -5422 c3/return -5423 -5424 test-convert-instruction-emits-sib-byte-with-missing-scale: -5425 # pack base and index operands into SIB byte -5426 # . prolog -5427 55/push-EBP -5428 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -5429 # setup -5430 # . clear-stream(_test-input-stream) -5431 # . . push args -5432 68/push _test-input-stream/imm32 -5433 # . . call -5434 e8/call clear-stream/disp32 -5435 # . . discard args -5436 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5437 # . clear-stream(_test-output-stream) -5438 # . . push args -5439 68/push _test-output-stream/imm32 -5440 # . . call -5441 e8/call clear-stream/disp32 -5442 # . . discard args -5443 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5444 # . clear-stream(_test-output-buffered-file+4) -5445 # . . push args -5446 b8/copy-to-EAX _test-output-buffered-file/imm32 -5447 05/add-to-EAX 4/imm32 -5448 50/push-EAX -5449 # . . call -5450 e8/call clear-stream/disp32 -5451 # . . discard args -5452 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5453 # initialize input -5454 # . write(_test-input-stream, "8b/copy 0/mod 4/rm32 1/r32 0/base 1/index") -5455 # . . push args -5456 68/push "8b/copy 0/mod 4/rm32 1/r32 0/base 1/index"/imm32 -5457 68/push _test-input-stream/imm32 -5458 # . . call -5459 e8/call write/disp32 -5460 # . . discard args -5461 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5462 # convert-instruction(_test-input-stream, _test-output-buffered-file) +4820 b8/copy-to-EAX _test-output-buffered-file/imm32 +4821 05/add-to-EAX 4/imm32 +4822 50/push-EAX +4823 # . . call +4824 e8/call clear-stream/disp32 +4825 # . . discard args +4826 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4827 # initialize input +4828 # . write(_test-input-stream, "8b/copy 0/mod 4/rm32 1/r32 0/base 1/index 0/scale") +4829 # . . push args +4830 68/push "8b/copy 0/mod 4/rm32 1/r32 0/base 1/index 0/scale"/imm32 +4831 68/push _test-input-stream/imm32 +4832 # . . call +4833 e8/call write/disp32 +4834 # . . discard args +4835 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4836 # convert-instruction(_test-input-stream, _test-output-buffered-file) +4837 # . . push args +4838 68/push _test-output-buffered-file/imm32 +4839 68/push _test-input-stream/imm32 +4840 # . . call +4841 e8/call convert-instruction/disp32 +4842 # . . discard args +4843 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4844 # check output +4845 # . flush(_test-output-buffered-file) +4846 # . . push args +4847 68/push _test-output-buffered-file/imm32 +4848 # . . call +4849 e8/call flush/disp32 +4850 # . . discard args +4851 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4852 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +4878 # . check-stream-equal(_test-output-stream, "8b 08 # 8b/copy 0/mod 4/rm32 1/r32 0/base 1/index 0/scale", msg) +4879 # . . push args +4880 68/push "F - test-convert-instruction-emits-sib-byte"/imm32 +4881 68/push "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 0/base 1/index 0/scale"/imm32 +4882 68/push _test-output-stream/imm32 +4883 # . . call +4884 e8/call check-stream-equal/disp32 +4885 # . . discard args +4886 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4887 # . epilog +4888 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4889 5d/pop-to-EBP +4890 c3/return +4891 +4892 test-convert-instruction-emits-sib-byte-with-missing-base: +4893 # pack index and scale operands into SIB byte +4894 # . prolog +4895 55/push-EBP +4896 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4897 # setup +4898 # . clear-stream(_test-input-stream) +4899 # . . push args +4900 68/push _test-input-stream/imm32 +4901 # . . call +4902 e8/call clear-stream/disp32 +4903 # . . discard args +4904 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4905 # . clear-stream(_test-output-stream) +4906 # . . push args +4907 68/push _test-output-stream/imm32 +4908 # . . call +4909 e8/call clear-stream/disp32 +4910 # . . discard args +4911 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4912 # . clear-stream(_test-output-buffered-file+4) +4913 # . . push args +4914 b8/copy-to-EAX _test-output-buffered-file/imm32 +4915 05/add-to-EAX 4/imm32 +4916 50/push-EAX +4917 # . . call +4918 e8/call clear-stream/disp32 +4919 # . . discard args +4920 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4921 # initialize input +4922 # . write(_test-input-stream, "8b/copy 0/mod 4/rm32 1/r32 1/index 0/scale") +4923 # . . push args +4924 68/push "8b/copy 0/mod 4/rm32 1/r32 1/index 0/scale"/imm32 +4925 68/push _test-input-stream/imm32 +4926 # . . call +4927 e8/call write/disp32 +4928 # . . discard args +4929 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4930 # convert-instruction(_test-input-stream, _test-output-buffered-file) +4931 # . . push args +4932 68/push _test-output-buffered-file/imm32 +4933 68/push _test-input-stream/imm32 +4934 # . . call +4935 e8/call convert-instruction/disp32 +4936 # . . discard args +4937 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +4938 # check output +4939 # . flush(_test-output-buffered-file) +4940 # . . push args +4941 68/push _test-output-buffered-file/imm32 +4942 # . . call +4943 e8/call flush/disp32 +4944 # . . discard args +4945 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4946 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +4972 # . check-stream-equal(_test-output-stream, "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 1/index 0/scale", msg) +4973 # . . push args +4974 68/push "F - test-convert-instruction-emits-sib-byte-with-missing-base"/imm32 +4975 68/push "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 1/index 0/scale"/imm32 +4976 68/push _test-output-stream/imm32 +4977 # . . call +4978 e8/call check-stream-equal/disp32 +4979 # . . discard args +4980 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +4981 # . epilog +4982 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +4983 5d/pop-to-EBP +4984 c3/return +4985 +4986 test-convert-instruction-emits-sib-byte-with-missing-index: +4987 # pack base and scale operands into SIB byte +4988 # . prolog +4989 55/push-EBP +4990 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +4991 # setup +4992 # . clear-stream(_test-input-stream) +4993 # . . push args +4994 68/push _test-input-stream/imm32 +4995 # . . call +4996 e8/call clear-stream/disp32 +4997 # . . discard args +4998 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +4999 # . clear-stream(_test-output-stream) +5000 # . . push args +5001 68/push _test-output-stream/imm32 +5002 # . . call +5003 e8/call clear-stream/disp32 +5004 # . . discard args +5005 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5006 # . clear-stream(_test-output-buffered-file+4) +5007 # . . push args +5008 b8/copy-to-EAX _test-output-buffered-file/imm32 +5009 05/add-to-EAX 4/imm32 +5010 50/push-EAX +5011 # . . call +5012 e8/call clear-stream/disp32 +5013 # . . discard args +5014 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5015 # initialize input +5016 # . write(_test-input-stream, "8b/copy 0/mod 4/rm32 1/r32 0/base 0/scale") +5017 # . . push args +5018 68/push "8b/copy 0/mod 4/rm32 1/r32 0/base 0/scale"/imm32 +5019 68/push _test-input-stream/imm32 +5020 # . . call +5021 e8/call write/disp32 +5022 # . . discard args +5023 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5024 # convert-instruction(_test-input-stream, _test-output-buffered-file) +5025 # . . push args +5026 68/push _test-output-buffered-file/imm32 +5027 68/push _test-input-stream/imm32 +5028 # . . call +5029 e8/call convert-instruction/disp32 +5030 # . . discard args +5031 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5032 # check output +5033 # . flush(_test-output-buffered-file) +5034 # . . push args +5035 68/push _test-output-buffered-file/imm32 +5036 # . . call +5037 e8/call flush/disp32 +5038 # . . discard args +5039 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5040 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +5066 # . check-stream-equal(_test-output-stream, "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 0/base 0/scale", msg) +5067 # . . push args +5068 68/push "F - test-convert-instruction-emits-sib-byte-with-missing-index"/imm32 +5069 68/push "8b 0c 00 # 8b/copy 0/mod 4/rm32 1/r32 0/base 0/scale"/imm32 +5070 68/push _test-output-stream/imm32 +5071 # . . call +5072 e8/call check-stream-equal/disp32 +5073 # . . discard args +5074 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +5075 # . epilog +5076 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +5077 5d/pop-to-EBP +5078 c3/return +5079 +5080 test-convert-instruction-emits-sib-byte-with-missing-scale: +5081 # pack base and index operands into SIB byte +5082 # . prolog +5083 55/push-EBP +5084 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +5085 # setup +5086 # . clear-stream(_test-input-stream) +5087 # . . push args +5088 68/push _test-input-stream/imm32 +5089 # . . call +5090 e8/call clear-stream/disp32 +5091 # . . discard args +5092 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5093 # . clear-stream(_test-output-stream) +5094 # . . push args +5095 68/push _test-output-stream/imm32 +5096 # . . call +5097 e8/call clear-stream/disp32 +5098 # . . discard args +5099 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5100 # . clear-stream(_test-output-buffered-file+4) +5101 # . . push args +5102 b8/copy-to-EAX _test-output-buffered-file/imm32 +5103 05/add-to-EAX 4/imm32 +5104 50/push-EAX +5105 # . . call +5106 e8/call clear-stream/disp32 +5107 # . . discard args +5108 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5109 # initialize input +5110 # . write(_test-input-stream, "8b/copy 0/mod 4/rm32 1/r32 0/base 1/index") +5111 # . . push args +5112 68/push "8b/copy 0/mod 4/rm32 1/r32 0/base 1/index"/imm32 +5113 68/push _test-input-stream/imm32 +5114 # . . call +5115 e8/call write/disp32 +5116 # . . discard args +5117 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5118 # convert-instruction(_test-input-stream, _test-output-buffered-file) +5119 # . . push args +5120 68/push _test-output-buffered-file/imm32 +5121 68/push _test-input-stream/imm32 +5122 # . . call +5123 e8/call convert-instruction/disp32 +5124 # . . discard args +5125 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5126 # check output +5127 # . flush(_test-output-buffered-file) +5128 # . . push args +5129 68/push _test-output-buffered-file/imm32 +5130 # . . call +5131 e8/call flush/disp32 +5132 # . . discard args +5133 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5134 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +5160 # . check-stream-equal(_test-output-stream, "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 0/base 1/index", msg) +5161 # . . push args +5162 68/push "F - test-convert-instruction-emits-sib-byte-with-missing-scale"/imm32 +5163 68/push "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 0/base 1/index"/imm32 +5164 68/push _test-output-stream/imm32 +5165 # . . call +5166 e8/call check-stream-equal/disp32 +5167 # . . discard args +5168 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +5169 # . epilog +5170 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +5171 5d/pop-to-EBP +5172 c3/return +5173 +5174 test-convert-instruction-handles-disp32-operand: +5175 # expand /disp32 operand into 4 bytes +5176 # . prolog +5177 55/push-EBP +5178 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +5179 # setup +5180 # . clear-stream(_test-input-stream) +5181 # . . push args +5182 68/push _test-input-stream/imm32 +5183 # . . call +5184 e8/call clear-stream/disp32 +5185 # . . discard args +5186 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5187 # . clear-stream(_test-output-stream) +5188 # . . push args +5189 68/push _test-output-stream/imm32 +5190 # . . call +5191 e8/call clear-stream/disp32 +5192 # . . discard args +5193 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5194 # . clear-stream(_test-output-buffered-file+4) +5195 # . . push args +5196 b8/copy-to-EAX _test-output-buffered-file/imm32 +5197 05/add-to-EAX 4/imm32 +5198 50/push-EAX +5199 # . . call +5200 e8/call clear-stream/disp32 +5201 # . . discard args +5202 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5203 # initialize input +5204 # . write(_test-input-stream, "e8/call 20/disp32") +5205 # . . push args +5206 68/push "e8/call 20/disp32"/imm32 +5207 68/push _test-input-stream/imm32 +5208 # . . call +5209 e8/call write/disp32 +5210 # . . discard args +5211 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5212 # convert-instruction(_test-input-stream, _test-output-buffered-file) +5213 # . . push args +5214 68/push _test-output-buffered-file/imm32 +5215 68/push _test-input-stream/imm32 +5216 # . . call +5217 e8/call convert-instruction/disp32 +5218 # . . discard args +5219 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5220 # check output +5221 # . flush(_test-output-buffered-file) +5222 # . . push args +5223 68/push _test-output-buffered-file/imm32 +5224 # . . call +5225 e8/call flush/disp32 +5226 # . . discard args +5227 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5228 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +5254 # . check-stream-equal(_test-output-stream, "e8 20 00 00 00 # e8/call 20/disp32", msg) +5255 # . . push args +5256 68/push "F - test-convert-instruction-handles-disp32-operand"/imm32 +5257 68/push "e8 20 00 00 00 # e8/call 20/disp32"/imm32 +5258 68/push _test-output-stream/imm32 +5259 # . . call +5260 e8/call check-stream-equal/disp32 +5261 # . . discard args +5262 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +5263 # . epilog +5264 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +5265 5d/pop-to-EBP +5266 c3/return +5267 +5268 test-convert-instruction-handles-disp16-operand: +5269 # expand /disp16 operand into 2 bytes +5270 # . prolog +5271 55/push-EBP +5272 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +5273 # setup +5274 # . clear-stream(_test-input-stream) +5275 # . . push args +5276 68/push _test-input-stream/imm32 +5277 # . . call +5278 e8/call clear-stream/disp32 +5279 # . . discard args +5280 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5281 # . clear-stream(_test-output-stream) +5282 # . . push args +5283 68/push _test-output-stream/imm32 +5284 # . . call +5285 e8/call clear-stream/disp32 +5286 # . . discard args +5287 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5288 # . clear-stream(_test-output-buffered-file+4) +5289 # . . push args +5290 b8/copy-to-EAX _test-output-buffered-file/imm32 +5291 05/add-to-EAX 4/imm32 +5292 50/push-EAX +5293 # . . call +5294 e8/call clear-stream/disp32 +5295 # . . discard args +5296 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5297 # initialize input +5298 # . write(_test-input-stream, "e8/call 20/disp16") +5299 # . . push args +5300 68/push "e8/call 20/disp16"/imm32 # not a valid instruction +5301 68/push _test-input-stream/imm32 +5302 # . . call +5303 e8/call write/disp32 +5304 # . . discard args +5305 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5306 # convert-instruction(_test-input-stream, _test-output-buffered-file) +5307 # . . push args +5308 68/push _test-output-buffered-file/imm32 +5309 68/push _test-input-stream/imm32 +5310 # . . call +5311 e8/call convert-instruction/disp32 +5312 # . . discard args +5313 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5314 # check output +5315 # . flush(_test-output-buffered-file) +5316 # . . push args +5317 68/push _test-output-buffered-file/imm32 +5318 # . . call +5319 e8/call flush/disp32 +5320 # . . discard args +5321 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5322 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +5348 # . check-stream-equal(_test-output-stream, "e8 20 00 # e8/call 20/disp16", msg) +5349 # . . push args +5350 68/push "F - test-convert-instruction-handles-disp16-operand"/imm32 +5351 68/push "e8 20 00 # e8/call 20/disp16"/imm32 +5352 68/push _test-output-stream/imm32 +5353 # . . call +5354 e8/call check-stream-equal/disp32 +5355 # . . discard args +5356 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +5357 # . epilog +5358 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +5359 5d/pop-to-EBP +5360 c3/return +5361 +5362 test-convert-instruction-handles-disp8-operand: +5363 # expand /disp8 operand into 1 byte +5364 # . prolog +5365 55/push-EBP +5366 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +5367 # setup +5368 # . clear-stream(_test-input-stream) +5369 # . . push args +5370 68/push _test-input-stream/imm32 +5371 # . . call +5372 e8/call clear-stream/disp32 +5373 # . . discard args +5374 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5375 # . clear-stream(_test-output-stream) +5376 # . . push args +5377 68/push _test-output-stream/imm32 +5378 # . . call +5379 e8/call clear-stream/disp32 +5380 # . . discard args +5381 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5382 # . clear-stream(_test-output-buffered-file+4) +5383 # . . push args +5384 b8/copy-to-EAX _test-output-buffered-file/imm32 +5385 05/add-to-EAX 4/imm32 +5386 50/push-EAX +5387 # . . call +5388 e8/call clear-stream/disp32 +5389 # . . discard args +5390 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5391 # initialize input +5392 # . write(_test-input-stream, "eb/jump 20/disp8") +5393 # . . push args +5394 68/push "eb/jump 20/disp8"/imm32 +5395 68/push _test-input-stream/imm32 +5396 # . . call +5397 e8/call write/disp32 +5398 # . . discard args +5399 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5400 # convert-instruction(_test-input-stream, _test-output-buffered-file) +5401 # . . push args +5402 68/push _test-output-buffered-file/imm32 +5403 68/push _test-input-stream/imm32 +5404 # . . call +5405 e8/call convert-instruction/disp32 +5406 # . . discard args +5407 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5408 # check output +5409 # . flush(_test-output-buffered-file) +5410 # . . push args +5411 68/push _test-output-buffered-file/imm32 +5412 # . . call +5413 e8/call flush/disp32 +5414 # . . discard args +5415 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5416 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +5442 # . check-stream-equal(_test-output-stream, "eb 20 # eb/jump 20/disp8", msg) +5443 # . . push args +5444 68/push "F - test-convert-instruction-handles-disp8-operand"/imm32 +5445 68/push "eb 20 # eb/jump 20/disp8"/imm32 +5446 68/push _test-output-stream/imm32 +5447 # . . call +5448 e8/call check-stream-equal/disp32 +5449 # . . discard args +5450 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +5451 # . epilog +5452 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +5453 5d/pop-to-EBP +5454 c3/return +5455 +5456 test-convert-instruction-handles-disp8-name: +5457 # pass /disp8 name directly through +5458 # . prolog +5459 55/push-EBP +5460 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +5461 # setup +5462 # . clear-stream(_test-input-stream) 5463 # . . push args -5464 68/push _test-output-buffered-file/imm32 -5465 68/push _test-input-stream/imm32 -5466 # . . call -5467 e8/call convert-instruction/disp32 -5468 # . . discard args -5469 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5470 # check output -5471 # . flush(_test-output-buffered-file) -5472 # . . push args -5473 68/push _test-output-buffered-file/imm32 -5474 # . . call -5475 e8/call flush/disp32 -5476 # . . discard args -5477 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5478 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -5512 # . check-stream-equal(_test-output-stream, "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 0/base 1/index", msg) -5513 # . . push args -5514 68/push "F - test-convert-instruction-emits-sib-byte-with-missing-scale"/imm32 -5515 68/push "8b 0c 08 # 8b/copy 0/mod 4/rm32 1/r32 0/base 1/index"/imm32 -5516 68/push _test-output-stream/imm32 -5517 # . . call -5518 e8/call check-stream-equal/disp32 -5519 # . . discard args -5520 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -5521 # . epilog -5522 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -5523 5d/pop-to-EBP -5524 c3/return -5525 -5526 test-convert-instruction-handles-disp32-operand: -5527 # expand /disp32 operand into 4 bytes -5528 # . prolog -5529 55/push-EBP -5530 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -5531 # setup -5532 # . clear-stream(_test-input-stream) -5533 # . . push args -5534 68/push _test-input-stream/imm32 -5535 # . . call -5536 e8/call clear-stream/disp32 -5537 # . . discard args -5538 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5539 # . clear-stream(_test-output-stream) -5540 # . . push args -5541 68/push _test-output-stream/imm32 -5542 # . . call -5543 e8/call clear-stream/disp32 -5544 # . . discard args -5545 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5546 # . clear-stream(_test-output-buffered-file+4) -5547 # . . push args -5548 b8/copy-to-EAX _test-output-buffered-file/imm32 -5549 05/add-to-EAX 4/imm32 -5550 50/push-EAX -5551 # . . call -5552 e8/call clear-stream/disp32 -5553 # . . discard args -5554 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5555 # initialize input -5556 # . write(_test-input-stream, "e8/call 20/disp32") +5464 68/push _test-input-stream/imm32 +5465 # . . call +5466 e8/call clear-stream/disp32 +5467 # . . discard args +5468 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5469 # . clear-stream(_test-output-stream) +5470 # . . push args +5471 68/push _test-output-stream/imm32 +5472 # . . call +5473 e8/call clear-stream/disp32 +5474 # . . discard args +5475 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5476 # . clear-stream(_test-output-buffered-file+4) +5477 # . . push args +5478 b8/copy-to-EAX _test-output-buffered-file/imm32 +5479 05/add-to-EAX 4/imm32 +5480 50/push-EAX +5481 # . . call +5482 e8/call clear-stream/disp32 +5483 # . . discard args +5484 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5485 # initialize input +5486 # . write(_test-input-stream, "eb/jump xyz/disp8") +5487 # . . push args +5488 68/push "eb/jump xyz/disp8"/imm32 +5489 68/push _test-input-stream/imm32 +5490 # . . call +5491 e8/call write/disp32 +5492 # . . discard args +5493 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5494 # convert-instruction(_test-input-stream, _test-output-buffered-file) +5495 # . . push args +5496 68/push _test-output-buffered-file/imm32 +5497 68/push _test-input-stream/imm32 +5498 # . . call +5499 e8/call convert-instruction/disp32 +5500 # . . discard args +5501 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5502 # check output +5503 # . flush(_test-output-buffered-file) +5504 # . . push args +5505 68/push _test-output-buffered-file/imm32 +5506 # . . call +5507 e8/call flush/disp32 +5508 # . . discard args +5509 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5510 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +5536 # . check-stream-equal(_test-output-stream, "eb xyz/disp8 # eb/jump xyz/disp8", msg) +5537 # . . push args +5538 68/push "F - test-convert-instruction-handles-disp8-name"/imm32 +5539 68/push "eb xyz/disp8 # eb/jump xyz/disp8"/imm32 +5540 68/push _test-output-stream/imm32 +5541 # . . call +5542 e8/call check-stream-equal/disp32 +5543 # . . discard args +5544 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +5545 # . epilog +5546 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +5547 5d/pop-to-EBP +5548 c3/return +5549 +5550 test-convert-instruction-handles-imm32-operand: +5551 # expand /imm32 operand into 4 bytes +5552 # . prolog +5553 55/push-EBP +5554 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +5555 # setup +5556 # . clear-stream(_test-input-stream) 5557 # . . push args -5558 68/push "e8/call 20/disp32"/imm32 -5559 68/push _test-input-stream/imm32 -5560 # . . call -5561 e8/call write/disp32 -5562 # . . discard args -5563 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5564 # convert-instruction(_test-input-stream, _test-output-buffered-file) -5565 # . . push args -5566 68/push _test-output-buffered-file/imm32 -5567 68/push _test-input-stream/imm32 -5568 # . . call -5569 e8/call convert-instruction/disp32 -5570 # . . discard args -5571 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5572 # check output -5573 # . flush(_test-output-buffered-file) -5574 # . . push args -5575 68/push _test-output-buffered-file/imm32 -5576 # . . call -5577 e8/call flush/disp32 -5578 # . . discard args -5579 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5580 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -5614 # . check-stream-equal(_test-output-stream, "e8 20 00 00 00 # e8/call 20/disp32", msg) -5615 # . . push args -5616 68/push "F - test-convert-instruction-handles-disp32-operand"/imm32 -5617 68/push "e8 20 00 00 00 # e8/call 20/disp32"/imm32 -5618 68/push _test-output-stream/imm32 -5619 # . . call -5620 e8/call check-stream-equal/disp32 -5621 # . . discard args -5622 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -5623 # . epilog -5624 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -5625 5d/pop-to-EBP -5626 c3/return -5627 -5628 test-convert-instruction-handles-disp16-operand: -5629 # expand /disp16 operand into 2 bytes -5630 # . prolog -5631 55/push-EBP -5632 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -5633 # setup -5634 # . clear-stream(_test-input-stream) -5635 # . . push args -5636 68/push _test-input-stream/imm32 -5637 # . . call -5638 e8/call clear-stream/disp32 -5639 # . . discard args -5640 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5641 # . clear-stream(_test-output-stream) -5642 # . . push args -5643 68/push _test-output-stream/imm32 -5644 # . . call -5645 e8/call clear-stream/disp32 -5646 # . . discard args -5647 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5648 # . clear-stream(_test-output-buffered-file+4) -5649 # . . push args -5650 b8/copy-to-EAX _test-output-buffered-file/imm32 -5651 05/add-to-EAX 4/imm32 -5652 50/push-EAX -5653 # . . call -5654 e8/call clear-stream/disp32 -5655 # . . discard args -5656 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5657 # initialize input -5658 # . write(_test-input-stream, "e8/call 20/disp16") +5558 68/push _test-input-stream/imm32 +5559 # . . call +5560 e8/call clear-stream/disp32 +5561 # . . discard args +5562 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5563 # . clear-stream(_test-output-stream) +5564 # . . push args +5565 68/push _test-output-stream/imm32 +5566 # . . call +5567 e8/call clear-stream/disp32 +5568 # . . discard args +5569 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5570 # . clear-stream(_test-output-buffered-file+4) +5571 # . . push args +5572 b8/copy-to-EAX _test-output-buffered-file/imm32 +5573 05/add-to-EAX 4/imm32 +5574 50/push-EAX +5575 # . . call +5576 e8/call clear-stream/disp32 +5577 # . . discard args +5578 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5579 # initialize input +5580 # . write(_test-input-stream, "68/push 0x20/imm32") +5581 # . . push args +5582 68/push "68/push 0x20/imm32"/imm32 +5583 68/push _test-input-stream/imm32 +5584 # . . call +5585 e8/call write/disp32 +5586 # . . discard args +5587 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5588 # convert-instruction(_test-input-stream, _test-output-buffered-file) +5589 # . . push args +5590 68/push _test-output-buffered-file/imm32 +5591 68/push _test-input-stream/imm32 +5592 # . . call +5593 e8/call convert-instruction/disp32 +5594 # . . discard args +5595 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5596 # check output +5597 # . flush(_test-output-buffered-file) +5598 # . . push args +5599 68/push _test-output-buffered-file/imm32 +5600 # . . call +5601 e8/call flush/disp32 +5602 # . . discard args +5603 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5604 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +5630 # . check-stream-equal(_test-output-stream, "68 20 00 00 00 # 68/push 0x20/imm32", msg) +5631 # . . push args +5632 68/push "F - test-convert-instruction-handles-imm32-operand"/imm32 +5633 68/push "68 20 00 00 00 # 68/push 0x20/imm32"/imm32 +5634 68/push _test-output-stream/imm32 +5635 # . . call +5636 e8/call check-stream-equal/disp32 +5637 # . . discard args +5638 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +5639 # . epilog +5640 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +5641 5d/pop-to-EBP +5642 c3/return +5643 +5644 test-convert-instruction-handles-imm16-operand: +5645 # expand /imm16 operand into 2 bytes +5646 # we don't have one of these at the moment, so this expands to an invalid instruction +5647 # . prolog +5648 55/push-EBP +5649 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +5650 # setup +5651 # . clear-stream(_test-input-stream) +5652 # . . push args +5653 68/push _test-input-stream/imm32 +5654 # . . call +5655 e8/call clear-stream/disp32 +5656 # . . discard args +5657 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5658 # . clear-stream(_test-output-stream) 5659 # . . push args -5660 68/push "e8/call 20/disp16"/imm32 # not a valid instruction -5661 68/push _test-input-stream/imm32 -5662 # . . call -5663 e8/call write/disp32 -5664 # . . discard args -5665 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5666 # convert-instruction(_test-input-stream, _test-output-buffered-file) -5667 # . . push args -5668 68/push _test-output-buffered-file/imm32 -5669 68/push _test-input-stream/imm32 +5660 68/push _test-output-stream/imm32 +5661 # . . call +5662 e8/call clear-stream/disp32 +5663 # . . discard args +5664 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5665 # . clear-stream(_test-output-buffered-file+4) +5666 # . . push args +5667 b8/copy-to-EAX _test-output-buffered-file/imm32 +5668 05/add-to-EAX 4/imm32 +5669 50/push-EAX 5670 # . . call -5671 e8/call convert-instruction/disp32 +5671 e8/call clear-stream/disp32 5672 # . . discard args -5673 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5674 # check output -5675 # . flush(_test-output-buffered-file) +5673 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5674 # initialize input +5675 # . write(_test-input-stream, "68/push 0x20/imm16") 5676 # . . push args -5677 68/push _test-output-buffered-file/imm32 -5678 # . . call -5679 e8/call flush/disp32 -5680 # . . discard args -5681 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5682 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -5716 # . check-stream-equal(_test-output-stream, "e8 20 00 # e8/call 20/disp16", msg) -5717 # . . push args -5718 68/push "F - test-convert-instruction-handles-disp16-operand"/imm32 -5719 68/push "e8 20 00 # e8/call 20/disp16"/imm32 -5720 68/push _test-output-stream/imm32 -5721 # . . call -5722 e8/call check-stream-equal/disp32 -5723 # . . discard args -5724 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -5725 # . epilog -5726 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -5727 5d/pop-to-EBP -5728 c3/return -5729 -5730 test-convert-instruction-handles-disp8-operand: -5731 # expand /disp8 operand into 1 byte -5732 # . prolog -5733 55/push-EBP -5734 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -5735 # setup -5736 # . clear-stream(_test-input-stream) -5737 # . . push args -5738 68/push _test-input-stream/imm32 -5739 # . . call -5740 e8/call clear-stream/disp32 -5741 # . . discard args -5742 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5743 # . clear-stream(_test-output-stream) -5744 # . . push args -5745 68/push _test-output-stream/imm32 -5746 # . . call -5747 e8/call clear-stream/disp32 -5748 # . . discard args -5749 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5750 # . clear-stream(_test-output-buffered-file+4) -5751 # . . push args -5752 b8/copy-to-EAX _test-output-buffered-file/imm32 -5753 05/add-to-EAX 4/imm32 -5754 50/push-EAX -5755 # . . call -5756 e8/call clear-stream/disp32 -5757 # . . discard args -5758 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5759 # initialize input -5760 # . write(_test-input-stream, "eb/jump 20/disp8") +5677 68/push "68/push 0x20/imm16"/imm32 # not a valid instruction +5678 68/push _test-input-stream/imm32 +5679 # . . call +5680 e8/call write/disp32 +5681 # . . discard args +5682 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5683 # convert-instruction(_test-input-stream, _test-output-buffered-file) +5684 # . . push args +5685 68/push _test-output-buffered-file/imm32 +5686 68/push _test-input-stream/imm32 +5687 # . . call +5688 e8/call convert-instruction/disp32 +5689 # . . discard args +5690 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5691 # check output +5692 # . flush(_test-output-buffered-file) +5693 # . . push args +5694 68/push _test-output-buffered-file/imm32 +5695 # . . call +5696 e8/call flush/disp32 +5697 # . . discard args +5698 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5699 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +5725 # . check-stream-equal(_test-output-stream, "68 20 00 # 68/push 0x20/imm16", msg) +5726 # . . push args +5727 68/push "F - test-convert-instruction-handles-imm16-operand"/imm32 +5728 68/push "68 20 00 # 68/push 0x20/imm16"/imm32 +5729 68/push _test-output-stream/imm32 +5730 # . . call +5731 e8/call check-stream-equal/disp32 +5732 # . . discard args +5733 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +5734 # . epilog +5735 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +5736 5d/pop-to-EBP +5737 c3/return +5738 +5739 test-convert-instruction-handles-imm8-operand: +5740 # expand /imm8 operand into 1 byte +5741 # we don't have one of these at the moment, so this expands to an invalid instruction +5742 # . prolog +5743 55/push-EBP +5744 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +5745 # setup +5746 # . clear-stream(_test-input-stream) +5747 # . . push args +5748 68/push _test-input-stream/imm32 +5749 # . . call +5750 e8/call clear-stream/disp32 +5751 # . . discard args +5752 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5753 # . clear-stream(_test-output-stream) +5754 # . . push args +5755 68/push _test-output-stream/imm32 +5756 # . . call +5757 e8/call clear-stream/disp32 +5758 # . . discard args +5759 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5760 # . clear-stream(_test-output-buffered-file+4) 5761 # . . push args -5762 68/push "eb/jump 20/disp8"/imm32 -5763 68/push _test-input-stream/imm32 -5764 # . . call -5765 e8/call write/disp32 -5766 # . . discard args -5767 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5768 # convert-instruction(_test-input-stream, _test-output-buffered-file) -5769 # . . push args -5770 68/push _test-output-buffered-file/imm32 -5771 68/push _test-input-stream/imm32 -5772 # . . call -5773 e8/call convert-instruction/disp32 -5774 # . . discard args -5775 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5776 # check output -5777 # . flush(_test-output-buffered-file) -5778 # . . push args -5779 68/push _test-output-buffered-file/imm32 -5780 # . . call -5781 e8/call flush/disp32 -5782 # . . discard args -5783 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5784 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -5818 # . check-stream-equal(_test-output-stream, "eb 20 # eb/jump 20/disp8", msg) -5819 # . . push args -5820 68/push "F - test-convert-instruction-handles-disp8-operand"/imm32 -5821 68/push "eb 20 # eb/jump 20/disp8"/imm32 -5822 68/push _test-output-stream/imm32 -5823 # . . call -5824 e8/call check-stream-equal/disp32 -5825 # . . discard args -5826 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -5827 # . epilog -5828 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -5829 5d/pop-to-EBP -5830 c3/return -5831 -5832 test-convert-instruction-handles-disp8-name: -5833 # pass /disp8 name directly through -5834 # . prolog -5835 55/push-EBP -5836 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -5837 # setup -5838 # . clear-stream(_test-input-stream) -5839 # . . push args -5840 68/push _test-input-stream/imm32 -5841 # . . call -5842 e8/call clear-stream/disp32 -5843 # . . discard args -5844 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5845 # . clear-stream(_test-output-stream) -5846 # . . push args -5847 68/push _test-output-stream/imm32 -5848 # . . call -5849 e8/call clear-stream/disp32 -5850 # . . discard args -5851 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5852 # . clear-stream(_test-output-buffered-file+4) -5853 # . . push args -5854 b8/copy-to-EAX _test-output-buffered-file/imm32 -5855 05/add-to-EAX 4/imm32 -5856 50/push-EAX -5857 # . . call -5858 e8/call clear-stream/disp32 -5859 # . . discard args -5860 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5861 # initialize input -5862 # . write(_test-input-stream, "eb/jump xyz/disp8") -5863 # . . push args -5864 68/push "eb/jump xyz/disp8"/imm32 -5865 68/push _test-input-stream/imm32 -5866 # . . call -5867 e8/call write/disp32 -5868 # . . discard args -5869 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5870 # convert-instruction(_test-input-stream, _test-output-buffered-file) -5871 # . . push args -5872 68/push _test-output-buffered-file/imm32 -5873 68/push _test-input-stream/imm32 -5874 # . . call -5875 e8/call convert-instruction/disp32 -5876 # . . discard args -5877 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5878 # check output -5879 # . flush(_test-output-buffered-file) -5880 # . . push args -5881 68/push _test-output-buffered-file/imm32 -5882 # . . call -5883 e8/call flush/disp32 -5884 # . . discard args -5885 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5886 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -5920 # . check-stream-equal(_test-output-stream, "eb xyz/disp8 # eb/jump xyz/disp8", msg) -5921 # . . push args -5922 68/push "F - test-convert-instruction-handles-disp8-name"/imm32 -5923 68/push "eb xyz/disp8 # eb/jump xyz/disp8"/imm32 -5924 68/push _test-output-stream/imm32 -5925 # . . call -5926 e8/call check-stream-equal/disp32 -5927 # . . discard args -5928 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -5929 # . epilog -5930 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -5931 5d/pop-to-EBP -5932 c3/return -5933 -5934 test-convert-instruction-handles-imm32-operand: -5935 # expand /imm32 operand into 4 bytes -5936 # . prolog -5937 55/push-EBP -5938 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -5939 # setup -5940 # . clear-stream(_test-input-stream) -5941 # . . push args -5942 68/push _test-input-stream/imm32 -5943 # . . call -5944 e8/call clear-stream/disp32 -5945 # . . discard args -5946 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5947 # . clear-stream(_test-output-stream) -5948 # . . push args -5949 68/push _test-output-stream/imm32 -5950 # . . call -5951 e8/call clear-stream/disp32 -5952 # . . discard args -5953 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5954 # . clear-stream(_test-output-buffered-file+4) -5955 # . . push args -5956 b8/copy-to-EAX _test-output-buffered-file/imm32 -5957 05/add-to-EAX 4/imm32 -5958 50/push-EAX -5959 # . . call -5960 e8/call clear-stream/disp32 -5961 # . . discard args -5962 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5963 # initialize input -5964 # . write(_test-input-stream, "68/push 0x20/imm32") -5965 # . . push args -5966 68/push "68/push 0x20/imm32"/imm32 -5967 68/push _test-input-stream/imm32 -5968 # . . call -5969 e8/call write/disp32 -5970 # . . discard args -5971 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5972 # convert-instruction(_test-input-stream, _test-output-buffered-file) -5973 # . . push args -5974 68/push _test-output-buffered-file/imm32 -5975 68/push _test-input-stream/imm32 -5976 # . . call -5977 e8/call convert-instruction/disp32 -5978 # . . discard args -5979 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -5980 # check output -5981 # . flush(_test-output-buffered-file) -5982 # . . push args -5983 68/push _test-output-buffered-file/imm32 -5984 # . . call -5985 e8/call flush/disp32 -5986 # . . discard args -5987 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -5988 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -6022 # . check-stream-equal(_test-output-stream, "68 20 00 00 00 # 68/push 0x20/imm32", msg) -6023 # . . push args -6024 68/push "F - test-convert-instruction-handles-imm32-operand"/imm32 -6025 68/push "68 20 00 00 00 # 68/push 0x20/imm32"/imm32 -6026 68/push _test-output-stream/imm32 -6027 # . . call -6028 e8/call check-stream-equal/disp32 -6029 # . . discard args -6030 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6031 # . epilog -6032 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -6033 5d/pop-to-EBP -6034 c3/return -6035 -6036 test-convert-instruction-handles-imm16-operand: -6037 # expand /imm16 operand into 2 bytes -6038 # we don't have one of these at the moment, so this expands to an invalid instruction +5762 b8/copy-to-EAX _test-output-buffered-file/imm32 +5763 05/add-to-EAX 4/imm32 +5764 50/push-EAX +5765 # . . call +5766 e8/call clear-stream/disp32 +5767 # . . discard args +5768 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5769 # initialize input +5770 # . write(_test-input-stream, "68/push 0x20/imm8") +5771 # . . push args +5772 68/push "68/push 0x20/imm8"/imm32 +5773 68/push _test-input-stream/imm32 +5774 # . . call +5775 e8/call write/disp32 +5776 # . . discard args +5777 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5778 # convert-instruction(_test-input-stream, _test-output-buffered-file) +5779 # . . push args +5780 68/push _test-output-buffered-file/imm32 +5781 68/push _test-input-stream/imm32 +5782 # . . call +5783 e8/call convert-instruction/disp32 +5784 # . . discard args +5785 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5786 # check output +5787 # . flush(_test-output-buffered-file) +5788 # . . push args +5789 68/push _test-output-buffered-file/imm32 +5790 # . . call +5791 e8/call flush/disp32 +5792 # . . discard args +5793 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5794 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +5820 # . check-stream-equal(_test-output-stream, "68 20 # 68/push 0x20/imm8", msg) +5821 # . . push args +5822 68/push "F - test-convert-instruction-handles-imm8-operand"/imm32 +5823 68/push "68 20 # 68/push 0x20/imm8"/imm32 +5824 68/push _test-output-stream/imm32 +5825 # . . call +5826 e8/call check-stream-equal/disp32 +5827 # . . discard args +5828 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +5829 # . epilog +5830 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +5831 5d/pop-to-EBP +5832 c3/return +5833 +5834 # (re)compute the bounds of the next word in the line +5835 # return empty string on reaching end of file +5836 next-word: # line : (address stream byte), out : (address slice) +5837 # . prolog +5838 55/push-EBP +5839 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +5840 # . save registers +5841 50/push-EAX +5842 51/push-ECX +5843 56/push-ESI +5844 57/push-EDI +5845 # ESI = line +5846 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +5847 # EDI = out +5848 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI +5849 # skip-chars-matching(line, ' ') +5850 # . . push args +5851 68/push 0x20/imm32/space +5852 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +5853 # . . call +5854 e8/call skip-chars-matching/disp32 +5855 # . . discard args +5856 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5857 $next-word:check0: +5858 # if (line->read >= line->write) clear out and return +5859 # . EAX = line->read +5860 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy *(ESI+4) to EAX +5861 # . if (EAX < line->write) goto next check +5862 3b/compare 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # compare EAX with *ESI +5863 7c/jump-if-lesser $next-word:check-for-comment/disp8 +5864 # . return out = {0, 0} +5865 c7 0/subop/copy 0/mod/direct 7/rm32/EDI . . . . . 0/imm32 # copy to *EDI +5866 c7 0/subop/copy 1/mod/*+disp8 7/rm32/EDI . . . . 4/disp8 0/imm32 # copy to *(EDI+4) +5867 eb/jump $next-word:end/disp8 +5868 $next-word:check-for-comment: +5869 # out->start = &line->data[line->read] +5870 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX +5871 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 1/index/ECX . 0/r32/EAX 0xc/disp8 . # copy ESI+ECX+12 to EAX +5872 89/copy 0/mod/indirect 7/rm32/EDI . . . 0/r32/EAX . . # copy EAX to *EDI +5873 # if (line->data[line->read] == '#') out->end = &line->data[line->write]), skip rest of stream and return +5874 # . EAX = line->data[line->read] +5875 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +5876 8a/copy-byte 1/mod/*+disp8 4/rm32/sib 6/base/ESI 1/index/ECX . 0/r32/AL 0xc/disp8 . # copy byte at *(ESI+ECX+12) to AL +5877 # . compare +5878 3d/compare-EAX-and 0x23/imm32/pound +5879 75/jump-if-not-equal $next-word:regular-word/disp8 +5880 $next-word:comment: +5881 # . out->end = &line->data[line->write] +5882 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX +5883 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 0/index/EAX . 0/r32/EAX 0xc/disp8 . # copy ESI+EAX+12 to EAX +5884 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDI+4) +5885 # . line->read = line->write +5886 89/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(ESI+4) +5887 # . return +5888 eb/jump $next-word:end/disp8 +5889 $next-word:regular-word: +5890 # otherwise skip-chars-not-matching-whitespace(line) # including trailing newline +5891 # . . push args +5892 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +5893 # . . call +5894 e8/call skip-chars-not-matching-whitespace/disp32 +5895 # . . discard args +5896 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5897 # out->end = &line->data[line->read] +5898 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX +5899 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 1/index/ECX . 0/r32/EAX 0xc/disp8 . # copy ESI+ECX+12 to EAX +5900 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDI+4) +5901 $next-word:end: +5902 # . restore registers +5903 5f/pop-to-EDI +5904 5e/pop-to-ESI +5905 59/pop-to-ECX +5906 58/pop-to-EAX +5907 # . epilog +5908 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +5909 5d/pop-to-EBP +5910 c3/return +5911 +5912 test-next-word: +5913 # . prolog +5914 55/push-EBP +5915 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +5916 # setup +5917 # . clear-stream(_test-stream) +5918 # . . push args +5919 68/push _test-stream/imm32 +5920 # . . call +5921 e8/call clear-stream/disp32 +5922 # . . discard args +5923 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5924 # var slice/ECX = {0, 0} +5925 68/push 0/imm32/end +5926 68/push 0/imm32/start +5927 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +5928 # write(_test-stream, " ab") +5929 # . . push args +5930 68/push " ab"/imm32 +5931 68/push _test-stream/imm32 +5932 # . . call +5933 e8/call write/disp32 +5934 # . . discard args +5935 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5936 # next-word(_test-stream, slice) +5937 # . . push args +5938 51/push-ECX +5939 68/push _test-stream/imm32 +5940 # . . call +5941 e8/call next-word/disp32 +5942 # . . discard args +5943 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5944 # check-ints-equal(slice->start - _test-stream->data, 2, msg) +5945 # . check-ints-equal(slice->start - _test-stream, 14, msg) +5946 # . . push args +5947 68/push "F - test-next-word: start"/imm32 +5948 68/push 0xe/imm32 +5949 # . . push slice->start - _test-stream +5950 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX +5951 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-stream/imm32 # subtract from EAX +5952 50/push-EAX +5953 # . . call +5954 e8/call check-ints-equal/disp32 +5955 # . . discard args +5956 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +5957 # check-ints-equal(slice->end - _test-stream->data, 4, msg) +5958 # . check-ints-equal(slice->end - _test-stream, 16, msg) +5959 # . . push args +5960 68/push "F - test-next-word: end"/imm32 +5961 68/push 0x10/imm32 +5962 # . . push slice->end - _test-stream +5963 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +5964 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-stream/imm32 # subtract from EAX +5965 50/push-EAX +5966 # . . call +5967 e8/call check-ints-equal/disp32 +5968 # . . discard args +5969 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +5970 # . epilog +5971 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +5972 5d/pop-to-EBP +5973 c3/return +5974 +5975 test-next-word-returns-whole-comment: +5976 # . prolog +5977 55/push-EBP +5978 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +5979 # setup +5980 # . clear-stream(_test-stream) +5981 # . . push args +5982 68/push _test-stream/imm32 +5983 # . . call +5984 e8/call clear-stream/disp32 +5985 # . . discard args +5986 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +5987 # var slice/ECX = {0, 0} +5988 68/push 0/imm32/end +5989 68/push 0/imm32/start +5990 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +5991 # write(_test-stream, " # a") +5992 # . . push args +5993 68/push " # a"/imm32 +5994 68/push _test-stream/imm32 +5995 # . . call +5996 e8/call write/disp32 +5997 # . . discard args +5998 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +5999 # next-word(_test-stream, slice) +6000 # . . push args +6001 51/push-ECX +6002 68/push _test-stream/imm32 +6003 # . . call +6004 e8/call next-word/disp32 +6005 # . . discard args +6006 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +6007 # check-ints-equal(slice->start - _test-stream->data, 2, msg) +6008 # . check-ints-equal(slice->start - _test-stream, 14, msg) +6009 # . . push args +6010 68/push "F - test-next-word-returns-whole-comment: start"/imm32 +6011 68/push 0xe/imm32 +6012 # . . push slice->start - _test-stream +6013 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX +6014 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-stream/imm32 # subtract from EAX +6015 50/push-EAX +6016 # . . call +6017 e8/call check-ints-equal/disp32 +6018 # . . discard args +6019 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6020 # check-ints-equal(slice->end - _test-stream->data, 5, msg) +6021 # . check-ints-equal(slice->end - _test-stream, 17, msg) +6022 # . . push args +6023 68/push "F - test-next-word-returns-whole-comment: end"/imm32 +6024 68/push 0x11/imm32 +6025 # . . push slice->end - _test-stream +6026 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +6027 81 5/subop/subtract 3/mod/direct 0/rm32/EAX . . . . . _test-stream/imm32 # subtract from EAX +6028 50/push-EAX +6029 # . . call +6030 e8/call check-ints-equal/disp32 +6031 # . . discard args +6032 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6033 # . epilog +6034 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6035 5d/pop-to-EBP +6036 c3/return +6037 +6038 test-next-word-returns-empty-string-on-eof: 6039 # . prolog 6040 55/push-EBP 6041 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 6042 # setup -6043 # . clear-stream(_test-input-stream) +6043 # . clear-stream(_test-stream) 6044 # . . push args -6045 68/push _test-input-stream/imm32 +6045 68/push _test-stream/imm32 6046 # . . call 6047 e8/call clear-stream/disp32 6048 # . . discard args 6049 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6050 # . clear-stream(_test-output-stream) -6051 # . . push args -6052 68/push _test-output-stream/imm32 -6053 # . . call -6054 e8/call clear-stream/disp32 -6055 # . . discard args -6056 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6057 # . clear-stream(_test-output-buffered-file+4) -6058 # . . push args -6059 b8/copy-to-EAX _test-output-buffered-file/imm32 -6060 05/add-to-EAX 4/imm32 -6061 50/push-EAX -6062 # . . call -6063 e8/call clear-stream/disp32 -6064 # . . discard args -6065 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6066 # initialize input -6067 # . write(_test-input-stream, "68/push 0x20/imm16") -6068 # . . push args -6069 68/push "68/push 0x20/imm16"/imm32 # not a valid instruction -6070 68/push _test-input-stream/imm32 +6050 # var slice/ECX = {0, 0} +6051 68/push 0/imm32/end +6052 68/push 0/imm32/start +6053 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +6054 # write nothing to _test-stream +6055 # next-word(_test-stream, slice) +6056 # . . push args +6057 51/push-ECX +6058 68/push _test-stream/imm32 +6059 # . . call +6060 e8/call next-word/disp32 +6061 # . . discard args +6062 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +6063 # check-ints-equal(slice->end - slice->start, 0, msg) +6064 # . . push args +6065 68/push "F - test-next-word-returns-empty-string-on-eof"/imm32 +6066 68/push 0/imm32 +6067 # . . push slice->end - slice->start +6068 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX +6069 2b/subtract 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # subtract *ECX from EAX +6070 50/push-EAX 6071 # . . call -6072 e8/call write/disp32 +6072 e8/call check-ints-equal/disp32 6073 # . . discard args -6074 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -6075 # convert-instruction(_test-input-stream, _test-output-buffered-file) -6076 # . . push args -6077 68/push _test-output-buffered-file/imm32 -6078 68/push _test-input-stream/imm32 -6079 # . . call -6080 e8/call convert-instruction/disp32 -6081 # . . discard args -6082 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -6083 # check output -6084 # . flush(_test-output-buffered-file) -6085 # . . push args -6086 68/push _test-output-buffered-file/imm32 -6087 # . . call -6088 e8/call flush/disp32 -6089 # . . discard args -6090 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6091 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -6125 # . check-stream-equal(_test-output-stream, "68 20 00 # 68/push 0x20/imm16", msg) -6126 # . . push args -6127 68/push "F - test-convert-instruction-handles-imm16-operand"/imm32 -6128 68/push "68 20 00 # 68/push 0x20/imm16"/imm32 -6129 68/push _test-output-stream/imm32 -6130 # . . call -6131 e8/call check-stream-equal/disp32 -6132 # . . discard args -6133 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6134 # . epilog -6135 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -6136 5d/pop-to-EBP -6137 c3/return -6138 -6139 test-convert-instruction-handles-imm8-operand: -6140 # expand /imm8 operand into 1 byte -6141 # we don't have one of these at the moment, so this expands to an invalid instruction -6142 # . prolog -6143 55/push-EBP -6144 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -6145 # setup -6146 # . clear-stream(_test-input-stream) -6147 # . . push args -6148 68/push _test-input-stream/imm32 -6149 # . . call -6150 e8/call clear-stream/disp32 -6151 # . . discard args -6152 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6153 # . clear-stream(_test-output-stream) -6154 # . . push args -6155 68/push _test-output-stream/imm32 -6156 # . . call -6157 e8/call clear-stream/disp32 -6158 # . . discard args -6159 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6160 # . clear-stream(_test-output-buffered-file+4) -6161 # . . push args -6162 b8/copy-to-EAX _test-output-buffered-file/imm32 -6163 05/add-to-EAX 4/imm32 -6164 50/push-EAX -6165 # . . call -6166 e8/call clear-stream/disp32 -6167 # . . discard args -6168 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6169 # initialize input -6170 # . write(_test-input-stream, "68/push 0x20/imm8") -6171 # . . push args -6172 68/push "68/push 0x20/imm8"/imm32 -6173 68/push _test-input-stream/imm32 -6174 # . . call -6175 e8/call write/disp32 -6176 # . . discard args -6177 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -6178 # convert-instruction(_test-input-stream, _test-output-buffered-file) -6179 # . . push args -6180 68/push _test-output-buffered-file/imm32 -6181 68/push _test-input-stream/imm32 -6182 # . . call -6183 e8/call convert-instruction/disp32 -6184 # . . discard args -6185 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -6186 # check output -6187 # . flush(_test-output-buffered-file) -6188 # . . push args -6189 68/push _test-output-buffered-file/imm32 +6074 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6075 # . epilog +6076 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6077 5d/pop-to-EBP +6078 c3/return +6079 +6080 has-metadata?: # word : (address slice), s : (address string) -> EAX : boolean +6081 # pseudocode: +6082 # var twig : &slice = next-token-from-slice(word->start, word->end, '/') # skip name +6083 # curr = twig->end +6084 # while true +6085 # twig = next-token-from-slice(curr, word->end, '/') +6086 # if (twig.empty()) break +6087 # if (slice-equal?(twig, s)) return true +6088 # curr = twig->end +6089 # return false +6090 # . prolog +6091 55/push-EBP +6092 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +6093 # . save registers +6094 51/push-ECX +6095 52/push-EDX +6096 56/push-ESI +6097 57/push-EDI +6098 # ESI = word +6099 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +6100 # EDX = word->end +6101 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 2/r32/EDX 4/disp8 . # copy *(ESI+4) to EDX +6102 # var twig/EDI : (address slice) = {0, 0} +6103 68/push 0/imm32/end +6104 68/push 0/imm32/start +6105 89/copy 3/mod/direct 7/rm32/EDI . . . 4/r32/ESP . . # copy ESP to EDI +6106 # next-token-from-slice(word->start, word->end, '/', twig) +6107 # . . push args +6108 57/push-EDI +6109 68/push 0x2f/imm32/slash +6110 52/push-EDX +6111 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI +6112 # . . call +6113 e8/call next-token-from-slice/disp32 +6114 # . . discard args +6115 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +6116 # curr/ECX = twig->end +6117 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 1/r32/ECX 4/disp8 . # copy *(EDI+4) to ECX +6118 $has-metadata?:loop: +6119 # next-token-from-slice(curr, word->end, '/', twig) +6120 # . . push args +6121 57/push-EDI +6122 68/push 0x2f/imm32/slash +6123 52/push-EDX +6124 51/push-ECX +6125 # . . call +6126 e8/call next-token-from-slice/disp32 +6127 # . . discard args +6128 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +6129 # if (slice-empty?(twig)) return false +6130 # . EAX = slice-empty?(twig) +6131 # . . push args +6132 57/push-EDI +6133 # . . call +6134 e8/call slice-empty?/disp32 +6135 # . . discard args +6136 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6137 # . if (EAX != 0) return false +6138 3d/compare-EAX-and 0/imm32 +6139 75/jump-if-not-equal $has-metadata?:false/disp8 +6140 # if (slice-equal?(twig, s)) return true +6141 # . EAX = slice-equal?(twig, s) +6142 # . . push args +6143 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) +6144 57/push-EDI +6145 # . . call +6146 e8/call slice-equal?/disp32 +6147 # . . discard args +6148 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +6149 # . if (EAX != 0) return true +6150 3d/compare-EAX-and 0/imm32 +6151 75/jump-if-not-equal $has-metadata?:true/disp8 +6152 # curr = twig->end +6153 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 1/r32/ECX 4/disp8 . # copy *(EDI+4) to ECX +6154 eb/jump $has-metadata?:loop/disp8 +6155 $has-metadata?:true: +6156 b8/copy-to-EAX 1/imm32/true +6157 eb/jump $has-metadata?:end/disp8 +6158 $has-metadata?:false: +6159 b8/copy-to-EAX 0/imm32/false +6160 $has-metadata?:end: +6161 # . reclaim locals +6162 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +6163 # . restore registers +6164 5f/pop-to-EDI +6165 5e/pop-to-ESI +6166 5a/pop-to-EDX +6167 59/pop-to-ECX +6168 # . epilog +6169 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6170 5d/pop-to-EBP +6171 c3/return +6172 +6173 test-has-metadata-true: +6174 # . prolog +6175 55/push-EBP +6176 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +6177 # (EAX..ECX) = "ab/c" +6178 b8/copy-to-EAX "ab/c"/imm32 +6179 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +6180 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX +6181 05/add-to-EAX 4/imm32 +6182 # var in/ESI : (address slice) = {EAX, ECX} +6183 51/push-ECX +6184 50/push-EAX +6185 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI +6186 # EAX = has-metadata?(ESI, "c") +6187 # . . push args +6188 68/push "c"/imm32 +6189 56/push-ESI 6190 # . . call -6191 e8/call flush/disp32 +6191 e8/call has-metadata?/disp32 6192 # . . discard args -6193 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6194 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -6228 # . check-stream-equal(_test-output-stream, "68 20 # 68/push 0x20/imm8", msg) -6229 # . . push args -6230 68/push "F - test-convert-instruction-handles-imm8-operand"/imm32 -6231 68/push "68 20 # 68/push 0x20/imm8"/imm32 -6232 68/push _test-output-stream/imm32 -6233 # . . call -6234 e8/call check-stream-equal/disp32 -6235 # . . discard args -6236 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6237 # . epilog -6238 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -6239 5d/pop-to-EBP -6240 c3/return -6241 -6242 has-metadata?: # word : (address slice), s : (address string) -> EAX : boolean -6243 # pseudocode: -6244 # var twig : &slice = next-token-from-slice(word->start, word->end, '/') # skip name -6245 # curr = twig->end -6246 # while true -6247 # twig = next-token-from-slice(curr, word->end, '/') -6248 # if (twig.empty()) break -6249 # if (slice-equal?(twig, s)) return true -6250 # curr = twig->end -6251 # return false -6252 # . prolog -6253 55/push-EBP -6254 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -6255 # . save registers -6256 51/push-ECX -6257 52/push-EDX -6258 56/push-ESI -6259 57/push-EDI -6260 # ESI = word -6261 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI -6262 # EDX = word->end -6263 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 2/r32/EDX 4/disp8 . # copy *(ESI+4) to EDX -6264 # var twig/EDI : (address slice) = {0, 0} -6265 68/push 0/imm32/end -6266 68/push 0/imm32/start -6267 89/copy 3/mod/direct 7/rm32/EDI . . . 4/r32/ESP . . # copy ESP to EDI -6268 # next-token-from-slice(word->start, word->end, '/', twig) -6269 # . . push args -6270 57/push-EDI -6271 68/push 0x2f/imm32/slash -6272 52/push-EDX -6273 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI -6274 # . . call -6275 e8/call next-token-from-slice/disp32 -6276 # . . discard args -6277 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -6278 # curr/ECX = twig->end -6279 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 1/r32/ECX 4/disp8 . # copy *(EDI+4) to ECX -6280 $has-metadata?:loop: -6281 # next-token-from-slice(curr, word->end, '/', twig) -6282 # . . push args -6283 57/push-EDI -6284 68/push 0x2f/imm32/slash -6285 52/push-EDX -6286 51/push-ECX -6287 # . . call -6288 e8/call next-token-from-slice/disp32 -6289 # . . discard args -6290 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -6291 # if (slice-empty?(twig)) return false -6292 # . EAX = slice-empty?(twig) -6293 # . . push args -6294 57/push-EDI +6193 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +6194 # check-ints-equal(EAX, 1, msg) +6195 # . . push args +6196 68/push "F - test-has-metadata-true"/imm32 +6197 68/push 1/imm32/true +6198 50/push-EAX +6199 # . . call +6200 e8/call check-ints-equal/disp32 +6201 # . . discard args +6202 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6203 # . epilog +6204 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6205 5d/pop-to-EBP +6206 c3/return +6207 +6208 test-has-metadata-false: +6209 # . prolog +6210 55/push-EBP +6211 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +6212 # (EAX..ECX) = "ab/c" +6213 b8/copy-to-EAX "ab/c"/imm32 +6214 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +6215 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX +6216 05/add-to-EAX 4/imm32 +6217 # var in/ESI : (address slice) = {EAX, ECX} +6218 51/push-ECX +6219 50/push-EAX +6220 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI +6221 # EAX = has-metadata?(ESI, "c") +6222 # . . push args +6223 68/push "d"/imm32 +6224 56/push-ESI +6225 # . . call +6226 e8/call has-metadata?/disp32 +6227 # . . discard args +6228 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +6229 # check-ints-equal(EAX, 0, msg) +6230 # . . push args +6231 68/push "F - test-has-metadata-false"/imm32 +6232 68/push 0/imm32/false +6233 50/push-EAX +6234 # . . call +6235 e8/call check-ints-equal/disp32 +6236 # . . discard args +6237 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6238 # . epilog +6239 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6240 5d/pop-to-EBP +6241 c3/return +6242 +6243 test-has-metadata-ignore-name: +6244 # . prolog +6245 55/push-EBP +6246 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +6247 # (EAX..ECX) = "a/b" +6248 b8/copy-to-EAX "a/b"/imm32 +6249 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +6250 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX +6251 05/add-to-EAX 4/imm32 +6252 # var in/ESI : (address slice) = {EAX, ECX} +6253 51/push-ECX +6254 50/push-EAX +6255 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI +6256 # EAX = has-metadata?(ESI, "a") +6257 # . . push args +6258 68/push "a"/imm32 +6259 56/push-ESI +6260 # . . call +6261 e8/call has-metadata?/disp32 +6262 # . . discard args +6263 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +6264 # check-ints-equal(EAX, 0, msg) +6265 # . . push args +6266 68/push "F - test-has-metadata-ignore-name"/imm32 +6267 68/push 0/imm32/false +6268 50/push-EAX +6269 # . . call +6270 e8/call check-ints-equal/disp32 +6271 # . . discard args +6272 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6273 # . epilog +6274 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6275 5d/pop-to-EBP +6276 c3/return +6277 +6278 test-has-metadata-multiple-true: +6279 # . prolog +6280 55/push-EBP +6281 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +6282 # (EAX..ECX) = "a/b/c" +6283 b8/copy-to-EAX "a/b/c"/imm32 +6284 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +6285 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX +6286 05/add-to-EAX 4/imm32 +6287 # var in/ESI : (address slice) = {EAX, ECX} +6288 51/push-ECX +6289 50/push-EAX +6290 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI +6291 # EAX = has-metadata?(ESI, "c") +6292 # . . push args +6293 68/push "c"/imm32 +6294 56/push-ESI 6295 # . . call -6296 e8/call slice-empty?/disp32 +6296 e8/call has-metadata?/disp32 6297 # . . discard args -6298 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6299 # . if (EAX != 0) return false -6300 3d/compare-EAX-and 0/imm32 -6301 75/jump-if-not-equal $has-metadata?:false/disp8 -6302 # if (slice-equal?(twig, s)) return true -6303 # . EAX = slice-equal?(twig, s) -6304 # . . push args -6305 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) -6306 57/push-EDI -6307 # . . call -6308 e8/call slice-equal?/disp32 -6309 # . . discard args -6310 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -6311 # . if (EAX != 0) return true -6312 3d/compare-EAX-and 0/imm32 -6313 75/jump-if-not-equal $has-metadata?:true/disp8 -6314 # curr = twig->end -6315 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 1/r32/ECX 4/disp8 . # copy *(EDI+4) to ECX -6316 eb/jump $has-metadata?:loop/disp8 -6317 $has-metadata?:true: -6318 b8/copy-to-EAX 1/imm32/true -6319 eb/jump $has-metadata?:end/disp8 -6320 $has-metadata?:false: -6321 b8/copy-to-EAX 0/imm32/false -6322 $has-metadata?:end: -6323 # . reclaim locals -6324 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -6325 # . restore registers -6326 5f/pop-to-EDI -6327 5e/pop-to-ESI -6328 5a/pop-to-EDX -6329 59/pop-to-ECX -6330 # . epilog -6331 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -6332 5d/pop-to-EBP -6333 c3/return -6334 -6335 test-has-metadata-true: -6336 # . prolog -6337 55/push-EBP -6338 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -6339 # (EAX..ECX) = "ab/c" -6340 b8/copy-to-EAX "ab/c"/imm32 -6341 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -6342 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX -6343 05/add-to-EAX 4/imm32 -6344 # var in/ESI : (address slice) = {EAX, ECX} -6345 51/push-ECX -6346 50/push-EAX -6347 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI -6348 # EAX = has-metadata?(ESI, "c") -6349 # . . push args -6350 68/push "c"/imm32 -6351 56/push-ESI -6352 # . . call -6353 e8/call has-metadata?/disp32 -6354 # . . discard args -6355 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -6356 # check-ints-equal(EAX, 1, msg) -6357 # . . push args -6358 68/push "F - test-has-metadata-true"/imm32 -6359 68/push 1/imm32/true -6360 50/push-EAX -6361 # . . call -6362 e8/call check-ints-equal/disp32 -6363 # . . discard args -6364 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6365 # . epilog -6366 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -6367 5d/pop-to-EBP -6368 c3/return -6369 -6370 test-has-metadata-false: -6371 # . prolog -6372 55/push-EBP -6373 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -6374 # (EAX..ECX) = "ab/c" -6375 b8/copy-to-EAX "ab/c"/imm32 -6376 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -6377 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX -6378 05/add-to-EAX 4/imm32 -6379 # var in/ESI : (address slice) = {EAX, ECX} -6380 51/push-ECX -6381 50/push-EAX -6382 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI -6383 # EAX = has-metadata?(ESI, "c") -6384 # . . push args -6385 68/push "d"/imm32 -6386 56/push-ESI -6387 # . . call -6388 e8/call has-metadata?/disp32 -6389 # . . discard args -6390 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -6391 # check-ints-equal(EAX, 0, msg) -6392 # . . push args -6393 68/push "F - test-has-metadata-false"/imm32 -6394 68/push 0/imm32/false -6395 50/push-EAX -6396 # . . call -6397 e8/call check-ints-equal/disp32 -6398 # . . discard args -6399 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6400 # . epilog -6401 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -6402 5d/pop-to-EBP -6403 c3/return -6404 -6405 test-has-metadata-ignore-name: -6406 # . prolog -6407 55/push-EBP -6408 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -6409 # (EAX..ECX) = "a/b" -6410 b8/copy-to-EAX "a/b"/imm32 -6411 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -6412 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX -6413 05/add-to-EAX 4/imm32 -6414 # var in/ESI : (address slice) = {EAX, ECX} -6415 51/push-ECX -6416 50/push-EAX -6417 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI -6418 # EAX = has-metadata?(ESI, "a") -6419 # . . push args -6420 68/push "a"/imm32 -6421 56/push-ESI -6422 # . . call -6423 e8/call has-metadata?/disp32 -6424 # . . discard args -6425 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -6426 # check-ints-equal(EAX, 0, msg) -6427 # . . push args -6428 68/push "F - test-has-metadata-ignore-name"/imm32 -6429 68/push 0/imm32/false -6430 50/push-EAX -6431 # . . call -6432 e8/call check-ints-equal/disp32 -6433 # . . discard args -6434 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6298 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +6299 # check-ints-equal(EAX, 1, msg) +6300 # . . push args +6301 68/push "F - test-has-metadata-multiple-true"/imm32 +6302 68/push 1/imm32/true +6303 50/push-EAX +6304 # . . call +6305 e8/call check-ints-equal/disp32 +6306 # . . discard args +6307 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6308 # . epilog +6309 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6310 5d/pop-to-EBP +6311 c3/return +6312 +6313 test-has-metadata-multiple-false: +6314 # . prolog +6315 55/push-EBP +6316 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +6317 # (EAX..ECX) = "a/b/c" +6318 b8/copy-to-EAX "a/b/c"/imm32 +6319 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX +6320 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX +6321 05/add-to-EAX 4/imm32 +6322 # var in/ESI : (address slice) = {EAX, ECX} +6323 51/push-ECX +6324 50/push-EAX +6325 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI +6326 # EAX = has-metadata?(ESI, "d") +6327 # . . push args +6328 68/push "d"/imm32 +6329 56/push-ESI +6330 # . . call +6331 e8/call has-metadata?/disp32 +6332 # . . discard args +6333 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +6334 # check-ints-equal(EAX, 0, msg) +6335 # . . push args +6336 68/push "F - test-has-metadata-multiple-false"/imm32 +6337 68/push 0/imm32/false +6338 50/push-EAX +6339 # . . call +6340 e8/call check-ints-equal/disp32 +6341 # . . discard args +6342 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6343 # . epilog +6344 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6345 5d/pop-to-EBP +6346 c3/return +6347 +6348 # If datum of 'word' is not a valid name, it must be a hex int. Parse and print +6349 # it in 'width' bytes of hex, least significant first. +6350 # Otherwise just print the entire word including metadata. +6351 # Always print a trailing space. +6352 emit: # out : (address buffered-file), word : (address slice), width : int -> <void> +6353 # . prolog +6354 55/push-EBP +6355 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +6356 # . save registers +6357 50/push-EAX +6358 56/push-ESI +6359 57/push-EDI +6360 # ESI = word +6361 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI +6362 # var name/EDI : (address slice) = {0, 0} +6363 68/push 0/imm32/end +6364 68/push 0/imm32/start +6365 89/copy 3/mod/direct 7/rm32/EDI . . . 4/r32/ESP . . # copy ESP to EDI +6366 # datum = next-token-from-slice(word->start, word->end, '/') +6367 # . . push args +6368 57/push-EDI +6369 68/push 0x2f/imm32/slash +6370 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) +6371 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI +6372 # . . call +6373 e8/call next-token-from-slice/disp32 +6374 # . . discard args +6375 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +6376 # if (is-valid-name?(datum)) write-slice(out, word) and return +6377 # . EAX = is-valid-name?(name) +6378 # . . push args +6379 57/push-EDI +6380 # . . call +6381 e8/call is-valid-name?/disp32 +6382 # . . discard args +6383 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6384 # . if (EAX != 0) +6385 3d/compare-EAX-and 0/imm32 +6386 74/jump-if-equal $emit:hex-int/disp8 +6387 $emit:name: +6388 # . write-slice(out, word) +6389 # . . push args +6390 56/push-ESI +6391 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +6392 # . . call +6393 e8/call write-slice/disp32 +6394 # . . discard args +6395 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +6396 # . write-buffered(out, " ") +6397 # . . push args +6398 68/push " "/imm32 +6399 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +6400 # . . call +6401 e8/call write-buffered/disp32 +6402 # . . discard args +6403 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +6404 # . return +6405 eb/jump $emit:end/disp8 +6406 # otherwise emit-hex(out, parse-hex-int(datum), width) +6407 # (Weird shit can happen here if the datum of 'word' isn't either a valid +6408 # name or a hex number, but we're only going to be passing in real legal +6409 # programs. We just want to make sure that valid names aren't treated as +6410 # (valid) hex numbers.) +6411 $emit:hex-int: +6412 # . value/EAX = parse-hex-int(datum) +6413 # . . push args +6414 57/push-EDI +6415 # . . call +6416 e8/call parse-hex-int/disp32 +6417 # . . discard args +6418 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6419 # . emit-hex(out, value, width) +6420 # . . push args +6421 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) +6422 50/push-EAX +6423 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +6424 # . . call +6425 e8/call emit-hex/disp32 +6426 # . . discard args +6427 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6428 $emit:end: +6429 # . reclaim locals +6430 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +6431 # . restore registers +6432 5f/pop-to-EDI +6433 5e/pop-to-ESI +6434 58/pop-to-EAX 6435 # . epilog 6436 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP 6437 5d/pop-to-EBP 6438 c3/return 6439 -6440 test-has-metadata-multiple-true: +6440 test-emit-number: 6441 # . prolog 6442 55/push-EBP 6443 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -6444 # (EAX..ECX) = "a/b/c" -6445 b8/copy-to-EAX "a/b/c"/imm32 -6446 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -6447 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX -6448 05/add-to-EAX 4/imm32 -6449 # var in/ESI : (address slice) = {EAX, ECX} -6450 51/push-ECX -6451 50/push-EAX -6452 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI -6453 # EAX = has-metadata?(ESI, "c") -6454 # . . push args -6455 68/push "c"/imm32 -6456 56/push-ESI +6444 # setup +6445 # . clear-stream(_test-output-stream) +6446 # . . push args +6447 68/push _test-output-stream/imm32 +6448 # . . call +6449 e8/call clear-stream/disp32 +6450 # . . discard args +6451 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6452 # . clear-stream(_test-output-buffered-file+4) +6453 # . . push args +6454 b8/copy-to-EAX _test-output-buffered-file/imm32 +6455 05/add-to-EAX 4/imm32 +6456 50/push-EAX 6457 # . . call -6458 e8/call has-metadata?/disp32 +6458 e8/call clear-stream/disp32 6459 # . . discard args -6460 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -6461 # check-ints-equal(EAX, 1, msg) -6462 # . . push args -6463 68/push "F - test-has-metadata-multiple-true"/imm32 -6464 68/push 1/imm32/true -6465 50/push-EAX -6466 # . . call -6467 e8/call check-ints-equal/disp32 -6468 # . . discard args -6469 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6470 # . epilog -6471 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -6472 5d/pop-to-EBP -6473 c3/return -6474 -6475 test-has-metadata-multiple-false: -6476 # . prolog -6477 55/push-EBP -6478 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -6479 # (EAX..ECX) = "a/b/c" -6480 b8/copy-to-EAX "a/b/c"/imm32 -6481 8b/copy 0/mod/indirect 0/rm32/EAX . . . 1/r32/ECX . . # copy *EAX to ECX -6482 8d/copy-address 1/mod/*+disp8 4/rm32/sib 0/base/EAX 1/index/ECX . 1/r32/ECX 4/disp8 . # copy EAX+ECX+4 to ECX -6483 05/add-to-EAX 4/imm32 -6484 # var in/ESI : (address slice) = {EAX, ECX} -6485 51/push-ECX -6486 50/push-EAX -6487 89/copy 3/mod/direct 6/rm32/ESI . . . 4/r32/ESP . . # copy ESP to ESI -6488 # EAX = has-metadata?(ESI, "d") -6489 # . . push args -6490 68/push "d"/imm32 -6491 56/push-ESI -6492 # . . call -6493 e8/call has-metadata?/disp32 -6494 # . . discard args -6495 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -6496 # check-ints-equal(EAX, 0, msg) -6497 # . . push args -6498 68/push "F - test-has-metadata-multiple-false"/imm32 -6499 68/push 0/imm32/false -6500 50/push-EAX -6501 # . . call -6502 e8/call check-ints-equal/disp32 -6503 # . . discard args -6504 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6505 # . epilog -6506 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -6507 5d/pop-to-EBP -6508 c3/return -6509 -6510 # If datum of 'word' is not a valid name, it must be a hex int. Parse and print -6511 # it in 'width' bytes of hex, least significant first. -6512 # Otherwise just print the entire word including metadata. -6513 # Always print a trailing space. -6514 emit: # out : (address buffered-file), word : (address slice), width : int -> <void> -6515 # . prolog -6516 55/push-EBP -6517 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -6518 # . save registers -6519 50/push-EAX -6520 56/push-ESI -6521 57/push-EDI -6522 # ESI = word -6523 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI -6524 # var name/EDI : (address slice) = {0, 0} -6525 68/push 0/imm32/end -6526 68/push 0/imm32/start -6527 89/copy 3/mod/direct 7/rm32/EDI . . . 4/r32/ESP . . # copy ESP to EDI -6528 # datum = next-token-from-slice(word->start, word->end, '/') -6529 # . . push args -6530 57/push-EDI -6531 68/push 0x2f/imm32/slash -6532 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) -6533 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI -6534 # . . call -6535 e8/call next-token-from-slice/disp32 -6536 # . . discard args -6537 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -6538 # if (is-valid-name?(datum)) write-slice(out, word) and return -6539 # . EAX = is-valid-name?(name) -6540 # . . push args -6541 57/push-EDI +6460 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6461 # var slice/ECX = "30" +6462 68/push _test-slice-three-zero-end/imm32/end +6463 68/push _test-slice-three-zero/imm32/start +6464 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +6465 # emit(_test-output-buffered-file, slice, 1) +6466 # . . push args +6467 68/push 1/imm32 +6468 51/push-ECX +6469 68/push _test-output-buffered-file/imm32 +6470 # . . call +6471 e8/call emit/disp32 +6472 # . . discard args +6473 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6474 # flush(_test-output-buffered-file) +6475 # . . push args +6476 68/push _test-output-buffered-file/imm32 +6477 # . . call +6478 e8/call flush/disp32 +6479 # . . discard args +6480 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6481 # check-stream-equal(_test-output-stream, "30 ", msg) +6482 # . . push args +6483 68/push "F - test-emit-number/1"/imm32 +6484 68/push "30 "/imm32 +6485 68/push _test-output-stream/imm32 +6486 # . . call +6487 e8/call check-stream-equal/disp32 +6488 # . . discard args +6489 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6490 # . epilog +6491 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6492 5d/pop-to-EBP +6493 c3/return +6494 +6495 test-emit-negative-number: +6496 # test support for sign-extending negative numbers +6497 # . prolog +6498 55/push-EBP +6499 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +6500 # setup +6501 # . clear-stream(_test-output-stream) +6502 # . . push args +6503 68/push _test-output-stream/imm32 +6504 # . . call +6505 e8/call clear-stream/disp32 +6506 # . . discard args +6507 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6508 # . clear-stream(_test-output-buffered-file+4) +6509 # . . push args +6510 b8/copy-to-EAX _test-output-buffered-file/imm32 +6511 05/add-to-EAX 4/imm32 +6512 50/push-EAX +6513 # . . call +6514 e8/call clear-stream/disp32 +6515 # . . discard args +6516 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6517 # var slice/ECX = "-2" +6518 68/push _test-slice-negative-two-end/imm32/end +6519 68/push _test-slice-negative-two/imm32/start +6520 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +6521 # emit(_test-output-buffered-file, slice, 2) +6522 # . . push args +6523 68/push 2/imm32 +6524 51/push-ECX +6525 68/push _test-output-buffered-file/imm32 +6526 # . . call +6527 e8/call emit/disp32 +6528 # . . discard args +6529 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6530 # flush(_test-output-buffered-file) +6531 # . . push args +6532 68/push _test-output-buffered-file/imm32 +6533 # . . call +6534 e8/call flush/disp32 +6535 # . . discard args +6536 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6537 # check-stream-equal(_test-output-stream, "fe ff ", msg) +6538 # . . push args +6539 68/push "F - test-emit-number/1"/imm32 +6540 68/push "fe ff "/imm32 +6541 68/push _test-output-stream/imm32 6542 # . . call -6543 e8/call is-valid-name?/disp32 +6543 e8/call check-stream-equal/disp32 6544 # . . discard args -6545 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6546 # . if (EAX != 0) -6547 3d/compare-EAX-and 0/imm32 -6548 74/jump-if-equal $emit:hex-int/disp8 -6549 $emit:name: -6550 # . write-slice(out, word) -6551 # . . push args -6552 56/push-ESI -6553 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -6554 # . . call -6555 e8/call write-slice/disp32 -6556 # . . discard args -6557 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -6558 # . write-buffered(out, " ") -6559 # . . push args -6560 68/push " "/imm32 -6561 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -6562 # . . call -6563 e8/call write-buffered/disp32 -6564 # . . discard args -6565 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -6566 # . return -6567 eb/jump $emit:end/disp8 -6568 # otherwise emit-hex(out, parse-hex-int(datum), width) -6569 # (Weird shit can happen here if the datum of 'word' isn't either a valid -6570 # name or a hex number, but we're only going to be passing in real legal -6571 # programs. We just want to make sure that valid names aren't treated as -6572 # (valid) hex numbers.) -6573 $emit:hex-int: -6574 # . value/EAX = parse-hex-int(datum) -6575 # . . push args -6576 57/push-EDI -6577 # . . call -6578 e8/call parse-hex-int/disp32 -6579 # . . discard args -6580 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6581 # . emit-hex(out, value, width) -6582 # . . push args -6583 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) -6584 50/push-EAX -6585 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -6586 # . . call -6587 e8/call emit-hex/disp32 -6588 # . . discard args -6589 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6590 $emit:end: -6591 # . reclaim locals -6592 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -6593 # . restore registers -6594 5f/pop-to-EDI -6595 5e/pop-to-ESI -6596 58/pop-to-EAX -6597 # . epilog -6598 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -6599 5d/pop-to-EBP -6600 c3/return -6601 -6602 test-emit-number: -6603 # . prolog -6604 55/push-EBP -6605 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -6606 # setup -6607 # . clear-stream(_test-output-stream) -6608 # . . push args -6609 68/push _test-output-stream/imm32 -6610 # . . call -6611 e8/call clear-stream/disp32 -6612 # . . discard args -6613 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6614 # . clear-stream(_test-output-buffered-file+4) -6615 # . . push args -6616 b8/copy-to-EAX _test-output-buffered-file/imm32 -6617 05/add-to-EAX 4/imm32 -6618 50/push-EAX -6619 # . . call -6620 e8/call clear-stream/disp32 -6621 # . . discard args -6622 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6623 # var slice/ECX = "30" -6624 68/push _test-slice-three-zero-end/imm32/end -6625 68/push _test-slice-three-zero/imm32/start -6626 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -6627 # emit(_test-output-buffered-file, slice, 1) -6628 # . . push args -6629 68/push 1/imm32 -6630 51/push-ECX -6631 68/push _test-output-buffered-file/imm32 -6632 # . . call -6633 e8/call emit/disp32 -6634 # . . discard args -6635 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6636 # flush(_test-output-buffered-file) -6637 # . . push args -6638 68/push _test-output-buffered-file/imm32 -6639 # . . call -6640 e8/call flush/disp32 -6641 # . . discard args -6642 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6643 # check-stream-equal(_test-output-stream, "30 ", msg) -6644 # . . push args -6645 68/push "F - test-emit-number/1"/imm32 -6646 68/push "30 "/imm32 -6647 68/push _test-output-stream/imm32 -6648 # . . call -6649 e8/call check-stream-equal/disp32 -6650 # . . discard args -6651 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6652 # . epilog -6653 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -6654 5d/pop-to-EBP -6655 c3/return -6656 -6657 test-emit-negative-number: -6658 # test support for sign-extending negative numbers -6659 # . prolog -6660 55/push-EBP -6661 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -6662 # setup -6663 # . clear-stream(_test-output-stream) -6664 # . . push args -6665 68/push _test-output-stream/imm32 -6666 # . . call -6667 e8/call clear-stream/disp32 -6668 # . . discard args -6669 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6670 # . clear-stream(_test-output-buffered-file+4) -6671 # . . push args -6672 b8/copy-to-EAX _test-output-buffered-file/imm32 -6673 05/add-to-EAX 4/imm32 -6674 50/push-EAX -6675 # . . call -6676 e8/call clear-stream/disp32 -6677 # . . discard args -6678 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6679 # var slice/ECX = "-2" -6680 68/push _test-slice-negative-two-end/imm32/end -6681 68/push _test-slice-negative-two/imm32/start -6682 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -6683 # emit(_test-output-buffered-file, slice, 2) -6684 # . . push args -6685 68/push 2/imm32 -6686 51/push-ECX -6687 68/push _test-output-buffered-file/imm32 -6688 # . . call -6689 e8/call emit/disp32 -6690 # . . discard args -6691 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6692 # flush(_test-output-buffered-file) -6693 # . . push args -6694 68/push _test-output-buffered-file/imm32 -6695 # . . call -6696 e8/call flush/disp32 -6697 # . . discard args -6698 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6699 # check-stream-equal(_test-output-stream, "fe ff ", msg) -6700 # . . push args -6701 68/push "F - test-emit-number/1"/imm32 -6702 68/push "fe ff "/imm32 -6703 68/push _test-output-stream/imm32 -6704 # . . call -6705 e8/call check-stream-equal/disp32 -6706 # . . discard args -6707 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6708 # . epilog -6709 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -6710 5d/pop-to-EBP -6711 c3/return -6712 -6713 test-emit-number-with-metadata: -6714 # . prolog -6715 55/push-EBP -6716 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -6717 # setup -6718 # . clear-stream(_test-output-stream) -6719 # . . push args -6720 68/push _test-output-stream/imm32 -6721 # . . call -6722 e8/call clear-stream/disp32 -6723 # . . discard args -6724 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6725 # . clear-stream(_test-output-buffered-file+4) -6726 # . . push args -6727 b8/copy-to-EAX _test-output-buffered-file/imm32 -6728 05/add-to-EAX 4/imm32 -6729 50/push-EAX -6730 # . . call -6731 e8/call clear-stream/disp32 -6732 # . . discard args -6733 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6734 # var slice/ECX = "-2/foo" -6735 68/push _test-slice-negative-two-metadata-end/imm32/end -6736 68/push _test-slice-negative-two/imm32/start -6737 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -6738 # emit(_test-output-buffered-file, slice, 2) -6739 # . . push args -6740 68/push 2/imm32 -6741 51/push-ECX -6742 68/push _test-output-buffered-file/imm32 -6743 # . . call -6744 e8/call emit/disp32 -6745 # . . discard args -6746 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6747 # flush(_test-output-buffered-file) -6748 # . . push args -6749 68/push _test-output-buffered-file/imm32 -6750 # . . call -6751 e8/call flush/disp32 -6752 # . . discard args -6753 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6754 # the '/foo' will have no impact on the output -6755 # check-stream-equal(_test-output-stream, "fe ff ", msg) -6756 # . . push args -6757 68/push "F - test-emit-number-with-metadata"/imm32 -6758 68/push "fe ff "/imm32 -6759 68/push _test-output-stream/imm32 -6760 # . . call -6761 e8/call check-stream-equal/disp32 -6762 # . . discard args -6763 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6764 # . epilog -6765 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -6766 5d/pop-to-EBP -6767 c3/return -6768 -6769 test-emit-non-number: -6770 # . prolog -6771 55/push-EBP -6772 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -6773 # setup -6774 # . clear-stream(_test-output-stream) -6775 # . . push args -6776 68/push _test-output-stream/imm32 -6777 # . . call -6778 e8/call clear-stream/disp32 -6779 # . . discard args -6780 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6781 # . clear-stream(_test-output-buffered-file+4) -6782 # . . push args -6783 b8/copy-to-EAX _test-output-buffered-file/imm32 -6784 05/add-to-EAX 4/imm32 -6785 50/push-EAX -6786 # . . call -6787 e8/call clear-stream/disp32 -6788 # . . discard args -6789 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6790 # var slice/ECX = "xyz" -6791 68/push _test-slice-non-number-word-end/imm32/end -6792 68/push _test-slice-non-number-word/imm32/start -6793 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -6794 # emit(_test-output-buffered-file, slice, 2) -6795 # . . push args -6796 68/push 2/imm32 -6797 51/push-ECX -6798 68/push _test-output-buffered-file/imm32 -6799 # . . call -6800 e8/call emit/disp32 -6801 # . . discard args -6802 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6803 # flush(_test-output-buffered-file) -6804 # . . push args -6805 68/push _test-output-buffered-file/imm32 -6806 # . . call -6807 e8/call flush/disp32 -6808 # . . discard args -6809 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6810 # check-stream-equal(_test-output-stream, "xyz", msg) -6811 # . . push args -6812 68/push "F - test-emit-non-number"/imm32 -6813 68/push "xyz "/imm32 -6814 68/push _test-output-stream/imm32 -6815 # . . call -6816 e8/call check-stream-equal/disp32 -6817 # . . discard args -6818 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6819 # . epilog -6820 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -6821 5d/pop-to-EBP -6822 c3/return -6823 -6824 test-emit-non-number-with-metadata: -6825 # . prolog -6826 55/push-EBP -6827 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -6828 # setup -6829 # . clear-stream(_test-output-stream) -6830 # . . push args -6831 68/push _test-output-stream/imm32 -6832 # . . call -6833 e8/call clear-stream/disp32 -6834 # . . discard args -6835 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6836 # . clear-stream(_test-output-buffered-file+4) -6837 # . . push args -6838 b8/copy-to-EAX _test-output-buffered-file/imm32 -6839 05/add-to-EAX 4/imm32 -6840 50/push-EAX -6841 # . . call -6842 e8/call clear-stream/disp32 -6843 # . . discard args -6844 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6845 # var slice/ECX = "xyz/" -6846 68/push _test-slice-non-number-word-metadata-end/imm32/end -6847 68/push _test-slice-non-number-word/imm32/start -6848 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -6849 # emit(_test-output-buffered-file, slice, 2) -6850 # . . push args -6851 68/push 2/imm32 -6852 51/push-ECX -6853 68/push _test-output-buffered-file/imm32 -6854 # . . call -6855 e8/call emit/disp32 -6856 # . . discard args -6857 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6858 # flush(_test-output-buffered-file) -6859 # . . push args -6860 68/push _test-output-buffered-file/imm32 -6861 # . . call -6862 e8/call flush/disp32 -6863 # . . discard args -6864 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6865 # check-stream-equal(_test-output-stream, "xyz/", msg) -6866 # . . push args -6867 68/push "F - test-emit-non-number-with-metadata"/imm32 -6868 68/push "xyz/ "/imm32 -6869 68/push _test-output-stream/imm32 -6870 # . . call -6871 e8/call check-stream-equal/disp32 -6872 # . . discard args -6873 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6874 # . epilog -6875 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -6876 5d/pop-to-EBP -6877 c3/return -6878 -6879 test-emit-non-number-with-all-hex-digits-and-metadata: -6880 # . prolog -6881 55/push-EBP -6882 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -6883 # setup -6884 # . clear-stream(_test-output-stream) -6885 # . . push args -6886 68/push _test-output-stream/imm32 -6887 # . . call -6888 e8/call clear-stream/disp32 -6889 # . . discard args -6890 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6891 # . clear-stream(_test-output-buffered-file+4) -6892 # . . push args -6893 b8/copy-to-EAX _test-output-buffered-file/imm32 -6894 05/add-to-EAX 4/imm32 -6895 50/push-EAX -6896 # . . call -6897 e8/call clear-stream/disp32 -6898 # . . discard args -6899 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6900 # var slice/ECX = "abcd/xyz" -6901 68/push _test-slice-hexlike-non-number-word-metadata-end/imm32/end -6902 68/push _test-slice-hexlike-non-number-word/imm32/start -6903 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -6904 # emit(_test-output-buffered-file, slice, 2) +6545 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6546 # . epilog +6547 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6548 5d/pop-to-EBP +6549 c3/return +6550 +6551 test-emit-number-with-metadata: +6552 # . prolog +6553 55/push-EBP +6554 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +6555 # setup +6556 # . clear-stream(_test-output-stream) +6557 # . . push args +6558 68/push _test-output-stream/imm32 +6559 # . . call +6560 e8/call clear-stream/disp32 +6561 # . . discard args +6562 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6563 # . clear-stream(_test-output-buffered-file+4) +6564 # . . push args +6565 b8/copy-to-EAX _test-output-buffered-file/imm32 +6566 05/add-to-EAX 4/imm32 +6567 50/push-EAX +6568 # . . call +6569 e8/call clear-stream/disp32 +6570 # . . discard args +6571 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6572 # var slice/ECX = "-2/foo" +6573 68/push _test-slice-negative-two-metadata-end/imm32/end +6574 68/push _test-slice-negative-two/imm32/start +6575 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +6576 # emit(_test-output-buffered-file, slice, 2) +6577 # . . push args +6578 68/push 2/imm32 +6579 51/push-ECX +6580 68/push _test-output-buffered-file/imm32 +6581 # . . call +6582 e8/call emit/disp32 +6583 # . . discard args +6584 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6585 # flush(_test-output-buffered-file) +6586 # . . push args +6587 68/push _test-output-buffered-file/imm32 +6588 # . . call +6589 e8/call flush/disp32 +6590 # . . discard args +6591 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6592 # the '/foo' will have no impact on the output +6593 # check-stream-equal(_test-output-stream, "fe ff ", msg) +6594 # . . push args +6595 68/push "F - test-emit-number-with-metadata"/imm32 +6596 68/push "fe ff "/imm32 +6597 68/push _test-output-stream/imm32 +6598 # . . call +6599 e8/call check-stream-equal/disp32 +6600 # . . discard args +6601 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6602 # . epilog +6603 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6604 5d/pop-to-EBP +6605 c3/return +6606 +6607 test-emit-non-number: +6608 # . prolog +6609 55/push-EBP +6610 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +6611 # setup +6612 # . clear-stream(_test-output-stream) +6613 # . . push args +6614 68/push _test-output-stream/imm32 +6615 # . . call +6616 e8/call clear-stream/disp32 +6617 # . . discard args +6618 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6619 # . clear-stream(_test-output-buffered-file+4) +6620 # . . push args +6621 b8/copy-to-EAX _test-output-buffered-file/imm32 +6622 05/add-to-EAX 4/imm32 +6623 50/push-EAX +6624 # . . call +6625 e8/call clear-stream/disp32 +6626 # . . discard args +6627 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6628 # var slice/ECX = "xyz" +6629 68/push _test-slice-non-number-word-end/imm32/end +6630 68/push _test-slice-non-number-word/imm32/start +6631 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +6632 # emit(_test-output-buffered-file, slice, 2) +6633 # . . push args +6634 68/push 2/imm32 +6635 51/push-ECX +6636 68/push _test-output-buffered-file/imm32 +6637 # . . call +6638 e8/call emit/disp32 +6639 # . . discard args +6640 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6641 # flush(_test-output-buffered-file) +6642 # . . push args +6643 68/push _test-output-buffered-file/imm32 +6644 # . . call +6645 e8/call flush/disp32 +6646 # . . discard args +6647 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6648 # check-stream-equal(_test-output-stream, "xyz", msg) +6649 # . . push args +6650 68/push "F - test-emit-non-number"/imm32 +6651 68/push "xyz "/imm32 +6652 68/push _test-output-stream/imm32 +6653 # . . call +6654 e8/call check-stream-equal/disp32 +6655 # . . discard args +6656 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6657 # . epilog +6658 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6659 5d/pop-to-EBP +6660 c3/return +6661 +6662 test-emit-non-number-with-metadata: +6663 # . prolog +6664 55/push-EBP +6665 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +6666 # setup +6667 # . clear-stream(_test-output-stream) +6668 # . . push args +6669 68/push _test-output-stream/imm32 +6670 # . . call +6671 e8/call clear-stream/disp32 +6672 # . . discard args +6673 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6674 # . clear-stream(_test-output-buffered-file+4) +6675 # . . push args +6676 b8/copy-to-EAX _test-output-buffered-file/imm32 +6677 05/add-to-EAX 4/imm32 +6678 50/push-EAX +6679 # . . call +6680 e8/call clear-stream/disp32 +6681 # . . discard args +6682 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6683 # var slice/ECX = "xyz/" +6684 68/push _test-slice-non-number-word-metadata-end/imm32/end +6685 68/push _test-slice-non-number-word/imm32/start +6686 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +6687 # emit(_test-output-buffered-file, slice, 2) +6688 # . . push args +6689 68/push 2/imm32 +6690 51/push-ECX +6691 68/push _test-output-buffered-file/imm32 +6692 # . . call +6693 e8/call emit/disp32 +6694 # . . discard args +6695 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6696 # flush(_test-output-buffered-file) +6697 # . . push args +6698 68/push _test-output-buffered-file/imm32 +6699 # . . call +6700 e8/call flush/disp32 +6701 # . . discard args +6702 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6703 # check-stream-equal(_test-output-stream, "xyz/", msg) +6704 # . . push args +6705 68/push "F - test-emit-non-number-with-metadata"/imm32 +6706 68/push "xyz/ "/imm32 +6707 68/push _test-output-stream/imm32 +6708 # . . call +6709 e8/call check-stream-equal/disp32 +6710 # . . discard args +6711 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6712 # . epilog +6713 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6714 5d/pop-to-EBP +6715 c3/return +6716 +6717 test-emit-non-number-with-all-hex-digits-and-metadata: +6718 # . prolog +6719 55/push-EBP +6720 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +6721 # setup +6722 # . clear-stream(_test-output-stream) +6723 # . . push args +6724 68/push _test-output-stream/imm32 +6725 # . . call +6726 e8/call clear-stream/disp32 +6727 # . . discard args +6728 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6729 # . clear-stream(_test-output-buffered-file+4) +6730 # . . push args +6731 b8/copy-to-EAX _test-output-buffered-file/imm32 +6732 05/add-to-EAX 4/imm32 +6733 50/push-EAX +6734 # . . call +6735 e8/call clear-stream/disp32 +6736 # . . discard args +6737 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6738 # var slice/ECX = "abcd/xyz" +6739 68/push _test-slice-hexlike-non-number-word-metadata-end/imm32/end +6740 68/push _test-slice-hexlike-non-number-word/imm32/start +6741 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +6742 # emit(_test-output-buffered-file, slice, 2) +6743 # . . push args +6744 68/push 2/imm32 +6745 51/push-ECX +6746 68/push _test-output-buffered-file/imm32 +6747 # . . call +6748 e8/call emit/disp32 +6749 # . . discard args +6750 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6751 # flush(_test-output-buffered-file) +6752 # . . push args +6753 68/push _test-output-buffered-file/imm32 +6754 # . . call +6755 e8/call flush/disp32 +6756 # . . discard args +6757 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6758 +-- 26 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- +6784 # check-stream-equal(_test-output-stream, "abcd/xyz") +6785 # . . push args +6786 68/push "F - test-emit-non-number-with-all-hex-digits"/imm32 +6787 68/push "abcd/xyz "/imm32 +6788 68/push _test-output-stream/imm32 +6789 # . . call +6790 e8/call check-stream-equal/disp32 +6791 # . . discard args +6792 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6793 # . epilog +6794 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6795 5d/pop-to-EBP +6796 c3/return +6797 +6798 # conditions for 'valid' names that are not at risk of looking like hex numbers +6799 # keep in sync with the rules in labels.cc +6800 #: - if it starts with a digit, it's treated as a number. If it can't be +6801 #: parsed as hex it will raise an error. +6802 #: - if it starts with '-' it's treated as a number. +6803 #: - if it starts with '0x' it's treated as a number. (redundant) +6804 #: - if it's two characters long, it can't be a name. Either it's a hex +6805 #: byte, or it raises an error. +6806 is-valid-name?: # in : (address slice) -> EAX : boolean +6807 # . prolog +6808 55/push-EBP +6809 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +6810 # . save registers +6811 51/push-ECX +6812 56/push-ESI +6813 # ESI = in +6814 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +6815 # start/ECX = in->start +6816 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX +6817 # end/EAX = in->end +6818 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy *(ESI+4) to EAX +6819 $is-valid-name?:check0: +6820 # if (start >= end) return false +6821 39/compare 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # compare ECX with EAX +6822 7d/jump-if-greater-or-equal $is-valid-name?:false/disp8 +6823 $is-valid-name?:check1: +6824 # EAX -= ECX +6825 29/subtract 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # subtract ECX from EAX +6826 # if (EAX == 2) return false +6827 3d/compare-EAX-and 2/imm32 +6828 74/jump-if-equal $is-valid-name?:false/disp8 +6829 $is-valid-name?:check2: +6830 # c/EAX = *ECX +6831 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +6832 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +6833 # if (c == "-") return false +6834 3d/compare-EAX-and 2d/imm32/- +6835 74/jump-if-equal $is-valid-name?:false/disp8 +6836 $is-valid-name?:check3a: +6837 # if (c < "0") return true +6838 3d/compare-EAX-with 30/imm32/0 +6839 7c/jump-if-lesser $is-valid-name?:true/disp8 +6840 $is-valid-name?:check3b: +6841 # if (c > "9") return true +6842 3d/compare-EAX-with 39/imm32/9 +6843 7f/jump-if-greater $is-valid-name?:true/disp8 +6844 $is-valid-name?:false: +6845 # return false +6846 b8/copy-to-EAX 0/imm32/false +6847 eb/jump $is-valid-name?:end/disp8 +6848 $is-valid-name?:true: +6849 # return true +6850 b8/copy-to-EAX 1/imm32/true +6851 $is-valid-name?:end: +6852 # . restore registers +6853 5e/pop-to-ESI +6854 59/pop-to-ECX +6855 # . epilog +6856 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6857 5d/pop-to-EBP +6858 c3/return +6859 +6860 test-is-valid-name-digit-prefix: +6861 # . prolog +6862 55/push-EBP +6863 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +6864 # var slice/ECX = "34" +6865 68/push _test-slice-hex-int-end/imm32 +6866 68/push _test-slice-hex-int/imm32 +6867 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +6868 # EAX = is-valid-name?(slice) +6869 # . . push args +6870 51/push-ECX +6871 # . . call +6872 e8/call is-valid-name?/disp32 +6873 # . . discard args +6874 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6875 # check-ints-equal(EAX, 0, msg) +6876 # . . push args +6877 68/push "F - test-is-valid-name-digit-prefix"/imm32 +6878 68/push 0/imm32/false +6879 50/push-EAX +6880 # . . call +6881 e8/call check-ints-equal/disp32 +6882 # . . discard args +6883 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6884 # . epilog +6885 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6886 5d/pop-to-EBP +6887 c3/return +6888 +6889 test-is-valid-name-negative-prefix: +6890 # . prolog +6891 55/push-EBP +6892 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +6893 # var slice/ECX = "-0x34" +6894 68/push _test-slice-hex-int-with-0x-prefix-end/imm32 +6895 68/push _test-slice-hex-int-with-0x-prefix-negative/imm32 +6896 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +6897 # EAX = is-valid-name?(slice) +6898 # . . push args +6899 51/push-ECX +6900 # . . call +6901 e8/call is-valid-name?/disp32 +6902 # . . discard args +6903 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6904 # check-ints-equal(EAX, 0, msg) 6905 # . . push args -6906 68/push 2/imm32 -6907 51/push-ECX -6908 68/push _test-output-buffered-file/imm32 +6906 68/push "F - test-is-valid-name-negative-prefix"/imm32 +6907 68/push 0/imm32/false +6908 50/push-EAX 6909 # . . call -6910 e8/call emit/disp32 +6910 e8/call check-ints-equal/disp32 6911 # . . discard args 6912 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6913 # flush(_test-output-buffered-file) -6914 # . . push args -6915 68/push _test-output-buffered-file/imm32 -6916 # . . call -6917 e8/call flush/disp32 -6918 # . . discard args -6919 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -6920 +-- 34 lines: #? # dump output --------------------------------------------------------------------------------------------------------------------------- -6954 # check-stream-equal(_test-output-stream, "abcd/xyz") -6955 # . . push args -6956 68/push "F - test-emit-non-number-with-all-hex-digits"/imm32 -6957 68/push "abcd/xyz "/imm32 -6958 68/push _test-output-stream/imm32 -6959 # . . call -6960 e8/call check-stream-equal/disp32 -6961 # . . discard args -6962 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -6963 # . epilog -6964 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -6965 5d/pop-to-EBP -6966 c3/return -6967 -6968 # conditions for 'valid' names that are not at risk of looking like hex numbers -6969 # keep in sync with the rules in labels.cc -6970 #: - if it starts with a digit, it's treated as a number. If it can't be -6971 #: parsed as hex it will raise an error. -6972 #: - if it starts with '-' it's treated as a number. -6973 #: - if it starts with '0x' it's treated as a number. (redundant) -6974 #: - if it's two characters long, it can't be a name. Either it's a hex -6975 #: byte, or it raises an error. -6976 is-valid-name?: # in : (address slice) -> EAX : boolean +6913 # . epilog +6914 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6915 5d/pop-to-EBP +6916 c3/return +6917 +6918 test-is-valid-name-0x-prefix: +6919 # . prolog +6920 55/push-EBP +6921 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +6922 # var slice/ECX = "0x34" +6923 68/push _test-slice-hex-int-with-0x-prefix-end/imm32 +6924 68/push _test-slice-hex-int-with-0x-prefix/imm32 +6925 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +6926 # EAX = is-valid-name?(slice) +6927 # . . push args +6928 51/push-ECX +6929 # . . call +6930 e8/call is-valid-name?/disp32 +6931 # . . discard args +6932 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6933 # check-ints-equal(EAX, 0, msg) +6934 # . . push args +6935 68/push "F - test-is-valid-name-0x-prefix"/imm32 +6936 68/push 0/imm32/false +6937 50/push-EAX +6938 # . . call +6939 e8/call check-ints-equal/disp32 +6940 # . . discard args +6941 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6942 # . epilog +6943 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6944 5d/pop-to-EBP +6945 c3/return +6946 +6947 test-is-valid-name-starts-with-pre-digit: +6948 # . prolog +6949 55/push-EBP +6950 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +6951 # var slice/ECX = "/03" +6952 68/push _test-slice-with-slash-prefix-end/imm32 +6953 68/push _test-slice-with-slash-prefix/imm32 +6954 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +6955 # EAX = is-valid-name?(slice) +6956 # . . push args +6957 51/push-ECX +6958 # . . call +6959 e8/call is-valid-name?/disp32 +6960 # . . discard args +6961 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6962 # check-ints-equal(EAX, 1, msg) +6963 # . . push args +6964 68/push "F - test-is-valid-name-starts-with-pre-digit"/imm32 +6965 68/push 1/imm32/true +6966 50/push-EAX +6967 # . . call +6968 e8/call check-ints-equal/disp32 +6969 # . . discard args +6970 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +6971 # . epilog +6972 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +6973 5d/pop-to-EBP +6974 c3/return +6975 +6976 test-is-valid-name-starts-with-post-digit: 6977 # . prolog 6978 55/push-EBP 6979 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -6980 # . save registers -6981 51/push-ECX -6982 56/push-ESI -6983 # ESI = in -6984 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI -6985 # start/ECX = in->start -6986 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX -6987 # end/EAX = in->end -6988 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 4/disp8 . # copy *(ESI+4) to EAX -6989 $is-valid-name?:check0: -6990 # if (start >= end) return false -6991 39/compare 3/mod/direct 1/rm32/ECX . . . 0/r32/EAX . . # compare ECX with EAX -6992 7d/jump-if-greater-or-equal $is-valid-name?:false/disp8 -6993 $is-valid-name?:check1: -6994 # EAX -= ECX -6995 29/subtract 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # subtract ECX from EAX -6996 # if (EAX == 2) return false -6997 3d/compare-EAX-and 2/imm32 -6998 74/jump-if-equal $is-valid-name?:false/disp8 -6999 $is-valid-name?:check2: -7000 # c/EAX = *ECX -7001 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -7002 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL -7003 # if (c == "-") return false -7004 3d/compare-EAX-and 2d/imm32/- -7005 74/jump-if-equal $is-valid-name?:false/disp8 -7006 $is-valid-name?:check3a: -7007 # if (c < "0") return true -7008 3d/compare-EAX-with 30/imm32/0 -7009 7c/jump-if-lesser $is-valid-name?:true/disp8 -7010 $is-valid-name?:check3b: -7011 # if (c > "9") return true -7012 3d/compare-EAX-with 39/imm32/9 -7013 7f/jump-if-greater $is-valid-name?:true/disp8 -7014 $is-valid-name?:false: -7015 # return false -7016 b8/copy-to-EAX 0/imm32/false -7017 eb/jump $is-valid-name?:end/disp8 -7018 $is-valid-name?:true: -7019 # return true -7020 b8/copy-to-EAX 1/imm32/true -7021 $is-valid-name?:end: -7022 # . restore registers -7023 5e/pop-to-ESI -7024 59/pop-to-ECX -7025 # . epilog -7026 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -7027 5d/pop-to-EBP -7028 c3/return -7029 -7030 test-is-valid-name-digit-prefix: -7031 # . prolog -7032 55/push-EBP -7033 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -7034 # var slice/ECX = "34" -7035 68/push _test-slice-hex-int-end/imm32 -7036 68/push _test-slice-hex-int/imm32 -7037 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -7038 # EAX = is-valid-name?(slice) -7039 # . . push args -7040 51/push-ECX -7041 # . . call -7042 e8/call is-valid-name?/disp32 -7043 # . . discard args -7044 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7045 # check-ints-equal(EAX, 0, msg) -7046 # . . push args -7047 68/push "F - test-is-valid-name-digit-prefix"/imm32 -7048 68/push 0/imm32/false -7049 50/push-EAX -7050 # . . call -7051 e8/call check-ints-equal/disp32 -7052 # . . discard args -7053 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -7054 # . epilog -7055 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -7056 5d/pop-to-EBP -7057 c3/return -7058 -7059 test-is-valid-name-negative-prefix: -7060 # . prolog -7061 55/push-EBP -7062 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -7063 # var slice/ECX = "-0x34" -7064 68/push _test-slice-hex-int-with-0x-prefix-end/imm32 -7065 68/push _test-slice-hex-int-with-0x-prefix-negative/imm32 -7066 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -7067 # EAX = is-valid-name?(slice) -7068 # . . push args -7069 51/push-ECX -7070 # . . call -7071 e8/call is-valid-name?/disp32 -7072 # . . discard args -7073 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7074 # check-ints-equal(EAX, 0, msg) -7075 # . . push args -7076 68/push "F - test-is-valid-name-negative-prefix"/imm32 -7077 68/push 0/imm32/false -7078 50/push-EAX -7079 # . . call -7080 e8/call check-ints-equal/disp32 -7081 # . . discard args -7082 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -7083 # . epilog -7084 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -7085 5d/pop-to-EBP -7086 c3/return -7087 -7088 test-is-valid-name-0x-prefix: -7089 # . prolog -7090 55/push-EBP -7091 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -7092 # var slice/ECX = "0x34" -7093 68/push _test-slice-hex-int-with-0x-prefix-end/imm32 -7094 68/push _test-slice-hex-int-with-0x-prefix/imm32 -7095 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -7096 # EAX = is-valid-name?(slice) -7097 # . . push args -7098 51/push-ECX -7099 # . . call -7100 e8/call is-valid-name?/disp32 -7101 # . . discard args -7102 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7103 # check-ints-equal(EAX, 0, msg) -7104 # . . push args -7105 68/push "F - test-is-valid-name-0x-prefix"/imm32 -7106 68/push 0/imm32/false -7107 50/push-EAX -7108 # . . call -7109 e8/call check-ints-equal/disp32 -7110 # . . discard args -7111 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -7112 # . epilog -7113 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -7114 5d/pop-to-EBP -7115 c3/return -7116 -7117 test-is-valid-name-starts-with-pre-digit: -7118 # . prolog -7119 55/push-EBP -7120 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -7121 # var slice/ECX = "/03" -7122 68/push _test-slice-with-slash-prefix-end/imm32 -7123 68/push _test-slice-with-slash-prefix/imm32 -7124 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -7125 # EAX = is-valid-name?(slice) +6980 # var slice/ECX = "q34" +6981 68/push _test-slice-char-and-digits-end/imm32 +6982 68/push _test-slice-char-and-digits/imm32 +6983 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +6984 # EAX = is-valid-name?(slice) +6985 # . . push args +6986 51/push-ECX +6987 # . . call +6988 e8/call is-valid-name?/disp32 +6989 # . . discard args +6990 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +6991 # check-ints-equal(EAX, 1, msg) +6992 # . . push args +6993 68/push "F - test-is-valid-name-starts-with-post-digit"/imm32 +6994 68/push 1/imm32/true +6995 50/push-EAX +6996 # . . call +6997 e8/call check-ints-equal/disp32 +6998 # . . discard args +6999 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +7000 # . epilog +7001 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +7002 5d/pop-to-EBP +7003 c3/return +7004 +7005 test-is-valid-name-starts-with-digit: +7006 # . prolog +7007 55/push-EBP +7008 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +7009 # var slice/ECX = "0x34" +7010 68/push _test-slice-hex-int-with-0x-prefix-end/imm32 +7011 68/push _test-slice-hex-int-with-0x-prefix/imm32 +7012 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +7013 # EAX = is-valid-name?(slice) +7014 # . . push args +7015 51/push-ECX +7016 # . . call +7017 e8/call is-valid-name?/disp32 +7018 # . . discard args +7019 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +7020 # check-ints-equal(EAX, 0, msg) +7021 # . . push args +7022 68/push "F - test-is-valid-name-starts-with-digit"/imm32 +7023 68/push 0/imm32/false +7024 50/push-EAX +7025 # . . call +7026 e8/call check-ints-equal/disp32 +7027 # . . discard args +7028 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +7029 # . epilog +7030 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +7031 5d/pop-to-EBP +7032 c3/return +7033 +7034 # print 'n' in hex in 'width' bytes in lower-endian order, with a space after every byte +7035 emit-hex: # out : (address buffered-file), n : int, width : int -> <void> +7036 # . prolog +7037 55/push-EBP +7038 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +7039 # . save registers +7040 50/push-EAX +7041 51/push-ECX +7042 52/push-EDX +7043 53/push-EBX +7044 57/push-EDI +7045 # EDI = out +7046 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI +7047 # EBX = n +7048 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX +7049 # EDX = width +7050 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 2/r32/EDX 0x10/disp8 . # copy *(EBP+16) to EDX +7051 # var curr/ECX = 0 +7052 31/xor 3/mod/direct 1/rm32/ECX . . . 1/r32/ECX . . # clear ECX +7053 $emit-hex:loop: +7054 # if (curr >= width) break +7055 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX +7056 7d/jump-if-greater-or-equal $emit-hex:end/disp8 +7057 # print-byte(out, EBX) +7058 # . . push args +7059 53/push-EBX +7060 57/push-EDI +7061 # . . call +7062 e8/call print-byte/disp32 +7063 # . . discard args +7064 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +7065 # write-byte(out, ' ') +7066 # . . push args +7067 68/push 0x20/imm32/space +7068 57/push-EDI +7069 # . . call +7070 e8/call write-byte/disp32 +7071 # . . discard args +7072 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +7073 # EBX = EBX >> 8 +7074 c1/shift 5/subop/logic-right 3/mod/direct 3/rm32/EBX . . . . . 8/imm8 # shift EBX right by 8 bits, while padding zeroes +7075 $emit-hex:continue: +7076 # ++curr +7077 41/increment-ECX +7078 eb/jump $emit-hex:loop/disp8 +7079 $emit-hex:end: +7080 # . restore registers +7081 5f/pop-to-EDI +7082 5b/pop-to-EBX +7083 5a/pop-to-EDX +7084 59/pop-to-ECX +7085 58/pop-to-EAX +7086 # . epilog +7087 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +7088 5d/pop-to-EBP +7089 c3/return +7090 +7091 test-emit-hex-single-byte: +7092 # setup +7093 # . clear-stream(_test-output-stream) +7094 # . . push args +7095 68/push _test-output-stream/imm32 +7096 # . . call +7097 e8/call clear-stream/disp32 +7098 # . . discard args +7099 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +7100 # . clear-stream(_test-output-buffered-file+4) +7101 # . . push args +7102 b8/copy-to-EAX _test-output-buffered-file/imm32 +7103 05/add-to-EAX 4/imm32 +7104 50/push-EAX +7105 # . . call +7106 e8/call clear-stream/disp32 +7107 # . . discard args +7108 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +7109 # emit-hex(_test-output-buffered-file, 0xab, 1) +7110 # . . push args +7111 68/push 1/imm32 +7112 68/push 0xab/imm32 +7113 68/push _test-output-buffered-file/imm32 +7114 # . . call +7115 e8/call emit-hex/disp32 +7116 # . . discard args +7117 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +7118 # flush(_test-output-buffered-file) +7119 # . . push args +7120 68/push _test-output-buffered-file/imm32 +7121 # . . call +7122 e8/call flush/disp32 +7123 # . . discard args +7124 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +7125 # check-ints-equal(*_test-output-stream->data, 'ab ', msg) 7126 # . . push args -7127 51/push-ECX -7128 # . . call -7129 e8/call is-valid-name?/disp32 -7130 # . . discard args -7131 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7132 # check-ints-equal(EAX, 1, msg) -7133 # . . push args -7134 68/push "F - test-is-valid-name-starts-with-pre-digit"/imm32 -7135 68/push 1/imm32/true -7136 50/push-EAX -7137 # . . call -7138 e8/call check-ints-equal/disp32 -7139 # . . discard args -7140 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -7141 # . epilog -7142 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -7143 5d/pop-to-EBP -7144 c3/return -7145 -7146 test-is-valid-name-starts-with-post-digit: -7147 # . prolog -7148 55/push-EBP -7149 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -7150 # var slice/ECX = "q34" -7151 68/push _test-slice-char-and-digits-end/imm32 -7152 68/push _test-slice-char-and-digits/imm32 -7153 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -7154 # EAX = is-valid-name?(slice) -7155 # . . push args -7156 51/push-ECX -7157 # . . call -7158 e8/call is-valid-name?/disp32 -7159 # . . discard args -7160 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7161 # check-ints-equal(EAX, 1, msg) -7162 # . . push args -7163 68/push "F - test-is-valid-name-starts-with-post-digit"/imm32 -7164 68/push 1/imm32/true -7165 50/push-EAX -7166 # . . call -7167 e8/call check-ints-equal/disp32 -7168 # . . discard args -7169 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -7170 # . epilog -7171 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -7172 5d/pop-to-EBP -7173 c3/return -7174 -7175 test-is-valid-name-starts-with-digit: -7176 # . prolog -7177 55/push-EBP -7178 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -7179 # var slice/ECX = "0x34" -7180 68/push _test-slice-hex-int-with-0x-prefix-end/imm32 -7181 68/push _test-slice-hex-int-with-0x-prefix/imm32 -7182 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -7183 # EAX = is-valid-name?(slice) -7184 # . . push args -7185 51/push-ECX -7186 # . . call -7187 e8/call is-valid-name?/disp32 -7188 # . . discard args -7189 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7190 # check-ints-equal(EAX, 0, msg) -7191 # . . push args -7192 68/push "F - test-is-valid-name-starts-with-digit"/imm32 -7193 68/push 0/imm32/false -7194 50/push-EAX -7195 # . . call -7196 e8/call check-ints-equal/disp32 -7197 # . . discard args -7198 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -7199 # . epilog -7200 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -7201 5d/pop-to-EBP -7202 c3/return -7203 -7204 # print 'n' in hex in 'width' bytes in lower-endian order, with a space after every byte -7205 emit-hex: # out : (address buffered-file), n : int, width : int -> <void> -7206 # . prolog -7207 55/push-EBP -7208 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -7209 # . save registers -7210 50/push-EAX -7211 51/push-ECX -7212 52/push-EDX -7213 53/push-EBX -7214 57/push-EDI -7215 # EDI = out -7216 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI -7217 # EBX = n -7218 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX -7219 # EDX = width -7220 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 2/r32/EDX 0x10/disp8 . # copy *(EBP+16) to EDX -7221 # var curr/ECX = 0 -7222 31/xor 3/mod/direct 1/rm32/ECX . . . 1/r32/ECX . . # clear ECX -7223 $emit-hex:loop: -7224 # if (curr >= width) break -7225 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX and EDX -7226 7d/jump-if-greater-or-equal $emit-hex:end/disp8 -7227 # print-byte(out, EBX) -7228 # . . push args -7229 53/push-EBX -7230 57/push-EDI -7231 # . . call -7232 e8/call print-byte/disp32 -7233 # . . discard args -7234 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -7235 # write-byte(out, ' ') -7236 # . . push args -7237 68/push 0x20/imm32/space -7238 57/push-EDI -7239 # . . call -7240 e8/call write-byte/disp32 -7241 # . . discard args -7242 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -7243 # EBX = EBX >> 8 -7244 c1/shift 5/subop/logic-right 3/mod/direct 3/rm32/EBX . . . . . 8/imm8 # shift EBX right by 8 bits, while padding zeroes -7245 $emit-hex:continue: -7246 # ++curr -7247 41/increment-ECX -7248 eb/jump $emit-hex:loop/disp8 -7249 $emit-hex:end: -7250 # . restore registers -7251 5f/pop-to-EDI -7252 5b/pop-to-EBX -7253 5a/pop-to-EDX -7254 59/pop-to-ECX -7255 58/pop-to-EAX -7256 # . epilog -7257 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -7258 5d/pop-to-EBP -7259 c3/return -7260 -7261 test-emit-hex-single-byte: -7262 # setup -7263 # . clear-stream(_test-output-stream) -7264 # . . push args -7265 68/push _test-output-stream/imm32 -7266 # . . call -7267 e8/call clear-stream/disp32 -7268 # . . discard args -7269 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7270 # . clear-stream(_test-output-buffered-file+4) -7271 # . . push args -7272 b8/copy-to-EAX _test-output-buffered-file/imm32 -7273 05/add-to-EAX 4/imm32 -7274 50/push-EAX -7275 # . . call -7276 e8/call clear-stream/disp32 -7277 # . . discard args -7278 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7279 # emit-hex(_test-output-buffered-file, 0xab, 1) -7280 # . . push args -7281 68/push 1/imm32 -7282 68/push 0xab/imm32 -7283 68/push _test-output-buffered-file/imm32 -7284 # . . call -7285 e8/call emit-hex/disp32 -7286 # . . discard args -7287 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -7288 # flush(_test-output-buffered-file) -7289 # . . push args -7290 68/push _test-output-buffered-file/imm32 -7291 # . . call -7292 e8/call flush/disp32 -7293 # . . discard args -7294 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7295 # check-ints-equal(*_test-output-stream->data, 'ab ', msg) -7296 # . . push args -7297 68/push "F - test-emit-hex-single-byte"/imm32 -7298 68/push 0x206261/imm32 -7299 # . . push *_test-output-stream->data -7300 b8/copy-to-EAX _test-output-stream/imm32 -7301 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) -7302 # . . call -7303 e8/call check-ints-equal/disp32 -7304 # . . discard args -7305 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -7306 # . end -7307 c3/return -7308 -7309 test-emit-hex-multiple-byte: -7310 # setup -7311 # . clear-stream(_test-output-stream) -7312 # . . push args -7313 68/push _test-output-stream/imm32 -7314 # . . call -7315 e8/call clear-stream/disp32 -7316 # . . discard args -7317 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7318 # . clear-stream(_test-output-buffered-file+4) -7319 # . . push args -7320 b8/copy-to-EAX _test-output-buffered-file/imm32 -7321 05/add-to-EAX 4/imm32 -7322 50/push-EAX -7323 # . . call -7324 e8/call clear-stream/disp32 -7325 # . . discard args -7326 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7327 # emit-hex(_test-output-buffered-file, 0x1234, 2) -7328 # . . push args -7329 68/push 2/imm32 -7330 68/push 0x1234/imm32 -7331 68/push _test-output-buffered-file/imm32 -7332 # . . call -7333 e8/call emit-hex/disp32 -7334 # . . discard args -7335 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -7336 # flush(_test-output-buffered-file) -7337 # . . push args -7338 68/push _test-output-buffered-file/imm32 -7339 # . . call -7340 e8/call flush/disp32 -7341 # . . discard args -7342 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7343 # check-stream-equal(_test-output-stream, "34 12 ", msg) -7344 # . . push args -7345 68/push "F - test-emit-hex-multiple-byte/1"/imm32 -7346 68/push "34 12 "/imm32 -7347 68/push _test-output-stream/imm32 -7348 # . . call -7349 e8/call check-stream-equal/disp32 -7350 # . . discard args -7351 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -7352 # . end -7353 c3/return -7354 -7355 test-emit-hex-zero-pad: -7356 # setup -7357 # . clear-stream(_test-output-stream) -7358 # . . push args -7359 68/push _test-output-stream/imm32 -7360 # . . call -7361 e8/call clear-stream/disp32 -7362 # . . discard args -7363 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7364 # . clear-stream(_test-output-buffered-file+4) -7365 # . . push args -7366 b8/copy-to-EAX _test-output-buffered-file/imm32 -7367 05/add-to-EAX 4/imm32 -7368 50/push-EAX -7369 # . . call -7370 e8/call clear-stream/disp32 -7371 # . . discard args -7372 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7373 # emit-hex(_test-output-buffered-file, 0xab, 2) -7374 # . . push args -7375 68/push 2/imm32 -7376 68/push 0xab/imm32 -7377 68/push _test-output-buffered-file/imm32 -7378 # . . call -7379 e8/call emit-hex/disp32 -7380 # . . discard args -7381 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -7382 # flush(_test-output-buffered-file) -7383 # . . push args -7384 68/push _test-output-buffered-file/imm32 -7385 # . . call -7386 e8/call flush/disp32 -7387 # . . discard args -7388 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7389 # check(_test-output-stream->data == 'ab 00 ') -7390 # . . push args -7391 68/push "F - test-emit-hex-zero-pad/1"/imm32 -7392 68/push "ab 00 "/imm32 -7393 68/push _test-output-stream/imm32 -7394 # . . call -7395 e8/call check-stream-equal/disp32 -7396 # . . discard args -7397 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -7398 # . end -7399 c3/return -7400 -7401 test-emit-hex-negative: -7402 # setup -7403 # . clear-stream(_test-output-stream) -7404 # . . push args -7405 68/push _test-output-stream/imm32 -7406 # . . call -7407 e8/call clear-stream/disp32 -7408 # . . discard args -7409 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7410 # . clear-stream(_test-output-buffered-file+4) -7411 # . . push args -7412 b8/copy-to-EAX _test-output-buffered-file/imm32 -7413 05/add-to-EAX 4/imm32 -7414 50/push-EAX -7415 # . . call -7416 e8/call clear-stream/disp32 -7417 # . . discard args -7418 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7419 # emit-hex(_test-output-buffered-file, -1, 2) -7420 # . . push args -7421 68/push 2/imm32 -7422 68/push -1/imm32 -7423 68/push _test-output-buffered-file/imm32 -7424 # . . call -7425 e8/call emit-hex/disp32 -7426 # . . discard args -7427 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -7428 # flush(_test-output-buffered-file) -7429 # . . push args -7430 68/push _test-output-buffered-file/imm32 -7431 # . . call -7432 e8/call flush/disp32 -7433 # . . discard args -7434 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7435 # check-stream-equal(_test-output-stream == "ff ff ") -7436 # . . push args -7437 68/push "F - test-emit-hex-negative/1"/imm32 -7438 68/push "ff ff "/imm32 -7439 68/push _test-output-stream/imm32 -7440 # . . call -7441 e8/call check-stream-equal/disp32 -7442 # . . discard args -7443 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -7444 # . end -7445 c3/return -7446 -7447 # write an entire stream's contents to a buffered-file -7448 # ways to do this: -7449 # - construct a 'maximal slice' and pass it to write-slice -7450 # - flush the buffered-file and pass the stream directly to its fd (disabling buffering) -7451 # we'll go with the first way for now -7452 write-stream-data: # f : (address buffered-file), s : (address stream) -> <void> -7453 # . prolog -7454 55/push-EBP -7455 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -7456 # . save registers -7457 50/push-EAX -7458 51/push-ECX -7459 56/push-ESI -7460 # ESI = s -7461 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI -7462 # var slice/ECX = {s->data, s->data + s->write} -7463 # . push s->data + s->write -7464 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX -7465 8d/copy-address 1/mod/*+disp8 4/rm32/sib 6/base/ESI 0/index/EAX . 0/r32/EAX 0xc/disp8 . # copy ESI+EAX+12 to EAX -7466 50/push-EAX -7467 # . push s->data -7468 8d/copy-address 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 0xc/disp8 . # copy ESI+12 to EAX -7469 50/push-EAX -7470 # . ECX = ESP -7471 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -7472 # write-slice(f, slice) -7473 # . . push args -7474 51/push-ECX -7475 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -7476 # . . call -7477 e8/call write-slice/disp32 -7478 # . . discard args -7479 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -7480 $write-stream-data:end: -7481 # . restore locals -7482 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -7483 # . restore registers -7484 5e/pop-to-ESI -7485 59/pop-to-ECX -7486 58/pop-to-EAX -7487 # . epilog -7488 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -7489 5d/pop-to-EBP -7490 c3/return -7491 -7492 test-write-stream-data: -7493 # . prolog -7494 55/push-EBP -7495 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -7496 # setup -7497 # . clear-stream(_test-output-stream) -7498 # . . push args -7499 68/push _test-output-stream/imm32 -7500 # . . call -7501 e8/call clear-stream/disp32 -7502 # . . discard args -7503 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7504 # . clear-stream(_test-output-buffered-file+4) -7505 # . . push args -7506 b8/copy-to-EAX _test-output-buffered-file/imm32 -7507 05/add-to-EAX 4/imm32 -7508 50/push-EAX -7509 # . . call -7510 e8/call clear-stream/disp32 -7511 # . . discard args -7512 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7513 # . clear-stream(_test-tmp-stream) -7514 # . . push args -7515 68/push _test-tmp-stream/imm32 -7516 # . . call -7517 e8/call clear-stream/disp32 -7518 # . . discard args -7519 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7520 # initialize input -7521 # . write(_test-tmp-stream, "abcd") -7522 # . . push args -7523 68/push "abcd"/imm32 -7524 68/push _test-tmp-stream/imm32 -7525 # . . call -7526 e8/call write/disp32 -7527 # . . discard args -7528 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -7529 # write-stream-data(_test-output-buffered-file, _test-tmp-stream) -7530 # . . push args -7531 68/push _test-tmp-stream/imm32 -7532 68/push _test-output-buffered-file/imm32 -7533 # . . call -7534 e8/call write-stream-data/disp32 -7535 # . . discard args -7536 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -7537 # check that the write happened as expected -7538 # . flush(_test-output-buffered-file) -7539 # . . push args -7540 68/push _test-output-buffered-file/imm32 -7541 # . . call -7542 e8/call flush/disp32 -7543 # . . discard args -7544 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7545 # . check-stream-equal(_test-output-stream, "abcd", msg) -7546 # . . push args -7547 68/push "F - test-write-stream-data"/imm32 -7548 68/push "abcd"/imm32 -7549 68/push _test-output-stream/imm32 -7550 # . . call -7551 e8/call check-stream-equal/disp32 -7552 # . . discard args -7553 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -7554 # . epilog -7555 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -7556 5d/pop-to-EBP -7557 c3/return -7558 -7559 # shortcut for parse-hex-int(next-token-from-slice(word->start, word->end, '/')) -7560 parse-datum-of-word: # word : (address slice) -> value/EAX -7561 # . prolog -7562 55/push-EBP -7563 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -7564 # . save registers -7565 51/push-ECX -7566 56/push-ESI -7567 # ESI = word -7568 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI -7569 # var slice/ECX = {0, 0} -7570 68/push 0/imm32/end -7571 68/push 0/imm32/start -7572 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -7573 # slice = next-token-from-slice(word->start, word->end, '/') -7574 # . . push args -7575 51/push-ECX -7576 68/push 0x2f/imm32/slash -7577 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) -7578 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI -7579 # . . call -7580 e8/call next-token-from-slice/disp32 -7581 # . . discard args -7582 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP -7583 # value/EAX = parse-hex-int(slice) -7584 # . . push args -7585 51/push-ECX -7586 # . . call -7587 e8/call parse-hex-int/disp32 -7588 # . . discard args -7589 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -7590 $parse-datum-of-word:end: -7591 # . reclaim locals -7592 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -7593 # . restore registers -7594 5e/pop-to-ESI -7595 59/pop-to-ECX -7596 # . epilog -7597 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -7598 5d/pop-to-EBP -7599 c3/return -7600 -7601 == data -7602 -7603 _test-slice-negative-two: -7604 2d/- 32/2 -7605 _test-slice-negative-two-end: -7606 2f/slash 66/f 6f/o 6f/o -7607 _test-slice-negative-two-metadata-end: -7608 -7609 _test-slice-three-zero: -7610 33/3 30/0 -7611 _test-slice-three-zero-end: -7612 -7613 _test-slice-non-number-word: -7614 78/x 79/y 7a/z -7615 _test-slice-non-number-word-end: -7616 2f/slash -7617 _test-slice-non-number-word-metadata-end: -7618 -7619 _test-input-stream: -7620 # current write index -7621 0/imm32 -7622 # current read index -7623 0/imm32 -7624 # length -7625 0x80/imm32 # 128 bytes -7626 # data (8 lines x 16 bytes/line) -7627 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -7628 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -7629 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -7630 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -7631 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -7632 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -7633 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -7634 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -7635 -7636 # a test buffered file for _test-input-stream -7637 _test-input-buffered-file: -7638 # file descriptor or (address stream) -7639 _test-input-stream/imm32 -7640 # current write index -7641 0/imm32 -7642 # current read index -7643 0/imm32 -7644 # length -7645 6/imm32 -7646 # data -7647 00 00 00 00 00 00 # 6 bytes -7648 -7649 _test-output-stream: -7650 # current write index -7651 0/imm32 -7652 # current read index -7653 0/imm32 -7654 # length -7655 0x80/imm32 # 128 bytes -7656 # data (8 lines x 16 bytes/line) -7657 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -7658 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -7659 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -7660 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -7661 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -7662 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -7663 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -7664 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 -7665 -7666 # a test buffered file for _test-output-stream -7667 _test-output-buffered-file: -7668 # file descriptor or (address stream) -7669 _test-output-stream/imm32 -7670 # current write index -7671 0/imm32 -7672 # current read index -7673 0/imm32 -7674 # length -7675 6/imm32 -7676 # data -7677 00 00 00 00 00 00 # 6 bytes -7678 -7679 _test-slice-hexlike-non-number-word: -7680 61/a 62/b 63/c 64/d -7681 _test-slice-hexlike-non-number-word-end: -7682 2f/slash -7683 78/x 79/y 7a/z -7684 _test-slice-hexlike-non-number-word-metadata-end: -7685 -7686 _test-slice-with-slash-prefix: -7687 2f/slash 30/0 33/3 -7688 _test-slice-with-slash-prefix-end: -7689 -7690 # . . vim:nowrap:textwidth=0 +7127 68/push "F - test-emit-hex-single-byte"/imm32 +7128 68/push 0x206261/imm32 +7129 # . . push *_test-output-stream->data +7130 b8/copy-to-EAX _test-output-stream/imm32 +7131 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) +7132 # . . call +7133 e8/call check-ints-equal/disp32 +7134 # . . discard args +7135 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +7136 # . end +7137 c3/return +7138 +7139 test-emit-hex-multiple-byte: +7140 # setup +7141 # . clear-stream(_test-output-stream) +7142 # . . push args +7143 68/push _test-output-stream/imm32 +7144 # . . call +7145 e8/call clear-stream/disp32 +7146 # . . discard args +7147 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +7148 # . clear-stream(_test-output-buffered-file+4) +7149 # . . push args +7150 b8/copy-to-EAX _test-output-buffered-file/imm32 +7151 05/add-to-EAX 4/imm32 +7152 50/push-EAX +7153 # . . call +7154 e8/call clear-stream/disp32 +7155 # . . discard args +7156 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +7157 # emit-hex(_test-output-buffered-file, 0x1234, 2) +7158 # . . push args +7159 68/push 2/imm32 +7160 68/push 0x1234/imm32 +7161 68/push _test-output-buffered-file/imm32 +7162 # . . call +7163 e8/call emit-hex/disp32 +7164 # . . discard args +7165 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +7166 # flush(_test-output-buffered-file) +7167 # . . push args +7168 68/push _test-output-buffered-file/imm32 +7169 # . . call +7170 e8/call flush/disp32 +7171 # . . discard args +7172 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +7173 # check-stream-equal(_test-output-stream, "34 12 ", msg) +7174 # . . push args +7175 68/push "F - test-emit-hex-multiple-byte/1"/imm32 +7176 68/push "34 12 "/imm32 +7177 68/push _test-output-stream/imm32 +7178 # . . call +7179 e8/call check-stream-equal/disp32 +7180 # . . discard args +7181 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +7182 # . end +7183 c3/return +7184 +7185 test-emit-hex-zero-pad: +7186 # setup +7187 # . clear-stream(_test-output-stream) +7188 # . . push args +7189 68/push _test-output-stream/imm32 +7190 # . . call +7191 e8/call clear-stream/disp32 +7192 # . . discard args +7193 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +7194 # . clear-stream(_test-output-buffered-file+4) +7195 # . . push args +7196 b8/copy-to-EAX _test-output-buffered-file/imm32 +7197 05/add-to-EAX 4/imm32 +7198 50/push-EAX +7199 # . . call +7200 e8/call clear-stream/disp32 +7201 # . . discard args +7202 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +7203 # emit-hex(_test-output-buffered-file, 0xab, 2) +7204 # . . push args +7205 68/push 2/imm32 +7206 68/push 0xab/imm32 +7207 68/push _test-output-buffered-file/imm32 +7208 # . . call +7209 e8/call emit-hex/disp32 +7210 # . . discard args +7211 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +7212 # flush(_test-output-buffered-file) +7213 # . . push args +7214 68/push _test-output-buffered-file/imm32 +7215 # . . call +7216 e8/call flush/disp32 +7217 # . . discard args +7218 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +7219 # check(_test-output-stream->data == 'ab 00 ') +7220 # . . push args +7221 68/push "F - test-emit-hex-zero-pad/1"/imm32 +7222 68/push "ab 00 "/imm32 +7223 68/push _test-output-stream/imm32 +7224 # . . call +7225 e8/call check-stream-equal/disp32 +7226 # . . discard args +7227 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +7228 # . end +7229 c3/return +7230 +7231 test-emit-hex-negative: +7232 # setup +7233 # . clear-stream(_test-output-stream) +7234 # . . push args +7235 68/push _test-output-stream/imm32 +7236 # . . call +7237 e8/call clear-stream/disp32 +7238 # . . discard args +7239 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +7240 # . clear-stream(_test-output-buffered-file+4) +7241 # . . push args +7242 b8/copy-to-EAX _test-output-buffered-file/imm32 +7243 05/add-to-EAX 4/imm32 +7244 50/push-EAX +7245 # . . call +7246 e8/call clear-stream/disp32 +7247 # . . discard args +7248 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +7249 # emit-hex(_test-output-buffered-file, -1, 2) +7250 # . . push args +7251 68/push 2/imm32 +7252 68/push -1/imm32 +7253 68/push _test-output-buffered-file/imm32 +7254 # . . call +7255 e8/call emit-hex/disp32 +7256 # . . discard args +7257 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +7258 # flush(_test-output-buffered-file) +7259 # . . push args +7260 68/push _test-output-buffered-file/imm32 +7261 # . . call +7262 e8/call flush/disp32 +7263 # . . discard args +7264 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +7265 # check-stream-equal(_test-output-stream == "ff ff ") +7266 # . . push args +7267 68/push "F - test-emit-hex-negative/1"/imm32 +7268 68/push "ff ff "/imm32 +7269 68/push _test-output-stream/imm32 +7270 # . . call +7271 e8/call check-stream-equal/disp32 +7272 # . . discard args +7273 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +7274 # . end +7275 c3/return +7276 +7277 # shortcut for parse-hex-int(next-token-from-slice(word->start, word->end, '/')) +7278 parse-datum-of-word: # word : (address slice) -> value/EAX +7279 # . prolog +7280 55/push-EBP +7281 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +7282 # . save registers +7283 51/push-ECX +7284 56/push-ESI +7285 # ESI = word +7286 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +7287 # var slice/ECX = {0, 0} +7288 68/push 0/imm32/end +7289 68/push 0/imm32/start +7290 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +7291 # slice = next-token-from-slice(word->start, word->end, '/') +7292 # . . push args +7293 51/push-ECX +7294 68/push 0x2f/imm32/slash +7295 ff 6/subop/push 1/mod/*+disp8 6/rm32/ESI . . . . 4/disp8 . # push *(ESI+4) +7296 ff 6/subop/push 0/mod/indirect 6/rm32/ESI . . . . . . # push *ESI +7297 # . . call +7298 e8/call next-token-from-slice/disp32 +7299 # . . discard args +7300 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # add to ESP +7301 # value/EAX = parse-hex-int(slice) +7302 # . . push args +7303 51/push-ECX +7304 # . . call +7305 e8/call parse-hex-int/disp32 +7306 # . . discard args +7307 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +7308 $parse-datum-of-word:end: +7309 # . reclaim locals +7310 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +7311 # . restore registers +7312 5e/pop-to-ESI +7313 59/pop-to-ECX +7314 # . epilog +7315 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +7316 5d/pop-to-EBP +7317 c3/return +7318 +7319 == data +7320 +7321 _test-slice-negative-two: +7322 2d/- 32/2 +7323 _test-slice-negative-two-end: +7324 2f/slash 66/f 6f/o 6f/o +7325 _test-slice-negative-two-metadata-end: +7326 +7327 _test-slice-three-zero: +7328 33/3 30/0 +7329 _test-slice-three-zero-end: +7330 +7331 _test-slice-non-number-word: +7332 78/x 79/y 7a/z +7333 _test-slice-non-number-word-end: +7334 2f/slash +7335 _test-slice-non-number-word-metadata-end: +7336 +7337 _test-slice-hexlike-non-number-word: +7338 61/a 62/b 63/c 64/d +7339 _test-slice-hexlike-non-number-word-end: +7340 2f/slash +7341 78/x 79/y 7a/z +7342 _test-slice-hexlike-non-number-word-metadata-end: +7343 +7344 _test-slice-with-slash-prefix: +7345 2f/slash 30/0 33/3 +7346 _test-slice-with-slash-prefix-end: +7347 +7348 # . . vim:nowrap:textwidth=0 diff --git a/html/subx/apps/subx-common.subx.html b/html/subx/apps/subx-common.subx.html index 01e40369..15818838 100644 --- a/html/subx/apps/subx-common.subx.html +++ b/html/subx/apps/subx-common.subx.html @@ -6,16 +6,17 @@ - +