about summary refs log tree commit diff stats
path: root/subx
diff options
context:
space:
mode:
Diffstat (limited to 'subx')
-rw-r--r--subx/055stream.subx2
-rw-r--r--subx/056trace.subx4
-rw-r--r--subx/058stream-equal.subx225
-rw-r--r--subx/060read.subx20
-rw-r--r--subx/062write-stream.subx22
-rw-r--r--subx/064write-byte.subx31
-rw-r--r--subx/066print-byte.subx10
-rw-r--r--subx/067write-buffered.subx12
-rw-r--r--subx/071read-line.subx13
-rw-r--r--subx/072slice.subx12
-rwxr-xr-xsubx/apps/crenshaw2-1bin15549 -> 16079 bytes
-rwxr-xr-xsubx/apps/crenshaw2-1bbin16108 -> 16638 bytes
-rwxr-xr-xsubx/apps/factorialbin14467 -> 14997 bytes
-rwxr-xr-xsubx/apps/handlebin15260 -> 15790 bytes
-rwxr-xr-xsubx/apps/hexbin18528 -> 19058 bytes
-rwxr-xr-xsubx/apps/packbin17443 -> 17973 bytes
16 files changed, 273 insertions, 78 deletions
diff --git a/subx/055stream.subx b/subx/055stream.subx
index 9711c60a..602a6e28 100644
--- a/subx/055stream.subx
+++ b/subx/055stream.subx
@@ -1,8 +1,8 @@
 # streams: data structure for operating on arrays in a stateful manner
 #
 # A stream looks like this:
-#   read : int  # index that we've read until
 #   write : int  # index at which writes go
+#   read : int  # index that we've read until
 #   data : (array byte)  # prefixed by length as usual
 #
 # primitives for operating on streams:
diff --git a/subx/056trace.subx b/subx/056trace.subx
index 3b1a22e5..96e5646b 100644
--- a/subx/056trace.subx
+++ b/subx/056trace.subx
@@ -1,8 +1,8 @@
 # primitives for emitting traces to a 'trace' stream, and for tests to make assertions on its contents
 #
-# A trace stream looks like this:
-#   read : int  # index that we've read until
+# A trace stream looks like a regular stream:
 #   write : int  # index at which writes go
+#   read : int  # index that we've read until
 #   data : (array byte)  # prefixed by length as usual
 # In a real trace the data will be in a special segment set aside for the purpose.
 #
