From 554777cb2b95e5f56541fc9be0da458c23adedea Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Thu, 14 Feb 2019 23:56:26 -0800 Subject: 4968 --- html/subx/072slice.subx.html | 1546 +++++++++++++++++++++++++----------------- subx/072slice.subx | 275 ++++++++ subx/apps/crenshaw2-1 | Bin 17622 -> 18370 bytes subx/apps/crenshaw2-1b | Bin 18181 -> 18929 bytes subx/apps/factorial | Bin 16540 -> 17288 bytes subx/apps/handle | Bin 17333 -> 18081 bytes subx/apps/hex | Bin 20601 -> 21349 bytes subx/apps/pack | Bin 20778 -> 21526 bytes 8 files changed, 1186 insertions(+), 635 deletions(-) diff --git a/html/subx/072slice.subx.html b/html/subx/072slice.subx.html index b2ae009c..36c731eb 100644 --- a/html/subx/072slice.subx.html +++ b/html/subx/072slice.subx.html @@ -18,12 +18,13 @@ a { color:inherit; } .Constant { color: #008787; } .LineNr { } .subxS1Comment { color: #0000af; } -.SpecialChar { color: #d70000; } +.CommentedCode { color: #8a8a8a; } .subxFunction { color: #af5f00; text-decoration: underline; } .subxTest { color: #5f8700; } .subxMinorFunction { color: #875f5f; } .Normal { color: #000000; background-color: #c6c6c6; padding-bottom: 1px; } .subxS2Comment { color: #8a8a8a; } +.SpecialChar { color: #d70000; } .subxH1Comment { color: #005faf; text-decoration: underline; } --> @@ -69,642 +70,917 @@ if ('onhashchange' in window) { 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 # main: - 10 e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'. - 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 with 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 # currs = s->start -101 # maxs = s->end -102 # if (maxs - currs != p->length) return false -103 # currp = p->data -104 # while (currs < maxs) -105 # if (*currs != *currp) return false -106 # ++currs -107 # ++currp -108 # return true -109 # -110 # registers: -111 # currs: EDX -112 # maxs: ESI -113 # currp: EBX -114 # *currs: EAX -115 # *currp: ECX -116 # -117 # . prolog -118 55/push-EBP -119 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -120 # . save registers -121 51/push-ECX -122 52/push-EDX -123 53/push-EBX -124 56/push-ESI -125 # ESI = s -126 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI -127 # currs/EDX = s->start -128 8b/copy 0/mod/indirect 6/rm32/ESI . . . 2/r32/EDX . . # copy *ESI to EDX -129 # maxs/ESI = s->end -130 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 6/r32/ESI 4/disp8 . # copy *(ESI+4) to ESI -131 # EBX = p -132 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX -133 # EAX = maxs - currs -134 89/copy 3/mod/direct 0/rm32/EAX . . . 6/r32/ESI . . # copy ESI to EAX -135 29/subtract 3/mod/direct 0/rm32/EAX . . . 2/r32/EDX . . # subtract EDX from EAX -136 # if (EAX != p->length) return false -137 39/compare 0/mod/indirect 3/rm32/EBX . . . 0/r32/EAX . . # compare *EBX and EAX -138 75/jump-if-not-equal $slice-equal?:false/disp8 -139 # currp/EBX = p->data -140 81 0/subop/add 3/mod/direct 3/rm32/EBX . . . . . 4/imm32 # add to EBX -141 # EAX = ECX = 0 -142 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -143 31/xor 3/mod/direct 1/rm32/ECX . . . 1/r32/ECX . . # clear ECX -144 $slice-equal?:loop: -145 # if (currs >= maxs) return true -146 39/compare 3/mod/direct 2/rm32/EDX . . . 6/r32/ESI . . # compare EDX and ESI -147 7d/jump-if-greater-or-equal $slice-equal?:true/disp8 -148 # AL = *currp -149 8a/copy-byte 0/mod/indirect 3/rm32/EBX . . . 0/r32/AL . . # copy byte at *EBX to AL -150 # CL = *currs -151 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 1/r32/CL . . # copy byte at *EDX to CL -152 # if (EAX != ECX) return false -153 39/compare 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # compare EAX and ECX -154 75/jump-if-not-equal $slice-equal?:false/disp8 -155 # ++currp -156 43/increment-EBX -157 # ++currs -158 42/increment-EDX -159 eb/jump $slice-equal?:loop/disp8 -160 $slice-equal?:false: -161 b8/copy-to-EAX 0/imm32 -162 eb/jump $slice-equal?:end/disp8 -163 $slice-equal?:true: -164 b8/copy-to-EAX 1/imm32 -165 $slice-equal?:end: -166 # . restore registers -167 5e/pop-to-ESI -168 5b/pop-to-EBX -169 5a/pop-to-EDX -170 59/pop-to-ECX -171 # . epilog -172 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -173 5d/pop-to-EBP -174 c3/return -175 -176 test-slice-equal: -177 # - slice-equal?(slice("Abc"), "Abc") == 1 -178 # . prolog -179 55/push-EBP -180 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -181 # var slice/ECX -182 68/push _test-slice-data-3/imm32/end -183 68/push _test-slice-data-0/imm32/start -184 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -185 # EAX = slice-equal?(ECX, "Abc") -186 # . . push args -187 68/push "Abc"/imm32 -188 51/push-ECX -189 # . . call -190 e8/call slice-equal?/disp32 -191 # . . discard args -192 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -193 # check-ints-equal(EAX, 1, msg) -194 # . . push args -195 68/push "F - test-slice-equal"/imm32 -196 68/push 1/imm32 -197 50/push-EAX -198 # . . call -199 e8/call check-ints-equal/disp32 -200 # . . discard args -201 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -202 # . epilog -203 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -204 5d/pop-to-EBP -205 c3/return -206 -207 test-slice-equal-false: -208 # - slice-equal?(slice("bcd"), "Abc") == 0 -209 # . prolog -210 55/push-EBP -211 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -212 # var slice/ECX -213 68/push _test-slice-data-4/imm32/end -214 68/push _test-slice-data-1/imm32/start -215 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -216 # EAX = slice-equal?(ECX, "Abc") -217 # . . push args -218 68/push "Abc"/imm32 -219 51/push-ECX -220 # . . call -221 e8/call slice-equal?/disp32 -222 # . . discard args -223 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -224 # check-ints-equal(EAX, 0, msg) -225 # . . push args -226 68/push "F - test-slice-equal-false"/imm32 -227 68/push 0/imm32 -228 50/push-EAX -229 # . . call -230 e8/call check-ints-equal/disp32 -231 # . . discard args -232 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -233 # . epilog -234 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -235 5d/pop-to-EBP -236 c3/return -237 -238 test-slice-equal-too-long: -239 # - slice-equal?(slice("Abcd"), "Abc") == 0 -240 # . prolog -241 55/push-EBP -242 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -243 # var slice/ECX -244 68/push _test-slice-data-4/imm32/end -245 68/push _test-slice-data-0/imm32/start -246 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -247 # EAX = slice-equal?(ECX, "Abc") -248 # . . push args -249 68/push "Abc"/imm32 -250 51/push-ECX -251 # . . call -252 e8/call slice-equal?/disp32 -253 # . . discard args -254 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -255 # check-ints-equal(EAX, 0, msg) -256 # . . push args -257 68/push "F - test-slice-equal-too-long"/imm32 -258 68/push 0/imm32 -259 50/push-EAX -260 # . . call -261 e8/call check-ints-equal/disp32 -262 # . . discard args -263 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -264 # . epilog -265 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -266 5d/pop-to-EBP -267 c3/return -268 -269 test-slice-equal-too-short: -270 # - slice-equal?(slice("A"), "Abc") == 0 -271 # . prolog -272 55/push-EBP -273 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -274 # var slice/ECX -275 68/push _test-slice-data-1/imm32/end -276 68/push _test-slice-data-0/imm32/start -277 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -278 # EAX = slice-equal?(ECX, "Abc") -279 # . . push args -280 68/push "Abc"/imm32 -281 51/push-ECX -282 # . . call -283 e8/call slice-equal?/disp32 -284 # . . discard args -285 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -286 # check-ints-equal(EAX, 0, msg) -287 # . . push args -288 68/push "F - test-slice-equal-too-short"/imm32 -289 68/push 0/imm32 -290 50/push-EAX -291 # . . call -292 e8/call check-ints-equal/disp32 -293 # . . discard args -294 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -295 # . epilog -296 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -297 5d/pop-to-EBP -298 c3/return -299 -300 test-slice-equal-empty: -301 # - slice-equal?(slice(""), "Abc") == 0 -302 # . prolog -303 55/push-EBP -304 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -305 # var slice/ECX -306 68/push _test-slice-data-0/imm32/end -307 68/push _test-slice-data-0/imm32/start -308 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -309 # EAX = slice-equal?(ECX, "Abc") -310 # . . push args -311 68/push "Abc"/imm32 -312 51/push-ECX -313 # . . call -314 e8/call slice-equal?/disp32 -315 # . . discard args -316 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -317 # check-ints-equal(EAX, 0, msg) -318 # . . push args -319 68/push "F - test-slice-equal-empty"/imm32 -320 68/push 0/imm32 -321 50/push-EAX -322 # . . call -323 e8/call check-ints-equal/disp32 -324 # . . discard args -325 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -326 # . epilog -327 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -328 5d/pop-to-EBP -329 c3/return -330 -331 test-slice-equal-with-empty: -332 # - slice-equal?(slice("Ab"), "") == 0 -333 # . prolog -334 55/push-EBP -335 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -336 # var slice/ECX -337 68/push _test-slice-data-2/imm32/end -338 68/push _test-slice-data-0/imm32/start -339 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -340 # EAX = slice-equal?(ECX, "") -341 # . . push args -342 68/push ""/imm32 -343 51/push-ECX -344 # . . call -345 e8/call slice-equal?/disp32 -346 # . . discard args -347 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -348 # check-ints-equal(EAX, 0, msg) -349 # . . push args -350 68/push "F - test-slice-equal-with-empty"/imm32 -351 68/push 0/imm32 -352 50/push-EAX -353 # . . call -354 e8/call check-ints-equal/disp32 -355 # . . discard args -356 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -357 # . epilog -358 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -359 5d/pop-to-EBP -360 c3/return -361 -362 test-slice-equal-empty-with-empty: -363 # - slice-equal?(slice(""), "") == 1 -364 # . prolog -365 55/push-EBP -366 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -367 # var slice/ECX -368 68/push _test-slice-data-0/imm32/end -369 68/push _test-slice-data-0/imm32/start -370 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -371 # EAX = slice-equal?(ECX, "") -372 # . . push args -373 68/push ""/imm32 -374 51/push-ECX -375 # . . call -376 e8/call slice-equal?/disp32 -377 # . . discard args -378 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -379 # check-ints-equal(EAX, 1, msg) -380 # . . push args -381 68/push "F - test-slice-equal-empty-with-empty"/imm32 -382 68/push 1/imm32 -383 50/push-EAX -384 # . . call -385 e8/call check-ints-equal/disp32 -386 # . . discard args -387 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -388 # . epilog -389 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -390 5d/pop-to-EBP -391 c3/return -392 -393 write-slice: # out : (address buffered-file), s : (address slice) -394 # . prolog -395 55/push-EBP -396 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -397 # . save registers -398 50/push-EAX -399 51/push-ECX -400 52/push-EDX -401 53/push-EBX -402 56/push-ESI -403 57/push-EDI -404 # ESI = s -405 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI -406 # curr/ECX = s->start -407 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX -408 # max/ESI = s->end -409 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 6/r32/ESI 4/disp8 . # copy *(ESI+4) to ESI -410 # EDI = f -411 8b/copy 1/mod/*+disp8 5/rm32/EBP . . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI -412 # EDX = f->length -413 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 0xc/disp8 . # copy *(EDI+12) to EDX -414 # EBX = f->write -415 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 3/r32/EBX 4/disp8 . # copy *(EDI+4) to EBX -416 $write-slice:loop: -417 # if (curr >= max) break -418 39/compare 3/mod/direct 1/rm32/ECX . . . 6/r32/ESI . . # compare ECX with ESI -419 7d/jump-if-greater-or-equal $write-slice:loop-end/disp8 -420 # if (f->write >= f->length) flush and clear f's stream -421 39/compare 3/mod/direct 3/rm32/EBX . . . 2/r32/EDX . . # compare EBX with EDX -422 7c/jump-if-lesser $write-slice:to-stream/disp8 -423 # . persist f->write -424 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 3/r32/EBX 4/disp8 . # copy EBX to *(EDI+4) -425 # . flush(f) -426 # . . push args -427 57/push-EDI -428 # . . call -429 e8/call flush/disp32 -430 # . . discard args -431 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -432 # . clear-stream(stream = f+4) -433 # . . push args -434 8d/copy-address 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EDI+4 to EAX -435 50/push-EAX -436 # . . call -437 e8/call clear-stream/disp32 -438 # . . discard args -439 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -440 # . f->write must now be 0; update its cache at EBX -441 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX -442 $write-slice:to-stream: -443 # f->data[f->write] = *in -444 # . AL = *in + 10 #? e8/call test-slice-starts-with-fails/disp32 + 11 #? e8/call test-slice-starts-with-single-character/disp32 + 12 e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'. + 13 # syscall(exit, Num-test-failures) + 14 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX + 15 b8/copy-to-EAX 1/imm32/exit + 16 cd/syscall 0x80/imm8 + 17 + 18 slice-empty?: # s : (address slice) -> EAX : boolean + 19 # . prolog + 20 55/push-EBP + 21 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 22 # . save registers + 23 51/push-ECX + 24 # ECX = s + 25 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 1/r32/ECX 8/disp8 . # copy *(EBP+8) to ECX + 26 # if (s->start == s->end) return true + 27 # . EAX = s->start + 28 8b/copy 0/mod/indirect 1/rm32/ECX . . . 0/r32/EAX . . # copy *ECX to EAX + 29 # . compare EAX with s->end + 30 39/compare 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # compare EAX and *(ECX+4) + 31 b8/copy-to-EAX 1/imm32/true + 32 74/jump-if-equal $slice-empty?:end/disp8 + 33 b8/copy-to-EAX 0/imm32/false + 34 $slice-empty?:end: + 35 # . restore registers + 36 59/pop-to-ECX + 37 # . epilog + 38 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 39 5d/pop-to-EBP + 40 c3/return + 41 + 42 test-slice-empty-true: + 43 # . prolog + 44 55/push-EBP + 45 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 46 # var slice/ECX = {34, 34} + 47 68/push 34/imm32/end + 48 68/push 34/imm32/start + 49 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 50 # slice-empty?(slice) + 51 # . . push args + 52 51/push-ECX + 53 # . . call + 54 e8/call slice-empty?/disp32 + 55 # . . discard args + 56 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 57 # check-ints-equal(EAX, 1, msg) + 58 # . . push args + 59 68/push "F - test-slice-empty-true"/imm32 + 60 68/push 1/imm32 + 61 50/push-EAX + 62 # . . call + 63 e8/call check-ints-equal/disp32 + 64 # . . discard args + 65 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 66 # . epilog + 67 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 68 5d/pop-to-EBP + 69 c3/return + 70 + 71 test-slice-empty-false: + 72 # . prolog + 73 55/push-EBP + 74 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + 75 # var slice/ECX = {34, 23} + 76 68/push 23/imm32/end + 77 68/push 34/imm32/start + 78 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + 79 # slice-empty?(slice) + 80 # . . push args + 81 51/push-ECX + 82 # . . call + 83 e8/call slice-empty?/disp32 + 84 # . . discard args + 85 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + 86 # check-ints-equal(EAX, 0, msg) + 87 # . . push args + 88 68/push "F - test-slice-empty-false"/imm32 + 89 68/push 0/imm32 + 90 50/push-EAX + 91 # . . call + 92 e8/call check-ints-equal/disp32 + 93 # . . discard args + 94 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + 95 # . epilog + 96 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 97 5d/pop-to-EBP + 98 c3/return + 99 +100 slice-equal?: # s : (address slice), p : (address string) -> EAX : boolean +101 # pseudocode: +102 # currs = s->start +103 # maxs = s->end +104 # if (maxs - currs != p->length) return false +105 # currp = p->data +106 # while (currs < maxs) +107 # if (*currs != *currp) return false +108 # ++currs +109 # ++currp +110 # return true +111 # +112 # registers: +113 # currs: EDX +114 # maxs: ESI +115 # currp: EBX +116 # *currs: EAX +117 # *currp: ECX +118 # +119 # . prolog +120 55/push-EBP +121 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +122 # . save registers +123 51/push-ECX +124 52/push-EDX +125 53/push-EBX +126 56/push-ESI +127 # ESI = s +128 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +129 # currs/EDX = s->start +130 8b/copy 0/mod/indirect 6/rm32/ESI . . . 2/r32/EDX . . # copy *ESI to EDX +131 # maxs/ESI = s->end +132 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 6/r32/ESI 4/disp8 . # copy *(ESI+4) to ESI +133 # EBX = p +134 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 3/r32/EBX 0xc/disp8 . # copy *(EBP+12) to EBX +135 # EAX = maxs - currs +136 89/copy 3/mod/direct 0/rm32/EAX . . . 6/r32/ESI . . # copy ESI to EAX +137 29/subtract 3/mod/direct 0/rm32/EAX . . . 2/r32/EDX . . # subtract EDX from EAX +138 # if (EAX != p->length) return false +139 39/compare 0/mod/indirect 3/rm32/EBX . . . 0/r32/EAX . . # compare *EBX and EAX +140 75/jump-if-not-equal $slice-equal?:false/disp8 +141 # currp/EBX = p->data +142 81 0/subop/add 3/mod/direct 3/rm32/EBX . . . . . 4/imm32 # add to EBX +143 # EAX = ECX = 0 +144 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +145 31/xor 3/mod/direct 1/rm32/ECX . . . 1/r32/ECX . . # clear ECX +146 $slice-equal?:loop: +147 # if (currs >= maxs) return true +148 39/compare 3/mod/direct 2/rm32/EDX . . . 6/r32/ESI . . # compare EDX and ESI +149 7d/jump-if-greater-or-equal $slice-equal?:true/disp8 +150 # AL = *currp +151 8a/copy-byte 0/mod/indirect 3/rm32/EBX . . . 0/r32/AL . . # copy byte at *EBX to AL +152 # CL = *currs +153 8a/copy-byte 0/mod/indirect 2/rm32/EDX . . . 1/r32/CL . . # copy byte at *EDX to CL +154 # if (EAX != ECX) return false +155 39/compare 3/mod/direct 0/rm32/EAX . . . 1/r32/ECX . . # compare EAX and ECX +156 75/jump-if-not-equal $slice-equal?:false/disp8 +157 # ++currp +158 43/increment-EBX +159 # ++currs +160 42/increment-EDX +161 eb/jump $slice-equal?:loop/disp8 +162 $slice-equal?:false: +163 b8/copy-to-EAX 0/imm32 +164 eb/jump $slice-equal?:end/disp8 +165 $slice-equal?:true: +166 b8/copy-to-EAX 1/imm32 +167 $slice-equal?:end: +168 # . restore registers +169 5e/pop-to-ESI +170 5b/pop-to-EBX +171 5a/pop-to-EDX +172 59/pop-to-ECX +173 # . epilog +174 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +175 5d/pop-to-EBP +176 c3/return +177 +178 test-slice-equal: +179 # - slice-equal?(slice("Abc"), "Abc") == 1 +180 # . prolog +181 55/push-EBP +182 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +183 # var slice/ECX +184 68/push _test-slice-data-3/imm32/end +185 68/push _test-slice-data-0/imm32/start +186 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +187 # EAX = slice-equal?(ECX, "Abc") +188 # . . push args +189 68/push "Abc"/imm32 +190 51/push-ECX +191 # . . call +192 e8/call slice-equal?/disp32 +193 # . . discard args +194 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +195 # check-ints-equal(EAX, 1, msg) +196 # . . push args +197 68/push "F - test-slice-equal"/imm32 +198 68/push 1/imm32 +199 50/push-EAX +200 # . . call +201 e8/call check-ints-equal/disp32 +202 # . . discard args +203 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +204 # . epilog +205 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +206 5d/pop-to-EBP +207 c3/return +208 +209 test-slice-equal-false: +210 # - slice-equal?(slice("bcd"), "Abc") == 0 +211 # . prolog +212 55/push-EBP +213 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +214 # var slice/ECX +215 68/push _test-slice-data-4/imm32/end +216 68/push _test-slice-data-1/imm32/start +217 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +218 # EAX = slice-equal?(ECX, "Abc") +219 # . . push args +220 68/push "Abc"/imm32 +221 51/push-ECX +222 # . . call +223 e8/call slice-equal?/disp32 +224 # . . discard args +225 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +226 # check-ints-equal(EAX, 0, msg) +227 # . . push args +228 68/push "F - test-slice-equal-false"/imm32 +229 68/push 0/imm32 +230 50/push-EAX +231 # . . call +232 e8/call check-ints-equal/disp32 +233 # . . discard args +234 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +235 # . epilog +236 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +237 5d/pop-to-EBP +238 c3/return +239 +240 test-slice-equal-too-long: +241 # - slice-equal?(slice("Abcd"), "Abc") == 0 +242 # . prolog +243 55/push-EBP +244 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +245 # var slice/ECX +246 68/push _test-slice-data-4/imm32/end +247 68/push _test-slice-data-0/imm32/start +248 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +249 # EAX = slice-equal?(ECX, "Abc") +250 # . . push args +251 68/push "Abc"/imm32 +252 51/push-ECX +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 # check-ints-equal(EAX, 0, msg) +258 # . . push args +259 68/push "F - test-slice-equal-too-long"/imm32 +260 68/push 0/imm32 +261 50/push-EAX +262 # . . call +263 e8/call check-ints-equal/disp32 +264 # . . discard args +265 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +266 # . epilog +267 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +268 5d/pop-to-EBP +269 c3/return +270 +271 test-slice-equal-too-short: +272 # - slice-equal?(slice("A"), "Abc") == 0 +273 # . prolog +274 55/push-EBP +275 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +276 # var slice/ECX +277 68/push _test-slice-data-1/imm32/end +278 68/push _test-slice-data-0/imm32/start +279 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +280 # EAX = slice-equal?(ECX, "Abc") +281 # . . push args +282 68/push "Abc"/imm32 +283 51/push-ECX +284 # . . call +285 e8/call slice-equal?/disp32 +286 # . . discard args +287 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +288 # check-ints-equal(EAX, 0, msg) +289 # . . push args +290 68/push "F - test-slice-equal-too-short"/imm32 +291 68/push 0/imm32 +292 50/push-EAX +293 # . . call +294 e8/call check-ints-equal/disp32 +295 # . . discard args +296 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +297 # . epilog +298 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +299 5d/pop-to-EBP +300 c3/return +301 +302 test-slice-equal-empty: +303 # - slice-equal?(slice(""), "Abc") == 0 +304 # . prolog +305 55/push-EBP +306 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +307 # var slice/ECX +308 68/push _test-slice-data-0/imm32/end +309 68/push _test-slice-data-0/imm32/start +310 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +311 # EAX = slice-equal?(ECX, "Abc") +312 # . . push args +313 68/push "Abc"/imm32 +314 51/push-ECX +315 # . . call +316 e8/call slice-equal?/disp32 +317 # . . discard args +318 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +319 # check-ints-equal(EAX, 0, msg) +320 # . . push args +321 68/push "F - test-slice-equal-empty"/imm32 +322 68/push 0/imm32 +323 50/push-EAX +324 # . . call +325 e8/call check-ints-equal/disp32 +326 # . . discard args +327 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +328 # . epilog +329 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +330 5d/pop-to-EBP +331 c3/return +332 +333 test-slice-equal-with-empty: +334 # - slice-equal?(slice("Ab"), "") == 0 +335 # . prolog +336 55/push-EBP +337 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +338 # var slice/ECX +339 68/push _test-slice-data-2/imm32/end +340 68/push _test-slice-data-0/imm32/start +341 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +342 # EAX = slice-equal?(ECX, "") +343 # . . push args +344 68/push ""/imm32 +345 51/push-ECX +346 # . . call +347 e8/call slice-equal?/disp32 +348 # . . discard args +349 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +350 # check-ints-equal(EAX, 0, msg) +351 # . . push args +352 68/push "F - test-slice-equal-with-empty"/imm32 +353 68/push 0/imm32 +354 50/push-EAX +355 # . . call +356 e8/call check-ints-equal/disp32 +357 # . . discard args +358 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +359 # . epilog +360 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +361 5d/pop-to-EBP +362 c3/return +363 +364 test-slice-equal-empty-with-empty: +365 # - slice-equal?(slice(""), "") == 1 +366 # . prolog +367 55/push-EBP +368 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +369 # var slice/ECX +370 68/push _test-slice-data-0/imm32/end +371 68/push _test-slice-data-0/imm32/start +372 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +373 # EAX = slice-equal?(ECX, "") +374 # . . push args +375 68/push ""/imm32 +376 51/push-ECX +377 # . . call +378 e8/call slice-equal?/disp32 +379 # . . discard args +380 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +381 # check-ints-equal(EAX, 1, msg) +382 # . . push args +383 68/push "F - test-slice-equal-empty-with-empty"/imm32 +384 68/push 1/imm32 +385 50/push-EAX +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 # . epilog +391 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +392 5d/pop-to-EBP +393 c3/return +394 +395 slice-starts-with?: # s : (address slice), head : (address string) -> EAX : boolean +396 # pseudocode +397 # lenh = head->length +398 # if (lenh > s->end - s->start) return false +399 # i = 0 +400 # currs = s->start +401 # currp = head->data +402 # while i < lenh +403 # if (*currs != *currh) return false +404 # ++i +405 # ++currs +406 # ++currh +407 # return true +408 # +409 # registers: +410 # currs: ESI +411 # currh: EDI +412 # *currs: EAX +413 # *currh: EBX +414 # i: ECX +415 # lenh: EDX +416 # +417 # . prolog +418 55/push-EBP +419 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +420 # . save registers +421 51/push-ECX +422 52/push-EDX +423 53/push-EBX +424 56/push-ESI +425 57/push-EDI +426 # ESI = s +427 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI +428 # ECX = s->end - s->start +429 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX +430 2b/subtract 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # subtract *ESI from ECX +431 # EDI = head +432 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI +433 # lenh/EDX = head->length +434 8b/copy 0/mod/indirect 7/rm32/EDI . . . 2/r32/EDX . . # copy *EDI to EDX +435 # if (lenh > s->end - s->start) return false +436 39/compare 3/mod/direct 2/rm32/EDX . . . 1/r32/ECX . . # compare EDX with ECX +437 7f/jump-if-greater $slice-starts-with?:false/disp8 +438 # currs/ESI = s->start +439 8b/subtract 0/mod/indirect 6/rm32/ESI . . . 6/r32/ESI . . # copy *ESI to ESI +440 # currh/EDI = head->data +441 81 0/subop/add 3/mod/direct 7/rm32/EDI . . . . . 4/imm32 # add to EDI +442 # i/ECX = 0 +443 31/xor 3/mod/direct 1/rm32/ECX . . . 1/r32/ECX . . # clear ECX +444 # EAX = EBX = 0 445 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX -446 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL -447 # . f->data[f->write] = AL -448 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) -449 # ++f->write -450 43/increment-EBX -451 # ++in -452 41/increment-ECX -453 eb/jump $write-slice:loop/disp8 -454 $write-slice:loop-end: -455 # persist necessary variables from registers -456 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 3/r32/EBX 4/disp8 . # copy EBX to *(EDI+4) -457 $write-slice:end: -458 # . restore registers -459 5f/pop-to-EDI -460 5e/pop-to-ESI -461 5b/pop-to-EBX -462 5a/pop-to-EDX -463 59/pop-to-ECX -464 58/pop-to-EAX -465 # . epilog -466 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -467 5d/pop-to-EBP -468 c3/return -469 -470 test-write-slice: -471 # . prolog -472 55/push-EBP -473 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -474 # setup -475 # . clear-stream(_test-stream) -476 # . . push args -477 68/push _test-stream/imm32 -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 # . clear-stream(_test-buffered-file+4) -483 # . . push args -484 b8/copy-to-EAX _test-buffered-file/imm32 -485 05/add-to-EAX 4/imm32 -486 50/push-EAX -487 # . . call -488 e8/call clear-stream/disp32 -489 # . . discard args -490 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -491 # var slice/ECX = "Abc" -492 68/push _test-slice-data-3/imm32/end -493 68/push _test-slice-data-0/imm32/start -494 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -495 # write-slice(_test-buffered-file, slice) -496 # . . push args -497 51/push-ECX -498 68/push _test-buffered-file/imm32 -499 # . . call -500 e8/call write-slice/disp32 -501 # . . discard args -502 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -503 # flush(_test-buffered-file) -504 # . . push args -505 68/push _test-buffered-file/imm32 -506 # . . call -507 e8/call flush/disp32 -508 # . . discard args -509 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -510 # check-stream-equal(_test-stream, "Abc", msg) -511 # . . push args -512 68/push "F - test-write-slice"/imm32 -513 68/push "Abc"/imm32 -514 68/push _test-stream/imm32 -515 # . . call -516 e8/call check-stream-equal/disp32 -517 # . . discard args -518 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -519 # . epilog -520 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -521 5d/pop-to-EBP -522 c3/return -523 -524 # write an entire stream's contents to a buffered-file -525 # ways to do this: -526 # - construct a 'maximal slice' and pass it to write-slice -527 # - flush the buffered-file and pass the stream directly to its fd (disabling buffering) -528 # we'll go with the first way for now -529 write-stream-buffered: # f : (address buffered-file), s : (address stream) -530 # . prolog -531 55/push-EBP -532 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -533 # . save registers +446 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX +447 $slice-starts-with?:loop: +448 # if (i >= lenh) return true +449 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX +450 7d/jump-if-greater-or-equal $slice-starts-with?:true/disp8 +451 # AL = *currs +452 8a/copy-byte 0/mod/indirect 6/rm32/ESI . . . 0/r32/AL . . # copy byte at *ESI to AL +453 # BL = *currh +454 8a/copy-byte 0/mod/indirect 7/rm32/EDI . . . 3/r32/BL . . # copy byte at *EDI to BL +455 # if (*currs != *currh) return false +456 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX +457 75/jump-if-not-equal $slice-starts-with?:false/disp8 +458 # ++i +459 41/increment-ECX +460 # ++currs +461 46/increment-ESI +462 # ++currh +463 47/increment-EDI +464 eb/jump $slice-starts-with?:loop/disp8 +465 $slice-starts-with?:true: +466 b8/copy-to-EAX 1/imm32 +467 eb/jump $slice-starts-with?:end/disp8 +468 $slice-starts-with?:false: +469 b8/copy-to-EAX 0/imm32 +470 $slice-starts-with?:end: +471 # . restore registers +472 5f/pop-to-EDI +473 5e/pop-to-ESI +474 5b/pop-to-EBX +475 5a/pop-to-EDX +476 59/pop-to-ECX +477 # . epilog +478 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +479 5d/pop-to-EBP +480 c3/return +481 +482 test-slice-starts-with-single-character: +483 # - slice-starts-with?(slice("Abc"), "A") == 1 +484 # . prolog +485 55/push-EBP +486 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +487 # var slice/ECX +488 68/push _test-slice-data-3/imm32/end +489 68/push _test-slice-data-0/imm32/start +490 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +491 # EAX = slice-starts-with?(ECX, "A") +492 # . . push args +493 68/push "A"/imm32 +494 51/push-ECX +495 # . . call +496 e8/call slice-starts-with?/disp32 +497 # . . discard args +498 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +499 # check-ints-equal(EAX, 1, msg) +500 # . . push args +501 68/push "F - test-slice-starts-with-single-character"/imm32 +502 68/push 1/imm32 +503 50/push-EAX +504 # . . call +505 e8/call check-ints-equal/disp32 +506 # . . discard args +507 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +508 # . epilog +509 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +510 5d/pop-to-EBP +511 c3/return +512 +513 test-slice-starts-with-empty-string: +514 # - slice-starts-with?(slice("Abc"), "") == 1 +515 # . prolog +516 55/push-EBP +517 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +518 # var slice/ECX +519 68/push _test-slice-data-3/imm32/end +520 68/push _test-slice-data-0/imm32/start +521 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +522 # EAX = slice-starts-with?(ECX, "") +523 # . . push args +524 68/push ""/imm32 +525 51/push-ECX +526 # . . call +527 e8/call slice-starts-with?/disp32 +528 # . . discard args +529 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +530 # check-ints-equal(EAX, 1, msg) +531 # . . push args +532 68/push "F - test-slice-starts-with-empty-string"/imm32 +533 68/push 1/imm32 534 50/push-EAX -535 56/push-ESI -536 # ESI = s -537 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI -538 # var slice/ECX = {s->data, s->data + s->write} -539 # . push s->data + s->write -540 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX -541 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 -542 50/push-EAX -543 # . push s->data -544 8d/copy-address 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 0xc/disp8 . # copy ESI+12 to EAX -545 50/push-EAX -546 # . ECX = ESP -547 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX -548 # write-slice(f, slice) -549 # . . push args -550 51/push-ECX -551 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) -552 # . . call -553 e8/call write-slice/disp32 -554 # . . discard args -555 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -556 $write-stream-buffered:end: -557 # . restore registers -558 5e/pop-to-ESI -559 58/pop-to-EAX -560 # . epilog -561 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -562 5d/pop-to-EBP -563 c3/return -564 -565 test-write-stream-buffered: -566 # . prolog -567 55/push-EBP -568 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP -569 # setup -570 # . clear-stream(_test-stream) -571 # . . push args -572 68/push _test-stream/imm32 -573 # . . call -574 e8/call clear-stream/disp32 -575 # . . discard args -576 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -577 # . clear-stream(_test-buffered-file+4) -578 # . . push args -579 b8/copy-to-EAX _test-buffered-file/imm32 -580 05/add-to-EAX 4/imm32 -581 50/push-EAX -582 # . . call -583 e8/call clear-stream/disp32 -584 # . . discard args -585 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -586 # . clear-stream(_test-tmp-stream) -587 # . . push args -588 68/push _test-tmp-stream/imm32 -589 # . . call -590 e8/call clear-stream/disp32 -591 # . . discard args -592 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -593 # initialize input -594 # . write(_test-tmp-stream, "abcd") -595 # . . push args -596 68/push "abcd"/imm32 -597 68/push _test-tmp-stream/imm32 -598 # . . call -599 e8/call write/disp32 -600 # . . discard args -601 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -602 # perform the write-stream-buffered -603 # . write-stream-buffered(_test-buffered-file, _test-tmp-stream) -604 # . . push args -605 68/push _test-tmp-stream/imm32 -606 68/push _test-buffered-file/imm32 -607 # . . call -608 e8/call write-stream-buffered/disp32 -609 # . . discard args -610 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP -611 # check that the write happened as expected -612 # . flush(_test-buffered-file) -613 # . . push args -614 68/push _test-buffered-file/imm32 -615 # . . call -616 e8/call flush/disp32 -617 # . . discard args -618 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP -619 # . check-stream-equal(_test-stream, "abcd", msg) -620 # . . push args -621 68/push "F - test-write-stream-buffered"/imm32 -622 68/push "abcd"/imm32 -623 68/push _test-stream/imm32 -624 # . . call -625 e8/call check-stream-equal/disp32 -626 # . . discard args -627 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -628 # . epilog -629 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP -630 5d/pop-to-EBP -631 c3/return -632 -633 == data -634 -635 _test-slice-data-0: -636 41/A -637 _test-slice-data-1: -638 62/b -639 _test-slice-data-2: -640 63/c -641 _test-slice-data-3: -642 64/d -643 _test-slice-data-4: -644 -645 # . _. vim:nowrap:textwidth=0 +535 # . . call +536 e8/call check-ints-equal/disp32 +537 # . . discard args +538 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +539 # . epilog +540 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +541 5d/pop-to-EBP +542 c3/return +543 +544 test-slice-starts-with-multiple-characters: +545 # - slice-starts-with?(slice("Abc"), "Ab") == 1 +546 # . prolog +547 55/push-EBP +548 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +549 # var slice/ECX +550 68/push _test-slice-data-3/imm32/end +551 68/push _test-slice-data-0/imm32/start +552 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +553 # EAX = slice-starts-with?(ECX, "Ab") +554 # . . push args +555 68/push "Ab"/imm32 +556 51/push-ECX +557 # . . call +558 e8/call slice-starts-with?/disp32 +559 # . . discard args +560 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +561 # check-ints-equal(EAX, 1, msg) +562 # . . push args +563 68/push "F - test-slice-starts-with-multiple-characters"/imm32 +564 68/push 1/imm32 +565 50/push-EAX +566 # . . call +567 e8/call check-ints-equal/disp32 +568 # . . discard args +569 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +570 # . epilog +571 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +572 5d/pop-to-EBP +573 c3/return +574 +575 test-slice-starts-with-entire-string: +576 # - slice-starts-with?(slice("Abc"), "Abc") == 1 +577 # . prolog +578 55/push-EBP +579 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +580 # var slice/ECX +581 68/push _test-slice-data-3/imm32/end +582 68/push _test-slice-data-0/imm32/start +583 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +584 # EAX = slice-starts-with?(ECX, "Abc") +585 # . . push args +586 68/push "Abc"/imm32 +587 51/push-ECX +588 # . . call +589 e8/call slice-starts-with?/disp32 +590 # . . discard args +591 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +592 # check-ints-equal(EAX, 1, msg) +593 # . . push args +594 68/push "F - test-slice-starts-with-entire-string"/imm32 +595 68/push 1/imm32 +596 50/push-EAX +597 # . . call +598 e8/call check-ints-equal/disp32 +599 # . . discard args +600 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +601 # . epilog +602 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +603 5d/pop-to-EBP +604 c3/return +605 +606 test-slice-starts-with-fails: +607 # - slice-starts-with?(slice("Abc"), "Abd") == 1 +608 # . prolog +609 55/push-EBP +610 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +611 # var slice/ECX +612 68/push _test-slice-data-3/imm32/end +613 68/push _test-slice-data-0/imm32/start +614 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +615 # EAX = slice-starts-with?(ECX, "Abd") +616 # . . push args +617 68/push "Abd"/imm32 +618 51/push-ECX +619 # . . call +620 e8/call slice-starts-with?/disp32 +621 # . . discard args +622 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +623 # check-ints-equal(EAX, 0, msg) +624 # . . push args +625 68/push "F - test-slice-starts-with-fails"/imm32 +626 68/push 0/imm32 +627 50/push-EAX +628 # . . call +629 e8/call check-ints-equal/disp32 +630 # . . discard args +631 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +632 # . epilog +633 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +634 5d/pop-to-EBP +635 c3/return +636 +637 test-slice-starts-with-fails-2: +638 # - slice-starts-with?(slice("Abc"), "Ac") == 1 +639 # . prolog +640 55/push-EBP +641 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +642 # var slice/ECX +643 68/push _test-slice-data-3/imm32/end +644 68/push _test-slice-data-0/imm32/start +645 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +646 # EAX = slice-starts-with?(ECX, "Ac") +647 # . . push args +648 68/push "Ac"/imm32 +649 51/push-ECX +650 # . . call +651 e8/call slice-starts-with?/disp32 +652 # . . discard args +653 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +654 # check-ints-equal(EAX, 0, msg) +655 # . . push args +656 68/push "F - test-slice-starts-with-fails-2"/imm32 +657 68/push 0/imm32 +658 50/push-EAX +659 # . . call +660 e8/call check-ints-equal/disp32 +661 # . . discard args +662 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +663 # . epilog +664 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +665 5d/pop-to-EBP +666 c3/return +667 +668 write-slice: # out : (address buffered-file), s : (address slice) +669 # . prolog +670 55/push-EBP +671 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +672 # . save registers +673 50/push-EAX +674 51/push-ECX +675 52/push-EDX +676 53/push-EBX +677 56/push-ESI +678 57/push-EDI +679 # ESI = s +680 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI +681 # curr/ECX = s->start +682 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX +683 # max/ESI = s->end +684 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 6/r32/ESI 4/disp8 . # copy *(ESI+4) to ESI +685 # EDI = f +686 8b/copy 1/mod/*+disp8 5/rm32/EBP . . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI +687 # EDX = f->length +688 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 0xc/disp8 . # copy *(EDI+12) to EDX +689 # EBX = f->write +690 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 3/r32/EBX 4/disp8 . # copy *(EDI+4) to EBX +691 $write-slice:loop: +692 # if (curr >= max) break +693 39/compare 3/mod/direct 1/rm32/ECX . . . 6/r32/ESI . . # compare ECX with ESI +694 7d/jump-if-greater-or-equal $write-slice:loop-end/disp8 +695 # if (f->write >= f->length) flush and clear f's stream +696 39/compare 3/mod/direct 3/rm32/EBX . . . 2/r32/EDX . . # compare EBX with EDX +697 7c/jump-if-lesser $write-slice:to-stream/disp8 +698 # . persist f->write +699 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 3/r32/EBX 4/disp8 . # copy EBX to *(EDI+4) +700 # . flush(f) +701 # . . push args +702 57/push-EDI +703 # . . call +704 e8/call flush/disp32 +705 # . . discard args +706 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +707 # . clear-stream(stream = f+4) +708 # . . push args +709 8d/copy-address 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EDI+4 to EAX +710 50/push-EAX +711 # . . call +712 e8/call clear-stream/disp32 +713 # . . discard args +714 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +715 # . f->write must now be 0; update its cache at EBX +716 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX +717 $write-slice:to-stream: +718 # f->data[f->write] = *in +719 # . AL = *in +720 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +721 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +722 # . f->data[f->write] = AL +723 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) +724 # ++f->write +725 43/increment-EBX +726 # ++in +727 41/increment-ECX +728 eb/jump $write-slice:loop/disp8 +729 $write-slice:loop-end: +730 # persist necessary variables from registers +731 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 3/r32/EBX 4/disp8 . # copy EBX to *(EDI+4) +732 $write-slice:end: +733 # . restore registers +734 5f/pop-to-EDI +735 5e/pop-to-ESI +736 5b/pop-to-EBX +737 5a/pop-to-EDX +738 59/pop-to-ECX +739 58/pop-to-EAX +740 # . epilog +741 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +742 5d/pop-to-EBP +743 c3/return +744 +745 test-write-slice: +746 # . prolog +747 55/push-EBP +748 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +749 # setup +750 # . clear-stream(_test-stream) +751 # . . push args +752 68/push _test-stream/imm32 +753 # . . call +754 e8/call clear-stream/disp32 +755 # . . discard args +756 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +757 # . clear-stream(_test-buffered-file+4) +758 # . . push args +759 b8/copy-to-EAX _test-buffered-file/imm32 +760 05/add-to-EAX 4/imm32 +761 50/push-EAX +762 # . . call +763 e8/call clear-stream/disp32 +764 # . . discard args +765 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +766 # var slice/ECX = "Abc" +767 68/push _test-slice-data-3/imm32/end +768 68/push _test-slice-data-0/imm32/start +769 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +770 # write-slice(_test-buffered-file, slice) +771 # . . push args +772 51/push-ECX +773 68/push _test-buffered-file/imm32 +774 # . . call +775 e8/call write-slice/disp32 +776 # . . discard args +777 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +778 # flush(_test-buffered-file) +779 # . . push args +780 68/push _test-buffered-file/imm32 +781 # . . call +782 e8/call flush/disp32 +783 # . . discard args +784 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +785 # check-stream-equal(_test-stream, "Abc", msg) +786 # . . push args +787 68/push "F - test-write-slice"/imm32 +788 68/push "Abc"/imm32 +789 68/push _test-stream/imm32 +790 # . . call +791 e8/call check-stream-equal/disp32 +792 # . . discard args +793 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +794 # . epilog +795 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +796 5d/pop-to-EBP +797 c3/return +798 +799 # write an entire stream's contents to a buffered-file +800 # ways to do this: +801 # - construct a 'maximal slice' and pass it to write-slice +802 # - flush the buffered-file and pass the stream directly to its fd (disabling buffering) +803 # we'll go with the first way for now +804 write-stream-buffered: # f : (address buffered-file), s : (address stream) +805 # . prolog +806 55/push-EBP +807 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +808 # . save registers +809 50/push-EAX +810 56/push-ESI +811 # ESI = s +812 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI +813 # var slice/ECX = {s->data, s->data + s->write} +814 # . push s->data + s->write +815 8b/copy 0/mod/indirect 6/rm32/ESI . . . 0/r32/EAX . . # copy *ESI to EAX +816 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 +817 50/push-EAX +818 # . push s->data +819 8d/copy-address 1/mod/*+disp8 6/rm32/ESI . . . 0/r32/EAX 0xc/disp8 . # copy ESI+12 to EAX +820 50/push-EAX +821 # . ECX = ESP +822 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +823 # write-slice(f, slice) +824 # . . push args +825 51/push-ECX +826 ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 8/disp8 . # push *(EBP+8) +827 # . . call +828 e8/call write-slice/disp32 +829 # . . discard args +830 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +831 $write-stream-buffered:end: +832 # . restore registers +833 5e/pop-to-ESI +834 58/pop-to-EAX +835 # . epilog +836 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +837 5d/pop-to-EBP +838 c3/return +839 +840 test-write-stream-buffered: +841 # . prolog +842 55/push-EBP +843 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +844 # setup +845 # . clear-stream(_test-stream) +846 # . . push args +847 68/push _test-stream/imm32 +848 # . . call +849 e8/call clear-stream/disp32 +850 # . . discard args +851 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +852 # . clear-stream(_test-buffered-file+4) +853 # . . push args +854 b8/copy-to-EAX _test-buffered-file/imm32 +855 05/add-to-EAX 4/imm32 +856 50/push-EAX +857 # . . call +858 e8/call clear-stream/disp32 +859 # . . discard args +860 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +861 # . clear-stream(_test-tmp-stream) +862 # . . push args +863 68/push _test-tmp-stream/imm32 +864 # . . call +865 e8/call clear-stream/disp32 +866 # . . discard args +867 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +868 # initialize input +869 # . write(_test-tmp-stream, "abcd") +870 # . . push args +871 68/push "abcd"/imm32 +872 68/push _test-tmp-stream/imm32 +873 # . . call +874 e8/call write/disp32 +875 # . . discard args +876 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +877 # perform the write-stream-buffered +878 # . write-stream-buffered(_test-buffered-file, _test-tmp-stream) +879 # . . push args +880 68/push _test-tmp-stream/imm32 +881 68/push _test-buffered-file/imm32 +882 # . . call +883 e8/call write-stream-buffered/disp32 +884 # . . discard args +885 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +886 # check that the write happened as expected +887 # . flush(_test-buffered-file) +888 # . . push args +889 68/push _test-buffered-file/imm32 +890 # . . call +891 e8/call flush/disp32 +892 # . . discard args +893 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +894 # . check-stream-equal(_test-stream, "abcd", msg) +895 # . . push args +896 68/push "F - test-write-stream-buffered"/imm32 +897 68/push "abcd"/imm32 +898 68/push _test-stream/imm32 +899 # . . call +900 e8/call check-stream-equal/disp32 +901 # . . discard args +902 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +903 # . epilog +904 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP +905 5d/pop-to-EBP +906 c3/return +907 +908 == data +909 +910 _test-slice-data-0: +911 41/A +912 _test-slice-data-1: +913 62/b +914 _test-slice-data-2: +915 63/c +916 _test-slice-data-3: +917 64/d +918 _test-slice-data-4: +919 +920 # . _. vim:nowrap:textwidth=0 diff --git a/subx/072slice.subx b/subx/072slice.subx index 99c3d459..54049b6d 100644 --- a/subx/072slice.subx +++ b/subx/072slice.subx @@ -7,6 +7,8 @@ # . 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 # main: +#? e8/call test-slice-starts-with-fails/disp32 +#? e8/call test-slice-starts-with-single-character/disp32 e8/call run-tests/disp32 # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'. # syscall(exit, Num-test-failures) 8b/copy 0/mod/indirect 5/rm32/.disp32 . . 3/r32/EBX Num-test-failures/disp32 # copy *Num-test-failures to EBX @@ -390,6 +392,279 @@ test-slice-equal-empty-with-empty: 5d/pop-to-EBP c3/return +slice-starts-with?: # s : (address slice), head : (address string) -> EAX : boolean + # pseudocode + # lenh = head->length + # if (lenh > s->end - s->start) return false + # i = 0 + # currs = s->start + # currp = head->data + # while i < lenh + # if (*currs != *currh) return false + # ++i + # ++currs + # ++currh + # return true + # + # registers: + # currs: ESI + # currh: EDI + # *currs: EAX + # *currh: EBX + # i: ECX + # lenh: EDX + # + # . prolog + 55/push-EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # . save registers + 51/push-ECX + 52/push-EDX + 53/push-EBX + 56/push-ESI + 57/push-EDI + # ESI = s + 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI + # ECX = s->end - s->start + 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 4/disp8 . # copy *(ESI+4) to ECX + 2b/subtract 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # subtract *ESI from ECX + # EDI = head + 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 7/r32/EDI 0xc/disp8 . # copy *(EBP+12) to EDI + # lenh/EDX = head->length + 8b/copy 0/mod/indirect 7/rm32/EDI . . . 2/r32/EDX . . # copy *EDI to EDX + # if (lenh > s->end - s->start) return false + 39/compare 3/mod/direct 2/rm32/EDX . . . 1/r32/ECX . . # compare EDX with ECX + 7f/jump-if-greater $slice-starts-with?:false/disp8 + # currs/ESI = s->start + 8b/subtract 0/mod/indirect 6/rm32/ESI . . . 6/r32/ESI . . # copy *ESI to ESI + # currh/EDI = head->data + 81 0/subop/add 3/mod/direct 7/rm32/EDI . . . . . 4/imm32 # add to EDI + # i/ECX = 0 + 31/xor 3/mod/direct 1/rm32/ECX . . . 1/r32/ECX . . # clear ECX + # EAX = EBX = 0 + 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX + 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX +$slice-starts-with?:loop: + # if (i >= lenh) return true + 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX + 7d/jump-if-greater-or-equal $slice-starts-with?:true/disp8 + # AL = *currs + 8a/copy-byte 0/mod/indirect 6/rm32/ESI . . . 0/r32/AL . . # copy byte at *ESI to AL + # BL = *currh + 8a/copy-byte 0/mod/indirect 7/rm32/EDI . . . 3/r32/BL . . # copy byte at *EDI to BL + # if (*currs != *currh) return false + 39/compare 3/mod/direct 0/rm32/EAX . . . 3/r32/EBX . . # compare EAX and EBX + 75/jump-if-not-equal $slice-starts-with?:false/disp8 + # ++i + 41/increment-ECX + # ++currs + 46/increment-ESI + # ++currh + 47/increment-EDI + eb/jump $slice-starts-with?:loop/disp8 +$slice-starts-with?:true: + b8/copy-to-EAX 1/imm32 + eb/jump $slice-starts-with?:end/disp8 +$slice-starts-with?:false: + b8/copy-to-EAX 0/imm32 +$slice-starts-with?:end: + # . restore registers + 5f/pop-to-EDI + 5e/pop-to-ESI + 5b/pop-to-EBX + 5a/pop-to-EDX + 59/pop-to-ECX + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +test-slice-starts-with-single-character: + # - slice-starts-with?(slice("Abc"), "A") == 1 + # . prolog + 55/push-EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # var slice/ECX + 68/push _test-slice-data-3/imm32/end + 68/push _test-slice-data-0/imm32/start + 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + # EAX = slice-starts-with?(ECX, "A") + # . . push args + 68/push "A"/imm32 + 51/push-ECX + # . . call + e8/call slice-starts-with?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # check-ints-equal(EAX, 1, msg) + # . . push args + 68/push "F - test-slice-starts-with-single-character"/imm32 + 68/push 1/imm32 + 50/push-EAX + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +test-slice-starts-with-empty-string: + # - slice-starts-with?(slice("Abc"), "") == 1 + # . prolog + 55/push-EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # var slice/ECX + 68/push _test-slice-data-3/imm32/end + 68/push _test-slice-data-0/imm32/start + 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + # EAX = slice-starts-with?(ECX, "") + # . . push args + 68/push ""/imm32 + 51/push-ECX + # . . call + e8/call slice-starts-with?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # check-ints-equal(EAX, 1, msg) + # . . push args + 68/push "F - test-slice-starts-with-empty-string"/imm32 + 68/push 1/imm32 + 50/push-EAX + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +test-slice-starts-with-multiple-characters: + # - slice-starts-with?(slice("Abc"), "Ab") == 1 + # . prolog + 55/push-EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # var slice/ECX + 68/push _test-slice-data-3/imm32/end + 68/push _test-slice-data-0/imm32/start + 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + # EAX = slice-starts-with?(ECX, "Ab") + # . . push args + 68/push "Ab"/imm32 + 51/push-ECX + # . . call + e8/call slice-starts-with?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # check-ints-equal(EAX, 1, msg) + # . . push args + 68/push "F - test-slice-starts-with-multiple-characters"/imm32 + 68/push 1/imm32 + 50/push-EAX + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +test-slice-starts-with-entire-string: + # - slice-starts-with?(slice("Abc"), "Abc") == 1 + # . prolog + 55/push-EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # var slice/ECX + 68/push _test-slice-data-3/imm32/end + 68/push _test-slice-data-0/imm32/start + 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + # EAX = slice-starts-with?(ECX, "Abc") + # . . push args + 68/push "Abc"/imm32 + 51/push-ECX + # . . call + e8/call slice-starts-with?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # check-ints-equal(EAX, 1, msg) + # . . push args + 68/push "F - test-slice-starts-with-entire-string"/imm32 + 68/push 1/imm32 + 50/push-EAX + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +test-slice-starts-with-fails: + # - slice-starts-with?(slice("Abc"), "Abd") == 1 + # . prolog + 55/push-EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # var slice/ECX + 68/push _test-slice-data-3/imm32/end + 68/push _test-slice-data-0/imm32/start + 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + # EAX = slice-starts-with?(ECX, "Abd") + # . . push args + 68/push "Abd"/imm32 + 51/push-ECX + # . . call + e8/call slice-starts-with?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # check-ints-equal(EAX, 0, msg) + # . . push args + 68/push "F - test-slice-starts-with-fails"/imm32 + 68/push 0/imm32 + 50/push-EAX + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +test-slice-starts-with-fails-2: + # - slice-starts-with?(slice("Abc"), "Ac") == 1 + # . prolog + 55/push-EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # var slice/ECX + 68/push _test-slice-data-3/imm32/end + 68/push _test-slice-data-0/imm32/start + 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + # EAX = slice-starts-with?(ECX, "Ac") + # . . push args + 68/push "Ac"/imm32 + 51/push-ECX + # . . call + e8/call slice-starts-with?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # check-ints-equal(EAX, 0, msg) + # . . push args + 68/push "F - test-slice-starts-with-fails-2"/imm32 + 68/push 0/imm32 + 50/push-EAX + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + write-slice: # out : (address buffered-file), s : (address slice) # . prolog 55/push-EBP diff --git a/subx/apps/crenshaw2-1 b/subx/apps/crenshaw2-1 index 379faac3..99d08ba4 100755 Binary files a/subx/apps/crenshaw2-1 and b/subx/apps/crenshaw2-1 differ diff --git a/subx/apps/crenshaw2-1b b/subx/apps/crenshaw2-1b index f610d4e5..ae66b7b4 100755 Binary files a/subx/apps/crenshaw2-1b and b/subx/apps/crenshaw2-1b differ diff --git a/subx/apps/factorial b/subx/apps/factorial index 9ef920f4..90193370 100755 Binary files a/subx/apps/factorial and b/subx/apps/factorial differ diff --git a/subx/apps/handle b/subx/apps/handle index 4ffd3ea1..5708c864 100755 Binary files a/subx/apps/handle and b/subx/apps/handle differ diff --git a/subx/apps/hex b/subx/apps/hex index d792de05..dcc77d5c 100755 Binary files a/subx/apps/hex and b/subx/apps/hex differ diff --git a/subx/apps/pack b/subx/apps/pack index 665e969c..b4d04abe 100755 Binary files a/subx/apps/pack and b/subx/apps/pack differ -- cgit 1.4.1-2-gfad0