about summary refs log tree commit diff stats
path: root/subx
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2018-10-29 16:22:40 -0700
committerKartik Agaram <vc@akkartik.com>2018-10-29 16:34:47 -0700
commitf94442fe2da11e3938f01b3065546b36313ef342 (patch)
treeda514f0b7ea1319e9887169d3e675e65eee99b17 /subx
parent3d94e2db0e809530f277220c5d5fea6996ee47d6 (diff)
downloadmu-f94442fe2da11e3938f01b3065546b36313ef342.tar.gz
4736
We'll use a common stream data structure for input and output streams.

Having separate types makes more sense in a more high-level language, where
we have type checking and where functions for handling the different types
are more concise. But in machine code the sweet spot is more toward fewer
types.
Diffstat (limited to 'subx')
-rw-r--r--subx/056write.subx91
-rwxr-xr-xsubx/apps/crenshaw2-1bin3334 -> 3345 bytes
-rwxr-xr-xsubx/apps/factorialbin3351 -> 3362 bytes
3 files changed, 48 insertions, 43 deletions
diff --git a/subx/056write.subx b/subx/056write.subx
index ba131e42..7ac0dfd0 100644
--- a/subx/056write.subx
+++ b/subx/056write.subx
@@ -1,26 +1,29 @@
-# write: like _write, but also support in-memory output streams (`ostream`s)
-# in addition to file descriptors.
+# write: like _write, but also support in-memory streams in addition to file
+# descriptors.
 #
 # Our first dependency-injected and testable primitive. We can pass it either
-# a file descriptor or an address to an ostream. If a file descriptor is
-# passed in, we _write to it using the right syscall. If a 'fake file descriptor'
-# or ostream is passed in, we append to the ostream. This lets us redirect
-# output in tests and check it later.
+# a file descriptor or an address to a stream. If a file descriptor is passed
+# in, we _write to it using the right syscall. If a 'fake file descriptor' or
+# stream is passed in, we append to the stream. This lets us redirect output
+# in tests and check it later.
 #
 # We assume our data segment will never begin at an address shorter than
 # 0x08000000, so any smaller arguments are assumed to be real file descriptors.
 #
-# An ostream looks like this:
+# A stream looks like this:
+#   read: int  # index at which to read next
 #   write: int  # index at which writes go
 #   data: (array byte)  # prefixed by length as usual
 
 == data
 
-# In-memory ostream for tests to write() to.
-# Also illustrates the layout of ostreams.
-Test-ostream:
+# In-memory stream for tests to write() to.
+# Also illustrates the layout of streams.
+Test-stream:
   # current write index
   00 00 00 00
+  # current read index
+  00 00 00 00
   # length (= 8)
   08 00 00 00
   # data
@@ -39,7 +42,7 @@ Test-ostream:
   b8/copy-to-EAX  1/imm32
   cd/syscall  0x80/imm8
 
-write:  # f : fd or (address ostream), s : (address array byte) -> <void>
+write:  # f : fd or (address stream), s : (address array byte) -> <void>
   # prolog
   55/push-EBP
   89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
@@ -55,7 +58,7 @@ write:  # f : fd or (address ostream), s : (address array byte) -> <void>
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               8/imm32           # add to ESP
   eb/jump  $write:end/disp8
 $write:fake:
-  # otherwise, treat 'f' as an ostream to append to
+  # otherwise, treat 'f' as an stream to append to
   # save registers
   50/push-EAX
   51/push-ECX
@@ -66,15 +69,15 @@ $write:fake:
   # EDX = f.write
   8b/copy                         0/mod/indirect  1/rm32/ECX    .           .             .           2/r32/EDX   .               .                 # copy *ECX to EDX
   # EBX = f.length
