about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2019-04-12 10:51:33 -0700
committerKartik Agaram <vc@akkartik.com>2019-04-12 10:59:43 -0700
commitfb2ffbd0960d8e9a9e8fd9daa9dc688405016ba2 (patch)
tree3912dc655f1a2924b379dd05acf322da4fc89640
parent61b8fe6b18c6314268ed24d79bf99de6f55be63b (diff)
downloadmu-fb2ffbd0960d8e9a9e8fd9daa9dc688405016ba2.tar.gz
5085 - 'assort' phase done!
Current plan for SubX translator:

  $ cat files.subx ... |assort |pack |survey |hex > a.out

Higher-level notations will be inserted at the start of the pipeline. The
first (and needed for bootstrapping) is for string literals.

  $ cat files.subx ... |string-literals |assort |pack |survey |hex > a.out

Alternatively, we should check how often we use string literals and just
convert them by hand.

They're used all over in tests, and converting them would make tests hard
(even harder) to read.
-rw-r--r--subx/010---vm.cc4
-rwxr-xr-xsubx/apps/assortbin19649 -> 21190 bytes
-rw-r--r--subx/apps/assort.subx904
-rwxr-xr-xsubx/test_apps10
4 files changed, 510 insertions, 408 deletions
diff --git a/subx/010---vm.cc b/subx/010---vm.cc
index 9fbecbc0..6fac9cf7 100644
--- a/subx/010---vm.cc
+++ b/subx/010---vm.cc
@@ -223,8 +223,10 @@ inline uint8_t* mem_addr_u8(uint32_t addr) {
       result = &Mem.at(i).data(addr);
     }
   }