diff --git a/subx/058stream-equal.subx b/subx/058stream-equal.subx
new file mode 100644
index 00000000..5a01d7ff
--- /dev/null
+++ b/subx/058stream-equal.subx
@@ -0,0 +1,225 @@
+== code
+#   instruction                     effective address                                                   register    displacement    immediate
+# . 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
+
+# main:
+#?     e8/call test-stream-data-equal/disp32
+    e8/call  run-tests/disp32  # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
+    # syscall(exit, Num-test-failures)
+    8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
+    b8/copy-to-EAX  1/imm32/exit
+    cd/syscall  0x80/imm8
+
+# compare all the data in a stream (ignoring the read pointer)
+stream-data-equal?:  # f : (address stream), s : (address string) -> EAX : boolean
+    # . 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
+    57/push-EDI
+    # ESI = f
+    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           6/r32/ESI   8/disp8         .                 # copy *(EBP+8) to ESI
+    # max/EDX = f->data + f->write
+    8b/copy                         0/mod/indirect  6/rm32/ESI    .           .             .           0/r32/EAX   .               .                 # copy *ESI to EAX
+    8d/copy-address                 1/mod/*+disp8   4/rm32/sib    6/base/ESI  0/index/EAX   .           2/r32/EDX   0xc/disp8       .                 # copy ESI+EAX+12 to EDX
+    # currf/ESI = f->data
+    81          0/subop/add         3/mod/direct    6/rm32/ESI    .           .             .           .           .               0xc/imm32         # add to ESI
+    # EDI = s
+    8b/copy                         1/mod/*+disp8   5/rm32/EBP    .           .             .           7/r32/EDI   0xc/disp8       .                 # copy *(EBP+12) to EDI
+    # if (f->write != s->length) return false;
+    39/compare                      0/mod/indirect  7/rm32/EDI    .           .             .           0/r32/EAX   .               .                 # compare *EDI and EAX
+    75/jump-if-not-equal  $stream-data-equal?:false/disp8
+    # currs/EDI = s->data
+    81          0/subop/add         3/mod/direct    7/rm32/EDI    .           .             .           .           .               4/imm32           # add to EDI
+    # EAX = ECX = 0
+    31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
+    31/xor                          3/mod/direct    1/rm32/ECX    .           .             .           1/r32/ECX   .               .                 # clear ECX
+$stream-data-equal?:loop:
+    # if (curr >= max) return true
+    39/compare                      3/mod/direct    6/rm32/ESI    .           .             .           2/r32/EDX   .               .                 # compare ESI with EDX
+    7d/jump-if-greater-or-equal  $stream-data-equal?:true/disp8
+    # AL = *s
+    8a/copy-byte                    0/mod/indirect  6/rm32/ESI    .           .             .           0/r32/AL    .               .                 # copy byte at *ESI to AL
+    # CL = *curr
+    8a/copy-byte                    0/mod/indirect  7/rm32/EDI    .           .             .           1/r32/CL    .               .                 # copy byte at *EDI to CL
+    # if (EAX != ECX) return false
+    39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # compare EAX and ECX
+    75/jump-if-not-equal  $stream-data-equal?:false/disp8
+    # ++f
+    46/increment-ESI
+    # ++curr
+    47/increment-EDI
+    eb/jump $stream-data-equal?:loop/disp8
+$stream-data-equal?:false:
+    b8/copy-to-EAX  0/imm32
+    eb/jump  $stream-data-equal?:end/disp8
+$stream-data-equal?:true:
+    b8/copy-to-EAX  1/imm32
+$stream-data-equal?:end:
+    # . restore registers
+    5f/pop-to-EDI
+    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
+
+test-stream-data-equal:
+    # . prolog
+    55/push-EBP
+    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+    # 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
+    # write(_test-stream, "Abc")
+    # . . push args
+    68/push  "Abc"/imm32
+    68/push  _test-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # EAX = stream-data-equal?(_test-stream, "Abc")
+    # . . push args
+    68/push  "Abc"/imm32
+    68/push  _test-stream/imm32
+    # . . call
+    e8/call  stream-data-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-stream-data-equal"/imm32
+    68/push  1/imm32
+    50/push-EAX
+    # . . call
+    e8/call  check-ints-equal/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+    # . epilog
+    89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+    5d/pop-to-EBP
+    c3/return
+
+test-stream-data-equal-2:
+    # . prolog
+    55/push-EBP
+    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+    # 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
+    # write(_test-stream, "Abc")
+    # . . push args
+    68/push  "Abc"/imm32
+    68/push  _test-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # EAX = stream-data-equal?(_test-stream, "Abd")
+    # . . push args
+    68/push  "Abd"/imm32
+    68/push  _test-stream/imm32
+    # . . call
+    e8/call  stream-data-equal?/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # check-ints-equal(EAX, 0, msg)
+    # . . push args
+    68/push  "F - test-stream-data-equal-2"/imm32
+    68/push  0/imm32
+    50/push-EAX
+    # . . call
+    e8/call  check-ints-equal/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+    # . epilog
+    89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+    5d/pop-to-EBP
+    c3/return
+
+test-stream-data-equal-length-check:
+    # . prolog
+    55/push-EBP
+    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+    # 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
+    # write(_test-stream, "Abc")
+    # . . push args
+    68/push  "Abc"/imm32
+    68/push  _test-stream/imm32
+    # . . call
+    e8/call  write/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # EAX = stream-data-equal?(_test-stream, "Abcd")
+    # . . push args
+    68/push  "Abcd"/imm32
+    68/push  _test-stream/imm32
+    # . . call
+    e8/call  stream-data-equal?/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
+    # check-ints-equal(EAX, 0, msg)
+    # . . push args
+    68/push  "F - test-stream-data-equal-length-check"/imm32
+    68/push  0/imm32
+    50/push-EAX
+    # . . call
+    e8/call  check-ints-equal/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
+    # . epilog
+    89/copy                         3/mod/direct    4/rm32/ESP    .           .             .           5/r32/EBP   .               .                 # copy EBP to ESP
+    5d/pop-to-EBP
+    c3/return
+
+# helper for tests
+check-stream-equal:  # f : (address stream), s : (address string), msg : (address string)
+    # . prolog
+    55/push-EBP
+    89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
+    # . save registers
+    50/push-EAX
+    # EAX = stream-data-equal?(f, s)
+    # . . push args
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0xc/disp8       .                 # push *(EBP+12)
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           8/disp8         .                 # push *(EBP+8)
+    # . . call
+    e8/call  stream-data-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
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/EBP    .           .             .           .           0x10/disp8      .                 # push *(EBP+16)
+    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
+    # . restore registers
+    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
diff --git a/subx/060read.subx b/subx/060read.subx
index 42056a13..c56b8788 100644
--- a/subx/060read.subx
+++ b/subx/060read.subx
@@ -220,15 +220,13 @@ test-read-single:
     e8/call  check-ints-equal/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-    # check-ints-equal(*_test-stream-buffer->data, 41/A 62/b 00 00, msg)
+    # check-stream-equal(_test-stream-buffer, "Ab", msg)
     # . . push args
     68/push  "F - test-read-single"/imm32
-    68/push  0x006241/imm32/Ab
-    # . . push *_test-stream-buffer->data
-    b8/copy-to-EAX  _test-stream-buffer/imm32
-    ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           0xc/disp8       .                 # push *(EAX+12)
+    68/push  "Ab"/imm32
+    68/push  _test-stream-buffer/imm32
     # . . call
-    e8/call  check-ints-equal/disp32
+    e8/call  check-stream-equal/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
     # end
@@ -282,15 +280,13 @@ test-read-is-stateful:
     e8/call  read/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-    # check-ints-equal(*_test-stream-buffer->data, 43/C 44/D 00 00, msg)
+    # check-stream-equal(_test-stream-buffer, "CD", msg)
     # . . push args
     68/push  "F - test-read-is-stateful"/imm32
-    68/push  0x00004443/imm32/C-D
-    # . . push *_test-stream-buffer->data
-    b8/copy-to-EAX  _test-stream-buffer/imm32
-    ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           0xc/disp8       .                 # push *(EAX+12)
+    68/push  "CD"/imm32
+    68/push  _test-stream-buffer/imm32
     # . . call
-    e8/call  check-ints-equal/disp32
+    e8/call  check-stream-equal/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
     # end
diff --git a/subx/062write-stream.subx b/subx/062write-stream.subx
index f112dee9..a4dd73b7 100644
--- a/subx/062write-stream.subx
+++ b/subx/062write-stream.subx
@@ -12,7 +12,7 @@
 #?     68/push  1/imm32/stdout
 #?     e8/call write-stream/disp32
     # automatic test
-#?     e8/call test-write-stream-appends/disp32
+#?     e8/call test-write-stream-single/disp32
     e8/call  run-tests/disp32  # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
     # syscall(exit, Num-test-failures)
     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           3/r32/EBX   Num-test-failures/disp32          # copy *Num-test-failures to EBX
@@ -150,15 +150,13 @@ test-write-stream-single:
     e8/call  write-stream/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-    # check-ints-equal(*_test-stream->data, 41/A 62/b 00 00, msg)
+    # check-stream-equal(_test-stream, "Ab", msg)
     # . . push args
     68/push  "F - test-write-stream-single"/imm32
-    68/push  0x006241/imm32/Ab
-    # . . 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)
+    68/push  "Ab"/imm32
+    68/push  _test-stream/imm32
     # . . call
-    e8/call  check-ints-equal/disp32
+    e8/call  check-stream-equal/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
     # . end
@@ -214,15 +212,13 @@ test-write-stream-appends:
     e8/call  write-stream/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
-    # check-ints-equal(*_test-stream->data, 43/C 44/D 00 00, msg)
+    # check-stream-equal(_test-stream, "CD", msg)
     # . . push args
     68/push  "F - test-write-stream-appends"/imm32
-    68/push  0x00004443/imm32/C-D
-    # . . 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)
+    68/push  "CD"/imm32
+    68/push  _test-stream/imm32
     # . . call
-    e8/call  check-ints-equal/disp32
+    e8/call  check-stream-equal/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
     # . end
diff --git a/subx/064write-byte.subx b/subx/064write-byte.subx
index 9c9b50a6..1d14b06b 100644
--- a/subx/064write-byte.subx
+++ b/subx/064write-byte.subx
@@ -146,15 +146,13 @@ test-write-byte-single:
     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, 'A', msg)
+    # check-stream-equal(_test-stream, "A", msg)
     # . . push args
     68/push  "F - test-write-byte-single"/imm32
-    68/push  0x41/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)
+    68/push  "A"/imm32
+    68/push  _test-stream/imm32
     # . . call
-    e8/call  check-ints-equal/disp32
+    e8/call  check-stream-equal/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
     # . end
@@ -205,26 +203,13 @@ test-write-byte-multiple-flushes:
     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[0..3], 'abcd', msg)
+    # check-stream-equal(_test-stream, "abcdef", msg)
     # . . push args
     68/push  "F - test-write-byte-multiple-flushes: 1"/imm32
-    68/push  0x64636261/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
-    # check-ints-equal(_test-stream->data[4..8], 'efg', msg)
-    # . . push args
-    68/push  "F - test-write-byte-multiple-flushes"/imm32
-    68/push  0x00676665/imm32
-    # . . push *_test-stream->data
-    b8/copy-to-EAX  _test-stream/imm32
-    ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           0x10/disp8      .                 # push *(EAX+16)
+    68/push  "abcdefg"/imm32
+    68/push  _test-stream/imm32
     # . . call
-    e8/call  check-ints-equal/disp32
+    e8/call  check-stream-equal/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
     # . end
diff --git a/subx/066print-byte.subx b/subx/066print-byte.subx
index 3d362fa0..3335bcbf 100644
--- a/subx/066print-byte.subx
+++ b/subx/066print-byte.subx
@@ -87,15 +87,13 @@ test-print-byte:
     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, '0a', msg)
+    # check-stream-equal(_test-stream, "0a", msg)
     # . . push args
     68/push  "F - test-print-byte"/imm32
-    68/push  0x6130/imm32/0a
-    # . . 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)
+    68/push  "0a"/imm32
+    68/push  _test-stream/imm32
     # . . call
-    e8/call  check-ints-equal/disp32
+    e8/call  check-stream-equal/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
     # . end
diff --git a/subx/067write-buffered.subx b/subx/067write-buffered.subx
index 9ae08b21..3825a7f3 100644
--- a/subx/067write-buffered.subx
+++ b/subx/067write-buffered.subx
@@ -146,15 +146,13 @@ test-write-buffered:
     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)
+    # check-stream-equal(_test-stream, "Abc", msg)
     # . . push args
     68/push  "F - test-write-buffered-single"/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)
+    68/push  "Abc"/imm32
+    68/push  _test-stream/imm32
     # . . call
-    e8/call  check-ints-equal/disp32
+    e8/call  check-stream-equal/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
     # . end
@@ -203,7 +201,7 @@ test-write-buffered-with-intermediate-flush:
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
     # and 1 byte should still be in _test-buffered-file
-    # . check-ints-equal(*_test-buffered-file>write, 1, msg)
+    # . check-ints-equal(*_test-buffered-file->write, 1, msg)
     # . . push args
     68/push  "F - test-write-buffered-with-intermediate-flush: unflushed bytes"/imm32
     68/push  1/imm32
diff --git a/subx/071read-line.subx b/subx/071read-line.subx
index 961fc521..1412fb13 100644
--- a/subx/071read-line.subx
+++ b/subx/071read-line.subx
@@ -184,7 +184,8 @@ test-read-line:
     e8/call  check-ints-equal/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-    # check-ints-equal(*_test-stream-buffer->data, 61/a 62/b 0a/newline 00, msg)
+    # check-stream-equal(_test-stream-buffer, "ab\n")
+    # . check-ints-equal(*_test-stream-buffer->data, 61/a 62/b 0a/newline 00, msg)
     # . . push args
     68/push  "F - test-read-line"/imm32
     68/push  0x000a6261/imm32
@@ -295,15 +296,13 @@ test-read-line-reads-final-line-until-eof:
     e8/call  check-ints-equal/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
-    # check-ints-equal(*_test-stream-buffer->data, 63/c 64/d 00 00, msg)
+    # check-stream-equal(_test-stream-buffer, "cd", msg)
     # . . push args
     68/push  "F - test-read-line-reads-final-line-until-eof"/imm32
-    68/push  0x00006463/imm32
-    # . . push *_test-stream->data
-    b8/copy-to-EAX  _test-stream-buffer/imm32
-    ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           0xc/disp8       .                 # push *(EAX+12)
+    68/push  "cd"/imm32
+    68/push  _test-stream-buffer/imm32
     # . . call
-    e8/call  check-ints-equal/disp32
+    e8/call  check-stream-equal/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
     # end
diff --git a/subx/072slice.subx b/subx/072slice.subx
index 82099bc5..36bdfdd4 100644
--- a/subx/072slice.subx
+++ b/subx/072slice.subx
@@ -120,7 +120,7 @@ slice-equal?:  # s : (address slice), p : (address string) -> EAX : boolean
     75/jump-if-not-equal  $slice-equal?:false/disp8
     # skip p->length
     81          0/subop/add         3/mod/direct    3/rm32/EBX    .           .             .           .           .               4/imm32           # add to EBX
-    # EAX = ECX = false
+    # EAX = ECX = 0
     31/xor                          3/mod/direct    0/rm32/EAX    .           .             .           0/r32/EAX   .               .                 # clear EAX
     31/xor                          3/mod/direct    1/rm32/ECX    .           .             .           1/r32/ECX   .               .                 # clear ECX
 $slice-equal?:loop:
@@ -489,15 +489,13 @@ test-write-slice:
     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)
+    # check-stream-equal(_test-stream, "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)
+    68/push  "Abc"/imm32
+    68/push  _test-stream/imm32
     # . . call
-    e8/call  check-ints-equal/disp32
+    e8/call  check-stream-equal/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               0xc/imm32         # add to ESP
     # . epilog
diff --git a/subx/apps/crenshaw2-1 b/subx/apps/crenshaw2-1
index 082416cf..2088b70b 100755
--- a/subx/apps/crenshaw2-1
+++ b/subx/apps/crenshaw2-1
Binary files differdiff --git a/subx/apps/crenshaw2-1b b/subx/apps/crenshaw2-1b
index f8d52e06..0d5d6b5f 100755
--- a/subx/apps/crenshaw2-1b
+++ b/subx/apps/crenshaw2-1b
Binary files differdiff --git a/subx/apps/factorial b/subx/apps/factorial
index ee7c9782..f5b6cae5 100755
--- a/subx/apps/factorial
+++ b/subx/apps/factorial
Binary files differdiff --git a/subx/apps/handle b/subx/apps/handle
index bfe7cf74..58e9cc13 100755
--- a/subx/apps/handle
+++ b/subx/apps/handle
Binary files differdiff --git a/subx/apps/hex b/subx/apps/hex
index e67cc1fb..0f151ac4 100755
--- a/subx/apps/hex
+++ b/subx/apps/hex
Binary files differdiff --git a/subx/apps/pack b/subx/apps/pack
index 4e7ae680..4651ec96 100755
--- a/subx/apps/pack
+++ b/subx/apps/pack
Binary files differ