From 3f97166cf7360c1b8f607ba37bb350790e83101d Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Mon, 14 Jan 2019 17:29:10 -0800 Subject: 4927 --- html/subx/069slice.subx.html | 187 ++++++++++++++++++++++++++++++++++++------- subx/069slice.subx | 133 ++++++++++++++++++++++++++++++ subx/apps/crenshaw2-1 | Bin 13826 -> 14065 bytes subx/apps/crenshaw2-1b | Bin 14385 -> 14624 bytes subx/apps/factorial | Bin 12744 -> 12983 bytes subx/apps/handle | Bin 13537 -> 13776 bytes subx/apps/hex | Bin 16805 -> 17044 bytes subx/apps/pack.subx | 25 +++--- 8 files changed, 306 insertions(+), 39 deletions(-) diff --git a/html/subx/069slice.subx.html b/html/subx/069slice.subx.html index 498d891a..65930bd3 100644 --- a/html/subx/069slice.subx.html +++ b/html/subx/069slice.subx.html @@ -223,8 +223,8 @@ if ('onhashchange' in window) { 161 55/push-EBP 162 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 163 # var slice/ECX -164 68/push _test-slice-data-3/imm32/end -165 68/push _test-slice-data-0/imm32/start +164 68/push _test-slice-data-3/imm32/end +165 68/push _test-slice-data-0/imm32/start 166 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX 167 # EAX = slice-equal?(ECX, "Abc") 168 # . . push args @@ -254,8 +254,8 @@ if ('onhashchange' in window) { 192 55/push-EBP 193 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 194 # var slice/ECX -195 68/push _test-slice-data-4/imm32/end -196 68/push _test-slice-data-1/imm32/start +195 68/push _test-slice-data-4/imm32/end +196 68/push _test-slice-data-1/imm32/start 197 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX 198 # EAX = slice-equal?(ECX, "Abc") 199 # . . push args @@ -285,8 +285,8 @@ if ('onhashchange' in window) { 223 55/push-EBP 224 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 225 # var slice/ECX -226 68/push _test-slice-data-4/imm32/end -227 68/push _test-slice-data-0/imm32/start +226 68/push _test-slice-data-4/imm32/end +227 68/push _test-slice-data-0/imm32/start 228 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX 229 # EAX = slice-equal?(ECX, "Abc") 230 # . . push args @@ -316,8 +316,8 @@ if ('onhashchange' in window) { 254 55/push-EBP 255 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 256 # var slice/ECX -257 68/push _test-slice-data-1/imm32/end -258 68/push _test-slice-data-0/imm32/start +257 68/push _test-slice-data-1/imm32/end +258 68/push _test-slice-data-0/imm32/start 259 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX 260 # EAX = slice-equal?(ECX, "Abc") 261 # . . push args @@ -347,8 +347,8 @@ if ('onhashchange' in window) { 285 55/push-EBP 286 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 287 # var slice/ECX -288 68/push _test-slice-data-0/imm32/end -289 68/push _test-slice-data-0/imm32/start +288 68/push _test-slice-data-0/imm32/end +289 68/push _test-slice-data-0/imm32/start 290 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX 291 # EAX = slice-equal?(ECX, "Abc") 292 # . . push args @@ -378,8 +378,8 @@ if ('onhashchange' in window) { 316 55/push-EBP 317 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 318 # var slice/ECX -319 68/push _test-slice-data-2/imm32/end -320 68/push _test-slice-data-0/imm32/start +319 68/push _test-slice-data-2/imm32/end +320 68/push _test-slice-data-0/imm32/start 321 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX 322 # EAX = slice-equal?(ECX, "") 323 # . . push args @@ -409,8 +409,8 @@ if ('onhashchange' in window) { 347 55/push-EBP 348 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP 349 # var slice/ECX -350 68/push _test-slice-data-0/imm32/end -351 68/push _test-slice-data-0/imm32/start +350 68/push _test-slice-data-0/imm32/end +351 68/push _test-slice-data-0/imm32/start 352 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX 353 # EAX = slice-equal?(ECX, "") 354 # . . push args @@ -434,19 +434,152 @@ if ('onhashchange' in window) { 372 5d/pop-to-EBP 373 c3/return 374 -375 == data -376 -377 _test-slice-data-0: -378 41/A -379 _test-slice-data-1: -380 62/b -381 _test-slice-data-2: -382 63/c -383 _test-slice-data-3: -384 64/d -385 _test-slice-data-4: -386 -387 # . _. vim:nowrap:textwidth=0 +375 write-slice: # out : (address buffered-file), s : (address slice) +376 # . prolog +377 55/push-EBP +378 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +379 # . save registers +380 50/push-EAX +381 51/push-ECX +382 52/push-EDX +383 53/push-EBX +384 56/push-ESI +385 57/push-EDI +386 # ESI = s +387 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 0xc/disp8 . # copy *(EBP+12) to ESI +388 # curr/ECX = s->start +389 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX +390 # max/ESI = s->end +391 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 6/r32/ESI 4/disp8 . # copy *(ESI+4) to ESI +392 # EDI = f +393 8b/copy 1/mod/*+disp8 5/rm32/EBP . . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI +394 # EDX = f->length +395 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 0xc/disp8 . # copy *(EDI+12) to EDX +396 # EBX = f->write +397 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 3/r32/EBX 4/disp8 . # copy *(EDI+4) to EBX +398 $write-slice:loop: +399 # if (curr >= max) break +400 39/compare 3/mod/direct 1/rm32/ECX . . . 6/r32/ESI . . # compare ECX with ESI +401 7d/jump-if-greater-or-equal $write-slice:loop-end/disp8 +402 # if (f->write >= f->length) flush and clear f's stream +403 39/compare 3/mod/direct 3/rm32/EBX . . . 2/r32/EDX . . # compare EBX with EDX +404 7c/jump-if-lesser $write-slice:to-stream/disp8 +405 # . persist f->write +406 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 3/r32/EBX 4/disp8 . # copy EBX to *(EDI+4) +407 # . flush(f) +408 # . . push args +409 57/push-EDI +410 # . . call +411 e8/call flush/disp32 +412 # . . discard args +413 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +414 # . clear-stream(stream = f+4) +415 # . . push args +416 8d/copy-address 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EDI+4 to EAX +417 50/push-EAX +418 # . . call +419 e8/call clear-stream/disp32 +420 # . . discard args +421 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +422 # . f->write must now be 0; update its cache at EBX +423 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX +424 $write-slice:to-stream: +425 # f->data[f->write] = *in +426 # . AL = *in +427 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX +428 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL +429 # . f->data[f->write] = AL +430 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) +431 # ++f->write +432 43/increment-EBX +433 # ++in +434 41/increment-ECX +435 eb/jump $write-slice:loop/disp8 +436 $write-slice:loop-end: +437 # persist necessary variables from registers +438 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 3/r32/EBX 4/disp8 . # copy EBX to *(EDI+4) +439 $write-slice:end: +440 # . restore registers +441 5f/pop-to-EDI +442 5e/pop-to-ESI +443 5b/pop-to-EBX +444 5a/pop-to-EDX +445 59/pop-to-ECX +446 58/pop-to-EAX +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-write-slice: +453 # . prolog +454 55/push-EBP +455 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP +456 # setup +457 # . clear-stream(_test-stream) +458 # . . push args +459 68/push _test-stream/imm32 +460 # . . call +461 e8/call clear-stream/disp32 +462 # . . discard args +463 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +464 # . clear-stream(_test-buffered-file+4) +465 # . . push args +466 b8/copy-to-EAX _test-buffered-file/imm32 +467 05/add-to-EAX 4/imm32 +468 50/push-EAX +469 # . . call +470 e8/call clear-stream/disp32 +471 # . . discard args +472 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +473 # var slice/ECX = "Abc" +474 68/push _test-slice-data-3/imm32/end +475 68/push _test-slice-data-0/imm32/start +476 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX +477 # write-slice(_test-buffered-file, slice) +478 # . . push args +479 51/push-ECX +480 68/push _test-buffered-file/imm32 +481 # . . call +482 e8/call write-slice/disp32 +483 # . . discard args +484 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP +485 # flush(_test-buffered-file) +486 # . . push args +487 68/push _test-buffered-file/imm32 +488 # . . call +489 e8/call flush/disp32 +490 # . . discard args +491 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP +492 # check-ints-equal(*_test-stream->data, "Abc", msg) +493 # . . push args +494 68/push "F - test-write-slice"/imm32 +495 68/push 0x636241/imm32 +496 # . . push *_test-stream->data +497 b8/copy-to-EAX _test-stream/imm32 +498 ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) +499 # . . call +500 e8/call check-ints-equal/disp32 +501 # . . discard args +502 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +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 == data +509 +510 _test-slice-data-0: +511 41/A +512 _test-slice-data-1: +513 62/b +514 _test-slice-data-2: +515 63/c +516 _test-slice-data-3: +517 64/d +518 _test-slice-data-4: +519 +520 # . _. vim:nowrap:textwidth=0 diff --git a/subx/069slice.subx b/subx/069slice.subx index a652ed4d..7be920ec 100644 --- a/subx/069slice.subx +++ b/subx/069slice.subx @@ -372,6 +372,139 @@ test-slice-equal-empty-with-empty: 5d/pop-to-EBP c3/return +write-slice: # out : (address buffered-file), s : (address slice) + # . prolog + 55/push-EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # . save registers + 50/push-EAX + 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 0xc/disp8 . # copy *(EBP+12) to ESI + # curr/ECX = s->start + 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX + # max/ESI = s->end + 8b/copy 1/mod/*+disp8 6/rm32/ESI . . . 6/r32/ESI 4/disp8 . # copy *(ESI+4) to ESI + # EDI = f + 8b/copy 1/mod/*+disp8 5/rm32/EBP . . 7/r32/EDI 8/disp8 . # copy *(EBP+8) to EDI + # EDX = f->length + 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 2/r32/EDX 0xc/disp8 . # copy *(EDI+12) to EDX + # EBX = f->write + 8b/copy 1/mod/*+disp8 7/rm32/EDI . . . 3/r32/EBX 4/disp8 . # copy *(EDI+4) to EBX +$write-slice:loop: + # if (curr >= max) break + 39/compare 3/mod/direct 1/rm32/ECX . . . 6/r32/ESI . . # compare ECX with ESI + 7d/jump-if-greater-or-equal $write-slice:loop-end/disp8 + # if (f->write >= f->length) flush and clear f's stream + 39/compare 3/mod/direct 3/rm32/EBX . . . 2/r32/EDX . . # compare EBX with EDX + 7c/jump-if-lesser $write-slice:to-stream/disp8 + # . persist f->write + 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 3/r32/EBX 4/disp8 . # copy EBX to *(EDI+4) + # . flush(f) + # . . push args + 57/push-EDI + # . . call + e8/call flush/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # . clear-stream(stream = f+4) + # . . push args + 8d/copy-address 1/mod/*+disp8 7/rm32/EDI . . . 0/r32/EAX 4/disp8 . # copy EDI+4 to EAX + 50/push-EAX + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # . f->write must now be 0; update its cache at EBX + 31/xor 3/mod/direct 3/rm32/EBX . . . 3/r32/EBX . . # clear EBX +$write-slice:to-stream: + # f->data[f->write] = *in + # . AL = *in + 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX + 8a/copy-byte 0/mod/indirect 1/rm32/ECX . . . 0/r32/AL . . # copy byte at *ECX to AL + # . f->data[f->write] = AL + 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) + # ++f->write + 43/increment-EBX + # ++in + 41/increment-ECX + eb/jump $write-slice:loop/disp8 +$write-slice:loop-end: + # persist necessary variables from registers + 89/copy 1/mod/*+disp8 7/rm32/EDI . . . 3/r32/EBX 4/disp8 . # copy EBX to *(EDI+4) +$write-slice:end: + # . restore registers + 5f/pop-to-EDI + 5e/pop-to-ESI + 5b/pop-to-EBX + 5a/pop-to-EDX + 59/pop-to-ECX + 58/pop-to-EAX + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + +test-write-slice: + # . prolog + 55/push-EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # setup + # . clear-stream(_test-stream) + # . . push args + 68/push _test-stream/imm32 + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # . clear-stream(_test-buffered-file+4) + # . . push args + b8/copy-to-EAX _test-buffered-file/imm32 + 05/add-to-EAX 4/imm32 + 50/push-EAX + # . . call + e8/call clear-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # var slice/ECX = "Abc" + 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 + # write-slice(_test-buffered-file, slice) + # . . push args + 51/push-ECX + 68/push _test-buffered-file/imm32 + # . . call + e8/call write-slice/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # flush(_test-buffered-file) + # . . push args + 68/push _test-buffered-file/imm32 + # . . call + e8/call flush/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 4/imm32 # add to ESP + # check-ints-equal(*_test-stream->data, "Abc", msg) + # . . push args + 68/push "F - test-write-slice"/imm32 + 68/push 0x636241/imm32 + # . . push *_test-stream->data + b8/copy-to-EAX _test-stream/imm32 + ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 0xc/disp8 . # push *(EAX+12) + # . . 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 + == data _test-slice-data-0: diff --git a/subx/apps/crenshaw2-1 b/subx/apps/crenshaw2-1 index 525d4983..614fa178 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 2b040406..633bc760 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 924ce4bc..0126f320 100755 Binary files a/subx/apps/factorial and b/subx/apps/factorial differ diff --git a/subx/apps/handle b/subx/apps/handle index 5cbed69e..b2b4b70c 100755 Binary files a/subx/apps/handle and b/subx/apps/handle differ diff --git a/subx/apps/hex b/subx/apps/hex index 2cca804f..1ef41c17 100755 Binary files a/subx/apps/hex and b/subx/apps/hex differ diff --git a/subx/apps/pack.subx b/subx/apps/pack.subx index b2b7a32a..5cd693b8 100644 --- a/subx/apps/pack.subx +++ b/subx/apps/pack.subx @@ -78,28 +78,28 @@ $main:end: # - To pack an instruction, following the C++ version: # read line # parse words -# read first word as opcode and emit -# if 0f or f2 or f3 read second opcode and emit -# if 'f2 0f' or 'f3 0f' read third opcode and emit +# read first word as opcode and write-slice +# if 0f or f2 or f3 read second opcode and write-slice +# if 'f2 0f' or 'f3 0f' read third opcode and write-slice # scan words # if has metadata 'mod', parse into mod # if has metadata 'rm32', parse into rm32 # if has metadata 'r32', parse into r32 # if has metadata 'subop', parse into r32 -# if at least one of the 3 was present, emit modrm byte +# if at least one of the 3 was present, print-byte # scan words # if has metadata 'base', parse into base # if has metadata 'index', parse into index # if has metadata 'scale', parse into scale -# if at least one of the 3 was present, emit sib byte +# if at least one of the 3 was present, print-byte # parse errors => # scan words -# if has metadata 'disp8', emit-maybe -# if has metadata 'disp16', emit-maybe as 2 bytes -# if has metadata 'disp32', emit-maybe as 4 bytes +# if has metadata 'disp8', emit as 1 byte +# if has metadata 'disp16', emit as 2 bytes +# if has metadata 'disp32', emit as 4 bytes # scan words -# if has metadata 'imm8', emit-maybe -# if has metadata 'imm32', emit-maybe as 4 bytes +# if has metadata 'imm8', emit +# if has metadata 'imm32', emit as 4 bytes # finally, emit line prefixed with a ' # ' # simplifications since we perform zero error handling (continuing to rely on the C++ version for that): @@ -121,8 +121,9 @@ $main:end: # slice-equal?(slice, kernel string) # helpers: -# emit-maybe(out : &buffered-file, n : int, width : int) -# emit(out : &buffered-file, word : &slice) +# emit(out : &buffered-file, word : &slice, width : int) +# if slice is all hex digits, parse and print appropriate digits +# otherwise just write-slice # has-metadata?(word : &slice, s : &kernel-string) -> bool convert: # in : (address buffered-file), out : (address buffered-file), err : (address buffered-file), ed : (address exit-descriptor) -> -- cgit 1.4.1-2-gfad0