-  if (result == NULL)
+  if (result == NULL) {
+    if (Trace_file) Trace_file.flush();
     raise << "Tried to access uninitialized memory at address 0x" << HEXWORD << addr << '\n' << end();
+  }
   return result;
 }
 inline int8_t* mem_addr_i8(uint32_t addr) {
diff --git a/subx/apps/assort b/subx/apps/assort
index 16084ccd..d7fbd379 100755
--- a/subx/apps/assort
+++ b/subx/apps/assort
Binary files differdiff --git a/subx/apps/assort.subx b/subx/apps/assort.subx
index 5c13f31b..74712632 100644
--- a/subx/apps/assort.subx
+++ b/subx/apps/assort.subx
@@ -131,408 +131,408 @@ $convert:end:
     5d/pop-to-EBP
     c3/return
 
-#? test-convert:
-#?     # . prolog
-#?     55/push-EBP
-#?     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
-#?     # setup
-#?     # . clear-stream(_test-input-stream)
-#?     # . . push args
-#?     68/push  _test-input-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-input-buffered-file+4)
-#?     # . . push args
-#?     b8/copy-to-EAX  _test-input-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
-#?     # . clear-stream(_test-output-stream)
-#?     # . . push args
-#?     68/push  _test-output-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-output-buffered-file+4)
-#?     # . . push args
-#?     b8/copy-to-EAX  _test-output-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
-#?     # initialize input (meta comments in parens)
-#?     #   # comment 1
-#?     #     # comment 2 indented
-#?     #   == code  (new segment)
-#?     #   # comment 3 inside a segment
-#?     #   1
-#?     #                         (empty line)
-#?     #   2 3 # comment 4 inline with other contents
-#?     #   == data  (new segment)
-#?     #   4 5/imm32
-#?     #   == code  (existing segment but non-contiguous with previous iteration)
-#?     #   6 7
-#?     #   8 9  (multiple lines)
-#?     #   == code  (existing segment contiguous with previous iteration)
-#?     #   10 11
-#?     # . write(_test-input-stream, "# comment 1")
-#?     # . . push args
-#?     68/push  "# comment 1"/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "\n")
-#?     # . . push args
-#?     68/push  Newline/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "  # comment 2 indented")
-#?     # . . push args
-#?     68/push  "  # comment 2 indented"/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "\n")
-#?     # . . push args
-#?     68/push  Newline/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "== code")
-#?     # . . push args
-#?     68/push  "== code"/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "\n")
-#?     # . . push args
-#?     68/push  Newline/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "# comment 3 inside a segment")
-#?     # . . push args
-#?     68/push  "# comment 3 inside a segment"/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "\n")
-#?     # . . push args
-#?     68/push  Newline/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "1")
-#?     # . . push args
-#?     68/push  "1"/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "\n")
-#?     # . . push args
-#?     68/push  Newline/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "\n")  # empty line
-#?     # . . push args
-#?     68/push  Newline/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "2 3 # comment 4 inline with other comments")
-#?     # . . push args
-#?     68/push  "2 3 # comment 4 inline with other comments"/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "\n")
-#?     # . . push args
-#?     68/push  Newline/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "== data")
-#?     # . . push args
-#?     68/push  "== data"/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "\n")
-#?     # . . push args
-#?     68/push  Newline/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "4 5/imm32")
-#?     # . . push args
-#?     68/push  "4 5/imm32"/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "\n")
-#?     # . . push args
-#?     68/push  Newline/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "== code")
-#?     # . . push args
-#?     68/push  "== code"/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "\n")
-#?     # . . push args
-#?     68/push  Newline/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "6 7")
-#?     # . . push args
-#?     68/push  "6 7"/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "\n")
-#?     # . . push args
-#?     68/push  Newline/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "8 9")
-#?     # . . push args
-#?     68/push  "6 7"/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "\n")
-#?     # . . push args
-#?     68/push  Newline/imm32
-#?     68/push  _test-input-stream/imm32
-#?     # . . call
-#?     e8/call  write/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "== code")
+test-convert:
+    # . prolog
+    55/push-EBP
+    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+    # setup
+    # . clear-stream(_test-input-stream)
+    # . . push args
+    68/push  _test-input-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-input-buffered-file+4)
+    # . . push args
+    b8/copy-to-EAX  _test-input-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
+    # . clear-stream(_test-output-stream)
+    # . . push args
+    68/push  _test-output-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-output-buffered-file+4)
+    # . . push args
+    b8/copy-to-EAX  _test-output-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
+    # initialize input (meta comments in parens)
+    #   # comment 1
+    #     # comment 2 indented
+    #   == code  (new segment)
+    #   # comment 3 inside a segment
+    #   1
+    #                         (empty line)
+    #   2 3 # comment 4 inline with other contents
+    #   == data  (new segment)
+    #   4 5/imm32
+    #   == code  (existing segment but non-contiguous with previous iteration)
+    #   6 7
+    #   8 9  (multiple lines)
+    #   == code  (existing segment contiguous with previous iteration)
+    #   10 11
+    # . write(_test-input-stream, "# comment 1")
+    # . . push args
+    68/push  "# comment 1"/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "\n")
+    # . . push args
+    68/push  Newline/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "  # comment 2 indented")
+    # . . push args
+    68/push  "  # comment 2 indented"/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "\n")
+    # . . push args
+    68/push  Newline/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "== code")
+    # . . push args
+    68/push  "== code"/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "\n")
+    # . . push args
+    68/push  Newline/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "# comment 3 inside a segment")
+    # . . push args
+    68/push  "# comment 3 inside a segment"/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "\n")
+    # . . push args
+    68/push  Newline/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "1")
+    # . . push args
+    68/push  "1"/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "\n")
+    # . . push args
+    68/push  Newline/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "\n")  # empty line
+    # . . push args
+    68/push  Newline/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "2 3 # comment 4 inline with other contents")
+    # . . push args
+    68/push  "2 3 # comment 4 inline with other contents"/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "\n")
+    # . . push args
+    68/push  Newline/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "== data")
+    # . . push args
+    68/push  "== data"/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "\n")
+    # . . push args
+    68/push  Newline/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "4 5/imm32")
+    # . . push args
+    68/push  "4 5/imm32"/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "\n")
+    # . . push args
+    68/push  Newline/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "== code")
+    # . . push args
+    68/push  "== code"/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "\n")
+    # . . push args
+    68/push  Newline/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "6 7")
+    # . . push args
+    68/push  "6 7"/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "\n")
+    # . . push args
+    68/push  Newline/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "8 9")
+    # . . push args
+    68/push  "8 9"/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "\n")
+    # . . push args
+    68/push  Newline/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "== code")
+    # . . push args
+    68/push  "== code"/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "\n")
+    # . . push args
+    68/push  Newline/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "10 11")
+    # . . push args
+    68/push  "10 11"/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write(_test-input-stream, "\n")
+    # . . push args
+    68/push  Newline/imm32
+    68/push  _test-input-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # convert(_test-input-buffered-file, _test-output-buffered-file)
+    # . . push args
+    68/push  _test-output-buffered-file/imm32
+    68/push  _test-input-buffered-file/imm32
+    # . . call
+    e8/call  convert/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # check output
+    #   == code
+    #   1
+    #   2 3 # comment 4 inline with other contents
+    #   6 7
+    #   8 9
+    #   10 11
+    #   == data
+    #   4 5/imm32
+#?     # dump output {{{
+#?     # . write(2/stderr, "result: ^")
 #?     # . . push args
