From 7c575de40da307ccb676c6aafb433f40ecafde41 Mon Sep 17 00:00:00 2001 From: Kartik Agaram Date: Sun, 26 May 2019 10:46:26 -0700 Subject: . --- subx/apps/assort | Bin 24109 -> 24100 bytes subx/apps/assort.subx | 279 +-------------------------------------------- subx/apps/pack | Bin 38948 -> 39782 bytes subx/apps/subx-common.subx | 274 ++++++++++++++++++++++++++++++++++++++++++++ subx/apps/survey | Bin 19668 -> 21901 bytes subx/apps/survey.subx | 110 ------------------ 6 files changed, 278 insertions(+), 385 deletions(-) (limited to 'subx') diff --git a/subx/apps/assort b/subx/apps/assort index c6a8840c..e9228e59 100755 Binary files a/subx/apps/assort and b/subx/apps/assort differ diff --git a/subx/apps/assort.subx b/subx/apps/assort.subx index 4a23fdbd..14956d82 100644 --- a/subx/apps/assort.subx +++ b/subx/apps/assort.subx @@ -453,7 +453,7 @@ read-segments: # in : (address buffered-file), table : (address stream {string, # continue # if slice-equal?(word-slice, "==") # var segment-name = next-word(line) - # curr-segment = get-or-insert-segment(table, segment-name, Segment-size) + # curr-segment = get-or-insert-stream(table, segment-name, Segment-size) # if curr-segment->write == 0 # rewind-stream(line) # write-stream(curr-segment, line) @@ -611,7 +611,7 @@ $read-segments:check-for-segment-header: #? # }}} # if slice-equal?(word-slice, "==") # segment-name = next-word(line) - # curr-segment = get-or-insert(table, segment-name) + # curr-segment = get-or-insert-stream(table, segment-name) # if (curr-segment->write > 0) continue # . EAX = slice-equal?(word-slice, "==") # . . push args @@ -674,13 +674,13 @@ $read-segments:check-for-segment-header: #? # . . discard args #? 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP #? # }}} - # . EAX = get-or-insert-segment(table, segment-name, Segment-size) + # . EAX = get-or-insert-stream(table, segment-name, Segment-size) # . . push args ff 6/subop/push 0/mod/indirect 5/rm32/.disp32 . . . Segment-size/disp32 # push *Segment-size 52/push-EDX ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) # . . call - e8/call get-or-insert-segment/disp32 + e8/call get-or-insert-stream/disp32 # . . discard args 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP # . curr-segment = EAX @@ -786,269 +786,6 @@ $write-segments:end: ## helpers -# TODO: pass in an allocation descriptor -get-or-insert-segment: # table : (address stream {string, (address stream byte)}), s : (address slice), n : int -> EAX : (address stream) - # pseudocode: - # curr = table->data - # max = &table->data[table->write] - # while curr < max - # if slice-equal?(s, *curr) - # return *(curr+4) - # curr += 8 - # if table->write < table->length - # *max = slice-to-string(Heap, s) - # result = new-stream(Heap, n, 1) - # *(max+4) = result - # table->write += 8 - # return result - # return 0 - # - # . 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 - 56/push-ESI - # ESI = table - 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI - # curr/ECX = table->data - 8d/copy-address 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 0xc/disp8 . # copy ESI+12 to ECX - # max/EDX = table->data + table->write - 8b/copy 0/mod/indirect 6/rm32/ESI . . . 2/r32/EDX . . # copy *ESI to EDX - 8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ECX 2/index/EDX . 2/r32/EDX . . # copy ECX+EDX to EDX -$get-or-insert-segment:search-loop: - # if (curr >= max) break - 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX - 7d/jump-if-greater-or-equal $get-or-insert-segment:not-found/disp8 - # if (slice-equal?(s, *curr)) return *(curr+4) - # . EAX = slice-equal?(s, *curr) - # . . push args - ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX - ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - # . . call - e8/call slice-equal?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - # . if (EAX != 0) return EAX = *(curr+4) - 3d/compare-EAX-and 0/imm32 - 74/jump-if-equal $get-or-insert-segment:mismatch/disp8 - 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX - eb/jump $get-or-insert-segment:end/disp8 -$get-or-insert-segment:mismatch: - # curr += 8 - 81 0/subop/add 3/mod/direct 1/rm32/ECX . . . . . 8/imm32 # add to ECX - # loop - eb/jump $get-or-insert-segment:search-loop/disp8 -$get-or-insert-segment:not-found: - # result/EAX = 0 - 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX - # if (table->write >= table->length) abort - 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX - 3b/compare 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 8/disp8 . # compare ECX with *(ESI+8) - 7d/jump-if-greater-or-equal $get-or-insert-segment:abort/disp8 - # *max = slice-to-string(Heap, s) - # . EAX = slice-to-string(Heap, s) - # . . push args - ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 68/push Heap/imm32 - # . . call - e8/call slice-to-string/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - # . *max = EAX - 89/copy 0/mod/indirect 2/rm32/EDX . . . 0/r32/EAX . . # copy EAX to *EDX - # result/EAX = new-stream(Heap, n, 1) - # . . push args - 68/push 1/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) - 68/push Heap/imm32 - # . . call - e8/call new-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - # *(max+4) = result - 89/copy 1/mod/*+disp8 2/rm32/EDX . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDX+4) - # table->write += 8 - 81 0/subop/add 0/mod/indirect 6/rm32/ESI . . . . . 8/imm32 # add to *ESI -$get-or-insert-segment:end: - # . restore registers - 5e/pop-to-ESI - 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 - -$get-or-insert-segment:abort: - # . _write(2/stderr, error) - # . . push args - 68/push "get-or-insert-segment: too many segments"/imm32 - 68/push 2/imm32/stderr - # . . call - e8/call _write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - # . syscall(exit, 1) - bb/copy-to-EBX 1/imm32 - b8/copy-to-EAX 1/imm32/exit - cd/syscall 0x80/imm8 - # never gets here - -test-get-or-insert-segment: - # . prolog - 55/push-EBP - 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP - # var table/ECX : (address stream byte) = stream(2 * 8) - 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # subtract from ESP - 68/push 0x10/imm32/length - 68/push 0/imm32/read - 68/push 0/imm32/write - 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX - # EDX : (address slice) = "code" - 68/push _test-code-segment-end/imm32/end - 68/push _test-code-segment/imm32/start - 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX -$test-get-or-insert-segment:first-call: - # - start with an empty table, insert one segment, verify that it was inserted - # segment/EAX = get-or-insert-segment(table, "code" slice, 10) - # . . push args - 68/push 0xa/imm32/segment-length - 52/push-EDX - 51/push-ECX - # . . call - e8/call get-or-insert-segment/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - # save segment - 50/push-EAX - # if (segment != 0) goto next check - 3d/compare-EAX-and 0/imm32 - 75/jump-if-not-equal $test-get-or-insert-segment:check1/disp8 - # fail test - # . _write(2/stderr, msg) - # . . push args - 68/push "F - test-get-or-insert-segment/0\n"/imm32 - 68/push 2/imm32/stderr - # . . call - e8/call _write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - # . increment Num-test-failures - ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Num-test-failures/disp32 # increment *Num-test-failures - e9/jump $test-get-or-insert-segment:end/disp32 -$test-get-or-insert-segment:check1: - # check-ints-equal(segment->length, 10, msg) - # . . push args - 68/push "F - test-get-or-insert-segment/1"/imm32 - 68/push 0xa/imm32/segment-length - ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 8/disp8 . # push *(EAX+8) - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -$test-get-or-insert-segment:check2: - # check-ints-equal(table->write, row-size = 8, msg) - # . . push args - 68/push "F - test-get-or-insert-segment/2"/imm32 - 68/push 8/imm32/row-size - ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - # EAX = string-equal?(*table->data, "code") - # . . push args - 68/push "code"/imm32 - ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 0xc/disp8 . # push *(ECX+12) - # . . call - e8/call string-equal?/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-get-or-insert-segment/3"/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 -$test-get-or-insert-segment:check3: - # stream/EAX = *(table->data+4) - 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 0x10/disp8 . # copy *(ECX+16) to EAX - # check-ints-equal(stream->length, 10, msg) - # . . push args - 68/push "F - test-get-or-insert-segment/4"/imm32 - 68/push 0xa/imm32/segment-size - ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 8/disp8 . # push *(EAX+8) - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -$test-get-or-insert-segment:second-call: - # - insert the same segment name again, verify that it was reused - # segment2/EAX = get-or-insert-segment(table, "code" slice, 8) - # . . push args - 68/push 8/imm32/segment-length - 52/push-EDX - 51/push-ECX - # . . call - e8/call get-or-insert-segment/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - # restore old segment1 - 5a/pop-to-EDX - # check-ints-equal(segment2/EAX, segment1/EDX, msg) - # . . push args - 68/push "F - test-get-or-insert-segment/5"/imm32 - 52/push-EDX - 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 - # no change to table size - # . check-ints-equal(table->write, row-size = 8, msg) - # . . push args - 68/push "F - test-get-or-insert-segment/6"/imm32 - 68/push 8/imm32/row-size - ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -$test-get-or-insert-segment:third-call: - # - insert a new segment name, verify that it was inserted - # EDX : (address slice) = "data" - c7 0/subop/copy 0/mod/indirect 2/rm32/EDX . . . . . _test-data-segment/imm32 # copy to *EDX - c7 0/subop/copy 1/mod/*+disp8 2/rm32/EDX . . . . 4/disp8 _test-data-segment-end/imm32 # copy to *(EDX+4) - # segment2/EAX = get-or-insert-segment(table, "data" slice, 8) - # . . push args - 68/push 8/imm32/segment-length - 52/push-EDX - 51/push-ECX - # . . call - e8/call get-or-insert-segment/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - # table gets a new row - # . check-ints-equal(table->write, 2 rows = 16, msg) - # . . push args - 68/push "F - test-get-or-insert-segment/7"/imm32 - 68/push 0x10/imm32/two-rows - ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX - # . . call - e8/call check-ints-equal/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP -$test-get-or-insert-segment:end: - # . epilog - 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP - 5d/pop-to-EBP - c3/return - # (re)compute the bounds of the next word in the line # return empty string on reaching end of file next-word: # line : (address stream byte), out : (address slice) @@ -1297,14 +1034,6 @@ test-next-word-returns-empty-string-on-eof: == data -_test-code-segment: - 63/c 6f/o 64/d 65/e -_test-code-segment-end: - -_test-data-segment: - 64/d 61/a 74/t 61/a -_test-data-segment-end: - Segment-size: 0x1000/imm32/4KB diff --git a/subx/apps/pack b/subx/apps/pack index 26497e17..f7363a10 100755 Binary files a/subx/apps/pack and b/subx/apps/pack differ diff --git a/subx/apps/subx-common.subx b/subx/apps/subx-common.subx index cba1e9cc..86cf10fe 100644 --- a/subx/apps/subx-common.subx +++ b/subx/apps/subx-common.subx @@ -5,6 +5,272 @@ # . op subop mod rm32 base index scale r32 # . 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 +# scan a 'table' of (string, stream) rows for a row matching 's' +# if it doesn't exist, add a new row with a stream of size 'n' +# if there isn't room, abort +# TODO: pass in an allocation descriptor +get-or-insert-stream: # table : (address stream {string, (address stream byte)}), s : (address slice), n : int -> EAX : (address stream) + # pseudocode: + # curr = table->data + # max = &table->data[table->write] + # while curr < max + # if slice-equal?(s, *curr) + # return *(curr+4) + # curr += 8 + # if table->write < table->length + # *max = slice-to-string(Heap, s) + # result = new-stream(Heap, n, 1) + # *(max+4) = result + # table->write += 8 + # return result + # return 0 + # + # . 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 + 56/push-ESI + # ESI = table + 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI + # curr/ECX = table->data + 8d/copy-address 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 0xc/disp8 . # copy ESI+12 to ECX + # max/EDX = table->data + table->write + 8b/copy 0/mod/indirect 6/rm32/ESI . . . 2/r32/EDX . . # copy *ESI to EDX + 8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ECX 2/index/EDX . 2/r32/EDX . . # copy ECX+EDX to EDX +$get-or-insert-stream:search-loop: + # if (curr >= max) break + 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX + 7d/jump-if-greater-or-equal $get-or-insert-stream:not-found/disp8 + # if (slice-equal?(s, *curr)) return *(curr+4) + # . EAX = slice-equal?(s, *curr) + # . . push args + ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX + ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + # . . call + e8/call slice-equal?/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # . if (EAX != 0) return EAX = *(curr+4) + 3d/compare-EAX-and 0/imm32 + 74/jump-if-equal $get-or-insert-stream:mismatch/disp8 + 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX + eb/jump $get-or-insert-stream:end/disp8 +$get-or-insert-stream:mismatch: + # curr += 8 + 81 0/subop/add 3/mod/direct 1/rm32/ECX . . . . . 8/imm32 # add to ECX + # loop + eb/jump $get-or-insert-stream:search-loop/disp8 +$get-or-insert-stream:not-found: + # result/EAX = 0 + 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX + # if (table->write >= table->length) abort + 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX + 3b/compare 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 8/disp8 . # compare ECX with *(ESI+8) + 7d/jump-if-greater-or-equal $get-or-insert-stream:abort/disp8 + # *max = slice-to-string(Heap, s) + # . EAX = slice-to-string(Heap, s) + # . . push args + ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) + 68/push Heap/imm32 + # . . call + e8/call slice-to-string/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # . *max = EAX + 89/copy 0/mod/indirect 2/rm32/EDX . . . 0/r32/EAX . . # copy EAX to *EDX + # result/EAX = new-stream(Heap, n, 1) + # . . push args + 68/push 1/imm32 + ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) + 68/push Heap/imm32 + # . . call + e8/call new-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # *(max+4) = result + 89/copy 1/mod/*+disp8 2/rm32/EDX . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDX+4) + # table->write += 8 + 81 0/subop/add 0/mod/indirect 6/rm32/ESI . . . . . 8/imm32 # add to *ESI +$get-or-insert-stream:end: + # . restore registers + 5e/pop-to-ESI + 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 + +$get-or-insert-stream:abort: + # . _write(2/stderr, error) + # . . push args + 68/push "get-or-insert-stream: too many segments"/imm32 + 68/push 2/imm32/stderr + # . . call + e8/call _write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # . syscall(exit, 1) + bb/copy-to-EBX 1/imm32 + b8/copy-to-EAX 1/imm32/exit + cd/syscall 0x80/imm8 + # never gets here + +test-get-or-insert-stream: + # . prolog + 55/push-EBP + 89/copy 3/mod/direct 5/rm32/EBP . . . 4/r32/ESP . . # copy ESP to EBP + # var table/ECX : (address stream byte) = stream(2 * 8) + 81 5/subop/subtract 3/mod/direct 4/rm32/ESP . . . . . 0x10/imm32 # subtract from ESP + 68/push 0x10/imm32/length + 68/push 0/imm32/read + 68/push 0/imm32/write + 89/copy 3/mod/direct 1/rm32/ECX . . . 4/r32/ESP . . # copy ESP to ECX + # EDX : (address slice) = "code" + 68/push _test-code-segment-end/imm32/end + 68/push _test-code-segment/imm32/start + 89/copy 3/mod/direct 2/rm32/EDX . . . 4/r32/ESP . . # copy ESP to EDX +$test-get-or-insert-stream:first-call: + # - start with an empty table, insert one segment, verify that it was inserted + # segment/EAX = get-or-insert-stream(table, "code" slice, 10) + # . . push args + 68/push 0xa/imm32/segment-length + 52/push-EDX + 51/push-ECX + # . . call + e8/call get-or-insert-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # save segment + 50/push-EAX + # if (segment != 0) goto next check + 3d/compare-EAX-and 0/imm32 + 75/jump-if-not-equal $test-get-or-insert-stream:check1/disp8 + # fail test + # . _write(2/stderr, msg) + # . . push args + 68/push "F - test-get-or-insert-stream/0\n"/imm32 + 68/push 2/imm32/stderr + # . . call + e8/call _write/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP + # . increment Num-test-failures + ff 0/subop/increment 0/mod/indirect 5/rm32/.disp32 . . . Num-test-failures/disp32 # increment *Num-test-failures + e9/jump $test-get-or-insert-stream:end/disp32 +$test-get-or-insert-stream:check1: + # check-ints-equal(segment->length, 10, msg) + # . . push args + 68/push "F - test-get-or-insert-stream/1"/imm32 + 68/push 0xa/imm32/segment-length + ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 8/disp8 . # push *(EAX+8) + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +$test-get-or-insert-stream:check2: + # check-ints-equal(table->write, row-size = 8, msg) + # . . push args + 68/push "F - test-get-or-insert-stream/2"/imm32 + 68/push 8/imm32/row-size + ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # EAX = string-equal?(*table->data, "code") + # . . push args + 68/push "code"/imm32 + ff 6/subop/push 1/mod/*+disp8 1/rm32/ECX . . . . 0xc/disp8 . # push *(ECX+12) + # . . call + e8/call string-equal?/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-get-or-insert-stream/3"/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 +$test-get-or-insert-stream:check3: + # stream/EAX = *(table->data+4) + 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 0x10/disp8 . # copy *(ECX+16) to EAX + # check-ints-equal(stream->length, 10, msg) + # . . push args + 68/push "F - test-get-or-insert-stream/4"/imm32 + 68/push 0xa/imm32/segment-size + ff 6/subop/push 1/mod/*+disp8 0/rm32/EAX . . . . 8/disp8 . # push *(EAX+8) + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +$test-get-or-insert-stream:second-call: + # - insert the same segment name again, verify that it was reused + # segment2/EAX = get-or-insert-stream(table, "code" slice, 8) + # . . push args + 68/push 8/imm32/segment-length + 52/push-EDX + 51/push-ECX + # . . call + e8/call get-or-insert-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # restore old segment1 + 5a/pop-to-EDX + # check-ints-equal(segment2/EAX, segment1/EDX, msg) + # . . push args + 68/push "F - test-get-or-insert-stream/5"/imm32 + 52/push-EDX + 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 + # no change to table size + # . check-ints-equal(table->write, row-size = 8, msg) + # . . push args + 68/push "F - test-get-or-insert-stream/6"/imm32 + 68/push 8/imm32/row-size + ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +$test-get-or-insert-stream:third-call: + # - insert a new segment name, verify that it was inserted + # EDX : (address slice) = "data" + c7 0/subop/copy 0/mod/indirect 2/rm32/EDX . . . . . _test-data-segment/imm32 # copy to *EDX + c7 0/subop/copy 1/mod/*+disp8 2/rm32/EDX . . . . 4/disp8 _test-data-segment-end/imm32 # copy to *(EDX+4) + # segment2/EAX = get-or-insert-stream(table, "data" slice, 8) + # . . push args + 68/push 8/imm32/segment-length + 52/push-EDX + 51/push-ECX + # . . call + e8/call get-or-insert-stream/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP + # table gets a new row + # . check-ints-equal(table->write, 2 rows = 16, msg) + # . . push args + 68/push "F - test-get-or-insert-stream/7"/imm32 + 68/push 0x10/imm32/two-rows + ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX + # . . call + e8/call check-ints-equal/disp32 + # . . discard args + 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP +$test-get-or-insert-stream:end: + # . epilog + 89/copy 3/mod/direct 4/rm32/ESP . . . 5/r32/EBP . . # copy EBP to ESP + 5d/pop-to-EBP + c3/return + # write an entire stream's contents to a buffered-file # ways to do this: # - construct a 'maximal slice' and pass it to write-slice-buffered @@ -195,4 +461,12 @@ _test-output-buffered-file: # data 00 00 00 00 00 00 # 6 bytes +_test-code-segment: + 63/c 6f/o 64/d 65/e +_test-code-segment-end: + +_test-data-segment: + 64/d 61/a 74/t 61/a +_test-data-segment-end: + # . . vim:nowrap:textwidth=0 diff --git a/subx/apps/survey b/subx/apps/survey index 1d4c9535..fb72c78f 100755 Binary files a/subx/apps/survey and b/subx/apps/survey differ diff --git a/subx/apps/survey.subx b/subx/apps/survey.subx index 43e52150..e0f04e22 100644 --- a/subx/apps/survey.subx +++ b/subx/apps/survey.subx @@ -115,116 +115,6 @@ $convert:end: ## helpers -# TODO: pass in an allocation descriptor -get-or-insert-segment: # table : (address stream row), s : (address slice), n : int -> EAX : (address stream) - # pseudocode: - # curr = table->data - # max = &table->data[table->write] - # while curr < max - # if slice-equal?(s, *curr) - # return *(curr+4) - # curr += 8 - # if table->write < table->length - # *max = slice-to-string(Heap, s) - # result = new-stream(Heap, n, 1) - # *(max+4) = result - # table->write += 8 - # return result - # return 0 - # - # . 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 - 56/push-ESI - # ESI = table - 8b/copy 1/mod/*+disp8 5/rm32/EBP . . . 6/r32/ESI 8/disp8 . # copy *(EBP+8) to ESI - # curr/ECX = table->data - 8d/copy-address 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 0xc/disp8 . # copy ESI+12 to ECX - # max/EDX = table->data + table->write - 8b/copy 0/mod/indirect 6/rm32/ESI . . . 2/r32/EDX . . # copy *ESI to EDX - 8d/copy-address 0/mod/indirect 4/rm32/sib 1/base/ECX 2/index/EDX . 2/r32/EDX . . # copy ECX+EDX to EDX -$get-or-insert-segment:search-loop: - # if (curr >= max) break - 39/compare 3/mod/direct 1/rm32/ECX . . . 2/r32/EDX . . # compare ECX with EDX - 7d/jump-if-greater-or-equal $get-or-insert-segment:not-found/disp8 - # if (slice-equal?(s, *curr)) return *(curr+4) - # . EAX = slice-equal?(s, *curr) - # . . push args - ff 6/subop/push 0/mod/indirect 1/rm32/ECX . . . . . . # push *ECX - ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - # . . call - e8/call slice-equal?/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - # . if (EAX != 0) return EAX = *(curr+4) - 3d/compare-EAX-and 0/imm32 - 74/jump-if-equal $get-or-insert-segment:mismatch/disp8 - 8b/copy 1/mod/*+disp8 1/rm32/ECX . . . 0/r32/EAX 4/disp8 . # copy *(ECX+4) to EAX - eb/jump $get-or-insert-segment:end/disp8 -$get-or-insert-segment:mismatch: - # curr += 8 - 81 0/subop/add 3/mod/direct 1/rm32/ECX . . . . . 8/imm32 # add to ECX - # loop - eb/jump $get-or-insert-segment:search-loop/disp8 -$get-or-insert-segment:not-found: - # result/EAX = 0 - 31/xor 3/mod/direct 0/rm32/EAX . . . 0/r32/EAX . . # clear EAX - # if (table->write >= table->length) abort - 8b/copy 0/mod/indirect 6/rm32/ESI . . . 1/r32/ECX . . # copy *ESI to ECX - 3b/compare 1/mod/*+disp8 6/rm32/ESI . . . 1/r32/ECX 8/disp8 . # compare ECX with *(ESI+8) - 7d/jump-if-greater-or-equal $get-or-insert-segment:abort/disp8 - # *max = slice-to-string(Heap, s) - # . EAX = slice-to-string(Heap, s) - # . . push args - ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0xc/disp8 . # push *(EBP+12) - 68/push Heap/imm32 - # . . call - e8/call slice-to-string/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - # . *max = EAX - 89/copy 0/mod/indirect 2/rm32/EDX . . . 0/r32/EAX . . # copy EAX to *EDX - # result/EAX = new-stream(Heap, n, 1) - # . . push args - 68/push 1/imm32 - ff 6/subop/push 1/mod/*+disp8 5/rm32/EBP . . . . 0x10/disp8 . # push *(EBP+16) - 68/push Heap/imm32 - # . . call - e8/call new-stream/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 0xc/imm32 # add to ESP - # *(max+4) = result - 89/copy 1/mod/*+disp8 2/rm32/EDX . . . 0/r32/EAX 4/disp8 . # copy EAX to *(EDX+4) - # table->write += 8 - 81 0/subop/add 0/mod/indirect 6/rm32/ESI . . . . . 8/imm32 # add to *ESI -$get-or-insert-segment:end: - # . restore registers - 5e/pop-to-ESI - 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 - -$get-or-insert-segment:abort: - # . _write(2/stderr, error) - # . . push args - 68/push "get-or-insert-segment: too many segments"/imm32 - 68/push 2/imm32/stderr - # . . call - e8/call _write/disp32 - # . . discard args - 81 0/subop/add 3/mod/direct 4/rm32/ESP . . . . . 8/imm32 # add to ESP - # . syscall(exit, 1) - bb/copy-to-EBX 1/imm32 - b8/copy-to-EAX 1/imm32/exit - cd/syscall 0x80/imm8 - # never gets here - == data Segment-size: -- cgit 1.4.1-2-gfad0