-  8b/copy                         1/mod/*+disp8   1/rm32/ECX    .           .             .           3/r32/EBX   4/disp8         .                 # copy *(ECX+4) to EBX
+  8b/copy                         1/mod/*+disp8   1/rm32/ECX    .           .             .           3/r32/EBX   8/disp8         .                 # copy *(ECX+8) to EBX
   # EAX = _append(&f.data[f.write], &f.data[f.length], s)
     # push s
   ff          6/subop/push        1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none  .           .           0xc/disp8       .                 # push *(EBP+12)
     # push &f.data[f.length]
-  8d/copy-address                 1/mod/*+disp8   4/rm32/sib    1/base/ECX  3/index/EBX   .           3/r32/EBX   8/disp8         .                 # copy ECX+EBX+8 to EBX
+  8d/copy-address                 1/mod/*+disp8   4/rm32/sib    1/base/ECX  3/index/EBX   .           3/r32/EBX   0xc/disp8       .                 # copy ECX+EBX+12 to EBX
   53/push-EBX
     # push &f.data[f.write]
-  8d/copy-address                 1/mod/*+disp8   4/rm32/sib    1/base/ECX  2/index/EDX   .           3/r32/EBX   8/disp8         .                 # copy ECX+EBX+8 to EBX
+  8d/copy-address                 1/mod/*+disp8   4/rm32/sib    1/base/ECX  2/index/EDX   .           3/r32/EBX   0xc/disp8       .                 # copy ECX+EDX+12 to EBX
   53/push-EBX
     # call
   e8/call  _append/disp32
@@ -93,7 +96,7 @@ $write:end:
   5d/pop-to-EBP
   c3/return
 
-clear-ostream:  # f : (address ostream)
+clear-stream:  # f : (address stream)
   # prolog
   55/push-EBP
   89/copy                         3/mod/direct    5/rm32/EBP    .           .             .           4/r32/ESP   .               .                 # copy ESP to EBP
@@ -103,24 +106,26 @@ clear-ostream:  # f : (address ostream)
   # EAX = f
   8b/copy                         1/mod/*+disp8   4/rm32/sib    5/base/EBP  4/index/none              0/r32/EAX   8/disp8         .                 # copy *(EBP+8) to EAX
   # ECX = f.length
-  8b/copy                         1/mod/*+disp8   0/rm32/EAX    .           .             .           1/r32/ECX   4/disp8         .                 # copy *(EAX+4) to ECX
+  8b/copy                         1/mod/*+disp8   0/rm32/EAX    .           .             .           1/r32/ECX   8/disp8         .                 # copy *(EAX+8) to ECX
   # ECX = &f.data[f.length]
-  8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/EAX  1/index/ECX   .           1/r32/ECX   8/disp8         .                 # copy EAX+ECX+8 to ECX
+  8d/copy-address                 1/mod/*+disp8   4/rm32/sib    0/base/EAX  1/index/ECX   .           1/r32/ECX   0xc/disp8       .                 # copy EAX+ECX+12 to ECX
   # f.write = 0
   c7/copy                         0/mod/direct    0/rm32/EAX    .           .             .           .           .               0/imm32           # copy to *EAX
+  # f.read = 0
+  c7/copy                         1/mod/*+disp8   0/rm32/EAX    .           .             .           .           4/disp8         0/imm32           # copy to *(EAX+4)
   # EAX = f.data
-  81          0/subop/add         3/mod/direct    0/rm32/EAX    .           .             .           .           .               8/imm32           # add to EAX
+  81          0/subop/add         3/mod/direct    0/rm32/EAX    .           .             .           .           .               0xc/imm32         # add to EAX
   # while (true)
-$clear-ostream:loop:
+$clear-stream:loop:
   # if EAX >= ECX break
   39/compare                      3/mod/direct    0/rm32/EAX    .           .             .           1/r32/ECX   .               .                 # compare EAX with ECX
-  7d/jump-if-greater-or-equal  $clear-ostream:end/disp8
+  7d/jump-if-greater-or-equal  $clear-stream:end/disp8
   # *EAX = 0
   c7/copy                         0/mod/direct    0/rm32/EAX    .           .             .           .           .               0/imm32           # copy to *EAX
   # EAX += 4
   81          0/subop/add         3/mod/direct    0/rm32/EAX    .           .             .           .           .               4/imm32           # add to EAX
-  eb/jump  $clear-ostream:loop/disp8
-$clear-ostream:end:
+  eb/jump  $clear-stream:loop/disp8
+$clear-stream:end:
   # restore registers
   59/pop-to-ECX
   58/pop-to-EAX
@@ -130,28 +135,28 @@ $clear-ostream:end:
   c3/return
 
 test-write-single:
-  # clear-ostream(Test-ostream)
+  # clear-stream(Test-stream)
     # push args
-  68/push  Test-ostream/imm32
+  68/push  Test-stream/imm32
     # call
-  e8/call  clear-ostream/disp32
+  e8/call  clear-stream/disp32
     # discard args
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-  # write(Test-ostream, "Ab")
+  # write(Test-stream, "Ab")
     # push args
   68/push  "Ab"/imm32
-  68/push  Test-ostream/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
-  # check-ints-equal(*Test-ostream.data, 41/A 62/b 00 00, msg)
+  # check-ints-equal(*Test-stream.data, 41/A 62/b 00 00, msg)
     # push args
   68/push  "F - test-write-single"/imm32
   68/push  0x006241/imm32/Ab
-    # push *Test-ostream.data
-  b8/copy-to-EAX  Test-ostream/imm32
-  ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           8/disp8         .                 # push *(EAX+8)
+    # 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
@@ -160,36 +165,36 @@ test-write-single:
   c3/return
 
 test-write-appends:
-  # clear-ostream(Test-ostream)
+  # clear-stream(Test-stream)
     # push args
-  68/push  Test-ostream/imm32
+  68/push  Test-stream/imm32
     # call
-  e8/call  clear-ostream/disp32
+  e8/call  clear-stream/disp32
     # discard args
   81          0/subop/add         3/mod/direct    4/rm32/ESP    .           .             .           .           .               4/imm32           # add to ESP
-  # write(Test-ostream, "C")
+  # write(Test-stream, "C")
     # push args
   68/push  "C"/imm32
-  68/push  Test-ostream/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
-  # write(Test-ostream, "D")
+  # write(Test-stream, "D")
     # push args
   68/push  "D"/imm32
-  68/push  Test-ostream/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
-  # check-ints-equal(*Test-ostream.data, 43/C 44/D 00 00, msg)
+  # check-ints-equal(*Test-stream.data, 43/C 44/D 00 00, msg)
     # push args
   68/push  "F - test-write-appends"/imm32
   68/push  0x00004443/imm32/C-D
-    # push *Test-ostream.data
-  b8/copy-to-EAX  Test-ostream/imm32
-  ff          6/subop/push        1/mod/*+disp8   0/rm32/EAX    .           .             .           .           8/disp8         .                 # push *(EAX+8)
+    # 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
diff --git a/subx/apps/crenshaw2-1 b/subx/apps/crenshaw2-1
index 9ac09053..2c20170f 100755
--- a/subx/apps/crenshaw2-1
+++ b/subx/apps/crenshaw2-1
Binary files differdiff --git a/subx/apps/factorial b/subx/apps/factorial
index 540b6c82..4a36fa37 100755
--- a/subx/apps/factorial
+++ b/subx/apps/factorial
Binary files differ