-#?     68/push  "== code"/imm32
-#?     68/push  _test-input-stream/imm32
+#?     68/push  "result: ^"/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
-#?     # . write(_test-input-stream, "\n")
+#?     # . write-stream(2/stderr, _test-output-stream)
 #?     # . . push args
-#?     68/push  Newline/imm32
-#?     68/push  _test-input-stream/imm32
+#?     68/push  _test-output-stream/imm32
+#?     68/push  2/imm32/stderr
 #?     # . . call
-#?     e8/call  write/disp32
+#?     e8/call  write-stream/disp32
 #?     # . . discard args
 #?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # . write(_test-input-stream, "10 11")
+#?     # . write(2/stderr, "$")
 #?     # . . push args
-#?     68/push  "10 11"/imm32
-#?     68/push  _test-input-stream/imm32
+#?     68/push  "$"/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
-#?     # . write(_test-input-stream, "\n")
+#?     # . write(2/stderr, "\n")
 #?     # . . push args
 #?     68/push  Newline/imm32
-#?     68/push  _test-input-stream/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
-#?     # convert(_test-input-buffered-file, _test-output-buffered-file)
-#?     # . . push args
-#?     68/push  _test-output-buffered-file/imm32
-#?     68/push  _test-input-buffered-file/imm32
-#?     # . . call
-#?     e8/call  convert/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#?     # check output
-#?     #   == code
-#?     #   1
-#?     #   2 3 # comment 4 inline with other contents
-#?     #   6 7
-#?     #   8 9
-#?     #   10 11
-#?     #   == data
-#?     #   4 5/imm32
-#? #?     # debug print {{{
-#? #?     # . write(2/stderr, "^")
-#? #?     # . . push args
-#? #?     68/push  "^"/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
-#? #?     # . write-stream(2/stderr, _test-output-stream)
-#? #?     # . . push args
-#? #?     68/push  _test-output-stream/imm32
-#? #?     68/push  2/imm32/stderr
-#? #?     # . . call
-#? #?     e8/call  write-stream/disp32
-#? #?     # . . discard args
-#? #?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-#? #?     # . write(2/stderr, "$")
-#? #?     # . . push args
-#? #?     68/push  "$"/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
-#? #?     # . write(2/stderr, "\n")
-#? #?     # . . push args
-#? #?     68/push  Newline/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
-#? #?     # }}}
-#?     # . flush(_test-output-buffered-file)
-#?     # . . push args
-#?     68/push  _test-output-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-next-stream-line-equal(_test-output-stream, "== code", msg)
-#?     # . . push args
-#?     68/push  "F - test-convert-code-and-data-segments/0"/imm32
-#?     68/push  "== code"/imm32
-#?     68/push  _test-output-stream/imm32
-#?     # . . call
-#?     e8/call  check-next-stream-line-equal/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-#?     # . check-next-stream-line-equal(_test-output-stream, "1", msg)
-#?     # . . push args
-#?     68/push  "F - test-convert-code-and-data-segments/1"/imm32
-#?     68/push  "e8 20 00 00 00  # e8/call 20/disp32"/imm32
-#?     68/push  _test-output-stream/imm32
-#?     # . . call
-#?     e8/call  check-next-stream-line-equal/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-#?     # . check-next-stream-line-equal(_test-output-stream, "2 3 # comment 4 inline with other contents", msg)
-#?     # . . push args
-#?     68/push  "F - test-convert-code-and-data-segments/2"/imm32
-#?     68/push  "2 3 # comment 4 inline with other contents"/imm32
-#?     68/push  _test-output-stream/imm32
-#?     # . . call
-#?     e8/call  check-next-stream-line-equal/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-#?     # . check-next-stream-line-equal(_test-output-stream, "6 7", msg)
-#?     # . . push args
-#?     68/push  "F - test-convert-code-and-data-segments/3"/imm32
-#?     68/push  "6 7"/imm32
-#?     68/push  _test-output-stream/imm32
-#?     # . . call
-#?     e8/call  check-next-stream-line-equal/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-#?     # . check-next-stream-line-equal(_test-output-stream, "8 9", msg)
-#?     # . . push args
-#?     68/push  "F - test-convert-code-and-data-segments/4"/imm32
-#?     68/push  "8 9"/imm32
-#?     68/push  _test-output-stream/imm32
-#?     # . . call
-#?     e8/call  check-next-stream-line-equal/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-#?     # . check-next-stream-line-equal(_test-output-stream, "10 11", msg)
-#?     # . . push args
-#?     68/push  "F - test-convert-code-and-data-segments/5"/imm32
-#?     68/push  "10 11"/imm32
-#?     68/push  _test-output-stream/imm32
-#?     # . . call
-#?     e8/call  check-next-stream-line-equal/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-#?     # . check-next-stream-line-equal(_test-output-stream, "== data", msg)
-#?     # . . push args
-#?     68/push  "F - test-convert-code-and-data-segments/6"/imm32
-#?     68/push  "== data"/imm32
-#?     68/push  _test-output-stream/imm32
-#?     # . . call
-#?     e8/call  check-next-stream-line-equal/disp32
-#?     # . . discard args
-#?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-#?     # . check-next-stream-line-equal(_test-output-stream, "4 5/imm32", msg)
-#?     # . . push args
-#?     68/push  "F - test-convert-code-and-data-segments/4"/imm32
-#?     68/push  "4 5/imm32"/imm32
-#?     68/push  _test-output-stream/imm32
-#?     # . . call
-#?     e8/call  check-next-stream-line-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
+#?     # }}}
+    # . flush(_test-output-buffered-file)
+    # . . push args
+    68/push  _test-output-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-next-stream-line-equal(_test-output-stream, "== code", msg)
+    # . . push args
+    68/push  "F - test-convert/0"/imm32
+    68/push  "== code"/imm32
+    68/push  _test-output-stream/imm32
+    # . . call
+    e8/call  check-next-stream-line-equal/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+    # . check-next-stream-line-equal(_test-output-stream, "1", msg)
+    # . . push args
+    68/push  "F - test-convert/1"/imm32
+    68/push  "1"/imm32
+    68/push  _test-output-stream/imm32
+    # . . call
+    e8/call  check-next-stream-line-equal/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+    # . check-next-stream-line-equal(_test-output-stream, "2 3 # comment 4 inline with other contents", msg)
+    # . . push args
+    68/push  "F - test-convert/2"/imm32
+    68/push  "2 3 # comment 4 inline with other contents"/imm32
+    68/push  _test-output-stream/imm32
+    # . . call
+    e8/call  check-next-stream-line-equal/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+    # . check-next-stream-line-equal(_test-output-stream, "6 7", msg)
+    # . . push args
+    68/push  "F - test-convert/3"/imm32
+    68/push  "6 7"/imm32
+    68/push  _test-output-stream/imm32
+    # . . call
+    e8/call  check-next-stream-line-equal/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+    # . check-next-stream-line-equal(_test-output-stream, "8 9", msg)
+    # . . push args
+    68/push  "F - test-convert/4"/imm32
+    68/push  "8 9"/imm32
+    68/push  _test-output-stream/imm32
+    # . . call
+    e8/call  check-next-stream-line-equal/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+    # . check-next-stream-line-equal(_test-output-stream, "10 11", msg)
+    # . . push args
+    68/push  "F - test-convert/5"/imm32
+    68/push  "10 11"/imm32
+    68/push  _test-output-stream/imm32
+    # . . call
+    e8/call  check-next-stream-line-equal/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+    # . check-next-stream-line-equal(_test-output-stream, "== data", msg)
+    # . . push args
+    68/push  "F - test-convert/6"/imm32
+    68/push  "== data"/imm32
+    68/push  _test-output-stream/imm32
+    # . . call
+    e8/call  check-next-stream-line-equal/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+    # . check-next-stream-line-equal(_test-output-stream, "4 5/imm32", msg)
+    # . . push args
+    68/push  "F - test-convert/7"/imm32
+    68/push  "4 5/imm32"/imm32
+    68/push  _test-output-stream/imm32
+    # . . call
+    e8/call  check-next-stream-line-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
 
 read-segments:  # in : (address buffered-file), table : (address stream row)
     # pseudocode:
@@ -547,17 +547,32 @@ read-segments:  # in : (address buffered-file), table : (address stream row)
     #       continue
     #     if slice-starts-with?(word-slice, "#")  # comment
     #       continue
-    #     if (slice-equal?(word-slice, "=="))
+    #     if slice-equal?(word-slice, "==")
     #       var segment-name = next-word(line)
-    #       curr-segment = get-or-insert-segment(table, segment-name, N)
+    #       curr-segment = get-or-insert-segment(table, segment-name, Segment-size)
     #     else
-    #       write-stream-data(curr-segment, line)
+    #       rewind-stream(line)
+    #       write-stream(curr-segment, line)  # abort if curr-segment overflows
+    #
+    # word-slice and segment-name are both slices with disjoint lifetimes, so
+    # we'll use the same address for them.
+    #
+    # registers:
+    #   line: ECX
+    #   word-slice and segment-name: EDX
+    #   segment-name and curr-segment: EBX
+    #   word-slice->start: ESI
+    #   temporary: EAX
     #
     # . 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
     # var line/ECX : (address stream byte) = stream(512)
     81          5/subop/subtract    3/mod/direct    4/rm32/ESP    .           .             .           .           .               0x200/imm32       # subtract from ESP
     68/push  0x200/imm32/length
@@ -568,8 +583,6 @@ read-segments:  # in : (address buffered-file), table : (address stream row)
     68/push  0/imm32/end
     68/push  0/imm32/curr
     89/copy                         3/mod/direct    2/rm32/EDX    .           .             .           4/r32/ESP   .               .                 # copy ESP to EDX
-    # var curr-segment/EBX = null
-    31/xor                          3/mod/direct    3/rm32/EBX    .           .             .           3/r32/EBX   .               .                 # clear EBX
 $read-segments:loop:
     # clear-stream(line)
     # . . push args
@@ -645,15 +658,15 @@ $read-segments:check1:
     3d/compare-EAX-and  0/imm32
     0f 85/jump-if-not-equal  $read-segments:loop/disp32
 $read-segments:check-for-comment:
-    # if (slice-starts-with?(word-slice, "#"))
-    # . start/EDX = word-slice->start
-    8b/copy                         0/mod/indirect  1/rm32/ECX    .           .             .           2/r32/EDX   .               .                 # copy *ECX to EDX
+    # if slice-starts-with?(word-slice, "#")
+    # . start/ESI = word-slice->start
+    8b/copy                         0/mod/indirect  2/rm32/EDX    .           .             .           6/r32/ESI   .               .                 # copy *ECX to ESI
     # . c/EAX = *start
     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
-    8a/copy-byte                    0/mod/indirect  2/rm32/EDX    .           .             .           0/r32/AL    .               .                 # copy byte at *EDX to AL
+    8a/copy-byte                    0/mod/indirect  6/rm32/ESI    .           .             .           0/r32/AL    .               .                 # copy byte at *ESI to AL
     # . if (EAX == '#') continue
     3d/compare-EAX-and  0x23/imm32/hash
-    74/jump-if-equal  $read-segments:loop/disp8
+    0f 84/jump-if-equal  $read-segments:loop/disp32
 $read-segments:check-for-segment-header:
 #?     # dump word-slice {{{
 #?     # . write(2/stderr, "AA: ")
@@ -705,7 +718,7 @@ $read-segments:check-for-segment-header:
 #?     # . . discard args
 #?     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
 #?     # }}}
-    # if (slice-equal?(word-slice, "=="))
+    # if slice-equal?(word-slice, "==")
     #   segment-name = next-word(line)
     #   curr-segment = get-or-insert(table, segment-name)
     # . EAX = slice-equal?(word-slice, "==")
@@ -777,9 +790,9 @@ $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, N)
+    # . EAX = get-or-insert-segment(table, segment-name, Segment-size)
     # . . push args
-    68/push  0x1000/imm32/segment-size/4KB
+    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
@@ -791,12 +804,19 @@ $read-segments:check-for-segment-header:
     # . continue
     e9/jump  $read-segments:loop/disp32
 $read-segments:regular-line:
-    # write-stream-data(curr-segment, line)
+    # rewind-stream(line)
+    # . . push args
+    51/push-ECX
+    # . . call
+    e8/call  rewind-stream/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
+    # write-stream(curr-segment, line)
     # . . push args
     51/push-ECX
     53/push-EBX
     # . . call
-    e8/call  write-stream-data/disp32
+    e8/call  write-stream/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
     # loop
@@ -806,7 +826,11 @@ $read-segments:end:
     # . reclaim locals
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0x214/imm32       # add to ESP
     # . restore registers
+    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
@@ -814,26 +838,89 @@ $read-segments:end:
 
 write-segments:  # out : (address buffered-file), table : (address stream row)
     # pseudocode:
-    #   name, stream = table[0]
-    #   var i = 0
-    #   while i < table.length
+    #   var curr = table->data
+    #   var max = table->data + table->write
+    #   while curr < max
     #     name = table[i].name
-    #     if (name == null) break
-    #     write-buffered(out, "== ")
-    #     write-buffered(out, name)
-    #     write-buffered(out, "\n")
+    #     print out, "== $name\n"
     #     stream = table[i].stream
     #     write-stream-data(out, stream)
-    #     ++i
+    #     curr += 8
     #   flush(out)
     #
     # . prolog
     55/push-EBP
     89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
     # . save registers
+    50/push-EAX
+    52/push-EDX
+    56/push-ESI
+    # ESI = table
+    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   0xc/disp8       .                 # copy *(EBP+12) to ESI
+    # write/EDX = table->write
+    8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           2/r32/EDX   .               .                 # copy *ESI to EDX
+    # curr/ESI = table->data
+    81          0/subop/add         3/mod/direct    6/rm32/ESI    .           .             .           .           .               0xc/imm32         # add to EAX
+    # max/EDX = curr + write
+    01/add                          3/mod/direct    2/rm32/EDX    .           .             .           6/r32/ESI   .               .                 # add ESI to EDX
+$write-segments:loop:
+    # if (curr >= max) break
+    39/compare                      3/mod/direct    6/rm32/ESI    .           .             .           2/r32/EDX   .               .                 # compare ESI with EDX
+    7d/jump-if-greater-or-equal  $write-segments:break/disp8
+    # name/EAX = table[i].name
+    8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           0/r32/EAX   .               .                 # copy *ESI to EAX
+    # print out, "== $name\n"
+    # . write-buffered(out, "== ")
+    # . . push args
+    68/push  "== "/imm32
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+    # . . call
+    e8/call  write-buffered/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write-buffered(out, name)
+    # . . push args
+    50/push-EAX
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+    # . . call
+    e8/call  write-buffered/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # . write-buffered(out, "\n")
+    # . . push args
+    68/push  Newline/imm32
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+    # . . call
+    e8/call  write-buffered/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # stream/EAX = table[i].stream
+    8b/copy                         1/mod/*+disp8   6/rm32/ESI    .           .             .           0/r32/EAX   4/disp8         .                 # copy *(ESI+4) to EAX
+    # write-stream-data(out, stream)
+    # . . push args
+    50/push-EAX
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+    # . . call
+    e8/call  write-stream-data/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+$write-segments:continue:
+    # curr += 8
+    81          0/subop/add         3/mod/direct    6/rm32/ESI    .           .             .           .           .               8/imm32           # add to ESI
+    eb/jump  $write-segments:loop/disp8
+$write-segments:break:
+    # flush(out)
+    # . . push args
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+    # . . call
+    e8/call  flush/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
 $write-segments:end:
-    # . reclaim locals
     # . restore registers
+    5e/pop-to-ESI
+    5a/pop-to-EDX
+    58/pop-to-EAX
     # . epilog
     89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
     5d/pop-to-EBP
@@ -911,7 +998,7 @@ $get-or-insert-segment:not-found:
     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 <= writes to 0x0a003873
+    # . *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
@@ -1310,4 +1397,7 @@ _test-data-segment:
   64/d 61/a 74/t 61/a
 _test-data-segment-end:
 
+Segment-size:
+  0x1000/imm32/4KB
+
 # . . vim:nowrap:textwidth=0
diff --git a/subx/test_apps b/subx/test_apps
index bca9d65b..4378a9df 100755
--- a/subx/test_apps
+++ b/subx/test_apps
@@ -190,4 +190,14 @@ test `uname` = 'Linux'  &&  {
   echo
 }
 
+echo assort
+./subx translate *.subx apps/subx-common.subx apps/assort.subx  -o apps/assort
+[ "$1" != record ]  &&  git diff --quiet apps/assort
+./subx run apps/assort test
+echo
+test `uname` = 'Linux'  &&  {
+  apps/assort test
+  echo
+}
+
 exit 0