about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2019-09-11 19:04:49 -0700
committerKartik Agaram <vc@akkartik.com>2019-09-11 19:53:23 -0700
commitecfbbfb5b58aaba9f9265cb13b9fb4a914bdcf37 (patch)
tree486cd5f4ee75323b5c733912c7a58501d65b0325
parent4d53de8afa0d44e29d3caeb01ccdd02bc2e4cd70 (diff)
downloadmu-ecfbbfb5b58aaba9f9265cb13b9fb4a914bdcf37.tar.gz
5647 - experimental support for swapping OS
-rw-r--r--049init.linux68
-rw-r--r--049memory_layout.subx8
-rwxr-xr-xapps/assortbin40134 -> 40205 bytes
-rwxr-xr-xapps/callsbin44884 -> 44955 bytes
-rwxr-xr-xapps/crenshaw2-1bin33868 -> 33939 bytes
-rwxr-xr-xapps/crenshaw2-1bbin34427 -> 34498 bytes
-rwxr-xr-xapps/dquotesbin45338 -> 45409 bytes
-rwxr-xr-xapps/factorialbin32880 -> 32951 bytes
-rwxr-xr-xapps/handlebin33734 -> 33805 bytes
-rwxr-xr-xapps/hexbin42527 -> 42598 bytes
-rwxr-xr-xapps/packbin52820 -> 52891 bytes
-rwxr-xr-xapps/sigilsbin52847 -> 52918 bytes
-rwxr-xr-xapps/surveybin49417 -> 49488 bytes
-rwxr-xr-xapps/testsbin38946 -> 39017 bytes
-rwxr-xr-xbuild8
-rwxr-xr-xexamples/ex1bin128 -> 197 bytes
-rw-r--r--examples/ex1.subx9
-rwxr-xr-xexamples/ex10bin195 -> 264 bytes
-rw-r--r--examples/ex10.subx9
-rwxr-xr-xexamples/ex11bin1111 -> 1178 bytes
-rw-r--r--examples/ex11.subx12
-rwxr-xr-xexamples/ex12bin167 -> 234 bytes
-rw-r--r--examples/ex12.subx14
-rwxr-xr-xexamples/ex2bin129 -> 198 bytes
-rw-r--r--examples/ex2.subx9
-rwxr-xr-xexamples/ex3bin146 -> 215 bytes
-rw-r--r--examples/ex3.subx9
-rwxr-xr-xexamples/ex4bin171 -> 236 bytes
-rw-r--r--examples/ex4.subx19
-rwxr-xr-xexamples/ex5bin171 -> 238 bytes
-rw-r--r--examples/ex5.subx14
-rwxr-xr-xexamples/ex6bin165 -> 232 bytes
-rw-r--r--examples/ex6.subx16
-rwxr-xr-xexamples/ex7bin313 -> 366 bytes
-rw-r--r--examples/ex7.subx49
-rwxr-xr-xexamples/ex8bin165 -> 234 bytes
-rw-r--r--examples/ex8.subx7
-rwxr-xr-xexamples/ex9bin159 -> 228 bytes
-rw-r--r--examples/ex9.subx9
-rwxr-xr-xtest_apps54
40 files changed, 168 insertions, 146 deletions
diff --git a/049init.linux b/049init.linux
new file mode 100644
index 00000000..4dcb77be
--- /dev/null
+++ b/049init.linux
@@ -0,0 +1,68 @@
+# Some OS-specific preliminaries for Linux.
+
+# Memory layout
+#
+#          0 - 0x08047ffff - reserved for the kernel
+# 0x08048000 - 0xbffffffff - available for user programs
+# 0xc0000000 - 0xfffffffff - reserved for the kernel
+== code 0x09000000
+== data 0x0a000000
+
+# Syscalls
+#
+# We don't have libc, so we need to know Linux's precise syscall layout.
+== code
+
+# http://man7.org/linux/man-pages/man2/exit.2.html
+syscall_exit:  # status/ebx : int
+    b8/copy-to-eax 1/imm32
+    cd/syscall 0x80/imm8
+
+# http://man7.org/linux/man-pages/man2/read.2.html
+syscall_read:  # fd/ebx : int, buf/ecx : address, size/edx : int -> nbytes-or-error/eax : int
+    b8/copy-to-eax 3/imm32
+    cd/syscall 0x80/imm8
+    c3/return
+
+# http://man7.org/linux/man-pages/man2/write.2.html
+syscall_write:  # fd/ebx : int, buf/ecx : address, size/edx : int -> nbytes-or-error/eax : int
+    b8/copy-to-eax 4/imm32
+    cd/syscall 0x80/imm8
+    c3/return
+
+# http://man7.org/linux/man-pages/man2/open.2.html
+syscall_open:  # filename/ebx : (address null-terminated-string), flags/ecx : int -> fd-or-error/eax : int
+    b8/copy-to-eax 5/imm32
+    cd/syscall 0x80/imm8
+    c3/return
+
+# http://man7.org/linux/man-pages/man2/close.2.html
+syscall_close:  # fd/ebx : int -> status/eax
+    b8/copy-to-eax 6/imm32
+    cd/syscall 0x80/imm8
+    c3/return
+
+# http://man7.org/linux/man-pages/man2/creat.2.html
+syscall_creat:  # filename/ebx : (address null-terminated-string) -> fd-or-error/eax : int
+    b8/copy-to-eax 8/imm32
+    cd/syscall 0x80/imm8
+    c3/return
+
+# http://man7.org/linux/man-pages/man2/unlink.2.html
+syscall_unlink:  # filename/ebx : (address null-terminated-string) -> status/eax : int
+    b8/copy-to-eax 0xa/imm32
+    cd/syscall 0x80/imm8
+    c3/return
+
+# http://man7.org/linux/man-pages/man2/rename.2.html
+syscall_rename:  # source/ebx : (address null-terminated-string), dest/ecx : (address null-terminated-string) -> status/eax : int
+    b8/copy-to-eax 0x26/imm32
+    cd/syscall 0x80/imm8
+    c3/return
+
+# https://github.com/torvalds/linux/blob/fa121bb3fed6313b1f0af23952301e06cf6d32ed/mm/nommu.c#L1352
+syscall_mmap:  # arg/ebx : (address mmap_arg_struct) -> status/eax : int
+    # the important thing: ebx+4 contains the 32-bit size to be allocated
+    b8/copy-to-eax 0x5a/imm32
+    cd/syscall 0x80/imm8
+    c3/return
diff --git a/049memory_layout.subx b/049memory_layout.subx
deleted file mode 100644
index 36837ade..00000000
--- a/049memory_layout.subx
+++ /dev/null
@@ -1,8 +0,0 @@
-# Segment addresses aren't really the concern of any other layer, so we'll
-# define them separately. They're approximate due to fidgety ELF alignment
-# requirements, so don't get clever assuming variables are at specific
-# addresses.
-
-== code 0x09000000
-
-== data 0x0a000000
diff --git a/apps/assort b/apps/assort
index df5bd853..aac0b75a 100755
--- a/apps/assort
+++ b/apps/assort
Binary files differdiff --git a/apps/calls b/apps/calls
index 1305659d..11179969 100755
--- a/apps/calls
+++ b/apps/calls
Binary files differdiff --git a/apps/crenshaw2-1 b/apps/crenshaw2-1
index 73ea69a8..62c12a81 100755
--- a/apps/crenshaw2-1
+++ b/apps/crenshaw2-1
Binary files differdiff --git a/apps/crenshaw2-1b b/apps/crenshaw2-1b
index c50483a7..e22acd4a 100755
--- a/apps/crenshaw2-1b
+++ b/apps/crenshaw2-1b
Binary files differdiff --git a/apps/dquotes b/apps/dquotes
index 98222863..d3f84e8b 100755
--- a/apps/dquotes
+++ b/apps/dquotes
Binary files differdiff --git a/apps/factorial b/apps/factorial
index 35e27ecf..ad02a27e 100755
--- a/apps/factorial
+++ b/apps/factorial
Binary files differdiff --git a/apps/handle b/apps/handle
index bfe24eaf..c4ed2356 100755
--- a/apps/handle
+++ b/apps/handle
Binary files differdiff --git a/apps/hex b/apps/hex
index 8312b87a..e5cdd533 100755
--- a/apps/hex
+++ b/apps/hex
Binary files differdiff --git a/apps/pack b/apps/pack
index 849f2e27..55fcfb6d 100755
--- a/apps/pack
+++ b/apps/pack
Binary files differdiff --git a/apps/sigils b/apps/sigils
index 88ae4de2..22dadf70 100755
--- a/apps/sigils
+++ b/apps/sigils
Binary files differdiff --git a/apps/survey b/apps/survey
index 9a142dac..b55bc007 100755
--- a/apps/survey
+++ b/apps/survey
Binary files differdiff --git a/apps/tests b/apps/tests
index 24659a6d..2fc7071c 100755
--- a/apps/tests
+++ b/apps/tests
Binary files differdiff --git a/build b/build
index aaa236de..483ac49c 100755
--- a/build
+++ b/build
@@ -119,7 +119,7 @@ then
   for n in `seq 1 12`
   do
     older_than examples/ex$n examples/ex$n.subx && {
-      ./subx_bin translate examples/ex$n.subx -o examples/ex$n
+      ./subx_bin translate 049init.linux examples/ex$n.subx -o examples/ex$n
     }
   done
 
@@ -127,7 +127,7 @@ then
   for app in factorial crenshaw2-1 crenshaw2-1b handle
   do
     older_than apps/$app apps/$app.subx [0-9]*.subx && {
-      ./subx_bin translate [0-9]*.subx apps/$app.subx -o apps/$app
+      ./subx_bin translate 049init.linux [0-9]*.subx apps/$app.subx -o apps/$app
     }
   done
 
@@ -135,7 +135,7 @@ then
   for phase in hex survey pack assort dquotes tests
   do
     older_than apps/$phase apps/$phase.subx apps/subx-common.subx [0-9]*.subx && {
-      ./subx_bin translate [0-9]*.subx apps/subx-common.subx apps/$phase.subx -o apps/$phase
+      ./subx_bin translate 049init.linux [0-9]*.subx apps/subx-common.subx apps/$phase.subx -o apps/$phase
     }
   done
 
@@ -143,7 +143,7 @@ then
   for phase in sigils
   do
     older_than apps/$phase apps/$phase.subx apps/subx-common.subx [0-9]*.subx && {
-      ./subx_bin translate [0-9]*.subx apps/subx-common.subx apps/$phase.subx -o apps/$phase
+      ./subx_bin translate 049init.linux [0-9]*.subx apps/subx-common.subx apps/$phase.subx -o apps/$phase
     }
   done
 
diff --git a/examples/ex1 b/examples/ex1
index aeb62302..5f17bc66 100755
--- a/examples/ex1
+++ b/examples/ex1
Binary files differdiff --git a/examples/ex1.subx b/examples/ex1.subx
index fae025c0..89ac8bce 100644
--- a/examples/ex1.subx
+++ b/examples/ex1.subx
@@ -8,14 +8,11 @@
 #   $ echo $?
 #   42
 
-== code 0x09000000
+== code
 
 Entry:
-# syscall(exit, 42)
+# exit(42)
 bb/copy-to-ebx  2a/imm32  # 42 in hex
-b8/copy-to-eax  1/imm32/exit
-cd/syscall  0x80/imm8
-
-== data 0x0a000000
+e8/call  syscall_exit/disp32
 
 # . . vim:nowrap:textwidth=0
diff --git a/examples/ex10 b/examples/ex10
index d8ad528e..cb8973fe 100755
--- a/examples/ex10
+++ b/examples/ex10
Binary files differdiff --git a/examples/ex10.subx b/examples/ex10.subx
index c32c44ea..36a21bbe 100644
--- a/examples/ex10.subx
+++ b/examples/ex10.subx
@@ -7,7 +7,7 @@
 #   $ echo $?
 #   0  # false
 
-== code 0x09000000
+== 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
@@ -27,10 +27,9 @@ Entry:  # return argv-equal(argv[1], argv[2])
     ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
     # . . call
     e8/call argv-equal/disp32
-    # syscall(exit, eax)
+    # exit(eax)
     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           0/r32/eax   .               .                 # copy eax to ebx
-    b8/copy-to-eax  1/imm32/exit
-    cd/syscall  0x80/imm8
+    e8/call  syscall_exit/disp32
 
 # compare two null-terminated ascii strings
 # reason for the name: the only place we should have null-terminated ascii strings is from commandline args
@@ -67,6 +66,4 @@ $argv-equal:false:
     b8/copy-to-eax  0/imm32
     c3/return
 
-== data 0x0a000000
-
 # . . vim:nowrap:textwidth=0
diff --git a/examples/ex11 b/examples/ex11
index 0ffafb6f..1cb1aa5c 100755
--- a/examples/ex11
+++ b/examples/ex11
Binary files differdiff --git a/examples/ex11.subx b/examples/ex11.subx
index ff0977df..a6a24cfc 100644
--- a/examples/ex11.subx
+++ b/examples/ex11.subx
@@ -14,17 +14,16 @@
 # because checking for it would require the function being tested! Breakage
 # would cause tests to not run, rather than to fail as we'd like.)
 
-== code 0x09000000
+== 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
 
 Entry:  # run all tests
     e8/call  run-tests/disp32  # 'run-tests' is a function created automatically by SubX. It calls all functions that start with 'test-'.
-    # syscall(exit, eax)
+    # exit(eax)
     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           0/r32/eax   .               .                 # copy eax to ebx
-    b8/copy-to-eax  1/imm32/exit
-    cd/syscall  0x80/imm8
+    e8/call  syscall_exit/disp32
 
 # compare a null-terminated ascii string with a more idiomatic length-prefixed byte array
 # reason for the name: the only place we should have null-terminated ascii strings is from commandline args
@@ -327,8 +326,7 @@ write-stderr:  # s : (address array byte) -> <void>
     8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           2/r32/edx   8/disp8         .                 # copy *(ebp+8) to edx
     8b/copy                         0/mod/indirect  2/rm32/edx    .           .             .           2/r32/edx   .               .                 # copy *edx to edx
     # . . syscall
-    b8/copy-to-eax  4/imm32/write
-    cd/syscall  0x80/imm8
+    e8/call  syscall_write/disp32
     # . restore registers
     5b/pop-to-ebx
     5a/pop-to-edx
@@ -339,7 +337,7 @@ write-stderr:  # s : (address array byte) -> <void>
     5d/pop-to-ebp
     c3/return
 
-== data 0x0a000000
+== data
 
 Newline:
     # size
diff --git a/examples/ex12 b/examples/ex12
index c13a86ed..80e5deeb 100755
--- a/examples/ex12
+++ b/examples/ex12
Binary files differdiff --git a/examples/ex12.subx b/examples/ex12.subx
index 571d42d8..dafa0071 100644
--- a/examples/ex12.subx
+++ b/examples/ex12.subx
@@ -6,26 +6,24 @@
 #   $ ./subx run examples/ex12
 # You shouldn't get a segmentation fault.
 
-== code 0x09000000
+== 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
 
 Entry:
-    # syscall(mmap, 0x1000)
+    # mmap(Mmap-new-segment->len)
     bb/copy-to-ebx  Mmap-new-segment/imm32
-    b8/copy-to-eax  0x5a/imm32/mmap
-    cd/syscall  0x80/imm8
+    e8/call  syscall_mmap/disp32
 
     # write to *eax to check that we have access to the newly-allocated segment
     c7          0/subop/copy        0/mod/direct    0/rm32/eax    .           .             .           .           .               0x34/imm32        # copy to *eax
 
-    # syscall(exit, eax)
+    # exit(eax)
     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           0/r32/eax   .               .                 # copy eax to ebx
-    b8/copy-to-eax  1/imm32/exit
-    cd/syscall  0x80/imm8
+    e8/call  syscall_exit/disp32
 
-== data 0x0a000000
+== data
 
 # various constants used here were found in the Linux sources (search for file mman-common.h)
 Mmap-new-segment:  # type mmap_arg_struct
diff --git a/examples/ex2 b/examples/ex2
index 55a87a3f..5e0c1be1 100755
--- a/examples/ex2
+++ b/examples/ex2
Binary files differdiff --git a/examples/ex2.subx b/examples/ex2.subx
index 83b48aad..f99704de 100644
--- a/examples/ex2.subx
+++ b/examples/ex2.subx
@@ -7,17 +7,14 @@
 #   $ echo $?
 #   2
 
-== code 0x09000000
+== code
 
 Entry:
 # ebx = 1
 bb/copy-to-ebx  1/imm32
 # increment ebx
 43/increment-ebx
-# syscall(exit, ebx)
-b8/copy-to-eax  1/imm32/exit
-cd/syscall  0x80/imm8
-
-== data 0x0a000000
+# exit(ebx)
+e8/call  syscall_exit/disp32
 
 # . . vim:nowrap:textwidth=0
diff --git a/examples/ex3 b/examples/ex3
index d85aba8e..af787c11 100755
--- a/examples/ex3
+++ b/examples/ex3
Binary files differdiff --git a/examples/ex3.subx b/examples/ex3.subx
index 84789f3a..21acfd66 100644
--- a/examples/ex3.subx
+++ b/examples/ex3.subx
@@ -7,7 +7,7 @@
 #   $ echo $?
 #   55
 
-== code 0x09000000
+== 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
@@ -30,10 +30,7 @@ $loop:
     eb/jump  $loop/disp8
 
 $exit:
-    # syscall(exit, ebx)
-    b8/copy-to-eax  1/imm32/exit
-    cd/syscall  0x80/imm8
-
-== data 0x0a000000
+    # exit(ebx)
+    e8/call  syscall_exit/disp32
 
 # . . vim:nowrap:textwidth=0
diff --git a/examples/ex4 b/examples/ex4
index 66fb61e6..35ade1ee 100755
--- a/examples/ex4
+++ b/examples/ex4
Binary files differdiff --git a/examples/ex4.subx b/examples/ex4.subx
index a8e0efaa..4ef72749 100644
--- a/examples/ex4.subx
+++ b/examples/ex4.subx
@@ -4,16 +4,16 @@
 #   $ ./subx translate examples/ex4.subx -o examples/ex4
 #   $ ./subx run examples/ex4
 
-== data 0x0a000000
+== data
 
 # the global variable we save to
 X:
     0/imm32  # space for read() to write to
 
-== code 0x09000000
+== code
 
 Entry:
-# syscall(read, stdin, X, 1)
+# read(stdin, X, 1)
 # . fd = 0 (stdin)
 bb/copy-to-ebx  0/imm32
 # . data = X (location to write result to)
@@ -21,10 +21,9 @@ b9/copy-to-ecx  X/imm32
 # . size = 1 character
 ba/copy-to-edx  1/imm32
 # . syscall
-b8/copy-to-eax  3/imm32/read
-cd/syscall  0x80/imm8
+e8/call  syscall_read/disp32
 
-# syscall(write, stdout, X, 1)
+# write(stdout, X, 1)
 # . fd = 1 (stdout)
 bb/copy-to-ebx  1/imm32
 # . initialize X (location to read from)
@@ -32,11 +31,9 @@ b9/copy-to-ecx  X/imm32
 # . size = 1 character
 ba/copy-to-edx  1/imm32
 # . syscall
-b8/copy-to-eax  4/imm32/write
-cd/syscall  0x80/imm8
+e8/call  syscall_write/disp32
 
-# syscall(exit, ebx)
-b8/copy-to-eax  1/imm32/exit
-cd/syscall  0x80/imm8
+# exit(ebx)
+e8/call  syscall_exit/disp32
 
 # . . vim:nowrap:textwidth=0
diff --git a/examples/ex5 b/examples/ex5
index 37689c98..805cadc3 100755
--- a/examples/ex5
+++ b/examples/ex5
Binary files differdiff --git a/examples/ex5.subx b/examples/ex5.subx
index ad9ad29b..0ea9c5ee 100644
--- a/examples/ex5.subx
+++ b/examples/ex5.subx
@@ -4,7 +4,7 @@
 #   $ ./subx translate examples/ex5.subx -o examples/ex5
 #   $ ./subx run examples/ex5
 
-== code 0x09000000
+== 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
@@ -14,7 +14,7 @@ Entry:
     # allocate x on the stack
     81          5/subop/subtract    3/mod/direct    4/rm32/esp    .           .             .           .           .               4/imm32           # subtract from esp
 
-    # syscall(read, stdin, x, 1)
+    # read(stdin, x, 1)
     # . fd = 0 (stdin)
     bb/copy-to-ebx  0/imm32
     # . data = x (location to write result to)
@@ -22,8 +22,7 @@ Entry:
     # . size = 1 character
     ba/copy-to-edx  1/imm32
     # . syscall
-    b8/copy-to-eax  3/imm32/read
-    cd/syscall  0x80/imm8
+    e8/call  syscall_read/disp32
 
     # syscall(write, stdout, x, 1)
     # . fd = 1 (stdout)
@@ -36,10 +35,7 @@ Entry:
     b8/copy-to-eax  4/imm32/write
     cd/syscall  0x80/imm8
 
-    # syscall(exit, ebx)
-    b8/copy-to-eax  1/imm32/exit
-    cd/syscall  0x80/imm8
-
-== data 0x0a000000
+    # exit(ebx)
+    e8/call  syscall_exit/disp32
 
 # . . vim:nowrap:textwidth=0
diff --git a/examples/ex6 b/examples/ex6
index aa84591c..06fdfd7b 100755
--- a/examples/ex6
+++ b/examples/ex6
Binary files differdiff --git a/examples/ex6.subx b/examples/ex6.subx
index 396fa947..9955b201 100644
--- a/examples/ex6.subx
+++ b/examples/ex6.subx
@@ -5,13 +5,13 @@
 #   $ ./subx run examples/ex6
 #   Hello, world!
 
-== code 0x09000000
-#   instruction                     effective address                                                   register    displacement    immediate
+== code
+
 # . 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
 
 Entry:
-    # syscall(write, stdout, X, Size)
+    # write(stdout, X, Size)
     # . fd = 1 (stdout)
     bb/copy-to-ebx  1/imm32
     # . initialize X (location to write result to)
@@ -19,14 +19,12 @@ Entry:
     # . initialize Size
     8b/copy                         0/mod/indirect  5/rm32/.disp32            .             .           2/r32/edx   Size/disp32     .                 # copy *Size to edx
     # . syscall
-    b8/copy-to-eax  4/imm32/write
-    cd/syscall  0x80/imm8
+    e8/call  syscall_write/disp32
 
-    # syscall(exit, ebx)
-    b8/copy-to-eax  1/imm32/exit
-    cd/syscall  0x80/imm8
+    # exit(ebx)
+    e8/call  syscall_exit/disp32
 
-== data 0x0a000000
+== data
 
 Size:  # size of string
     0x0e/imm32  # 14
diff --git a/examples/ex7 b/examples/ex7
index 28c5bda9..0a535d45 100755
--- a/examples/ex7
+++ b/examples/ex7
Binary files differdiff --git a/examples/ex7.subx b/examples/ex7.subx
index ffef013d..cf684f86 100644
--- a/examples/ex7.subx
+++ b/examples/ex7.subx
@@ -11,88 +11,79 @@
 #   $ echo $?
 #   97
 
-== code 0x09000000
+== 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
 
 Entry:
-    # syscall(creat, Filename)
+    # creat(Filename)
     bb/copy-to-ebx  Filename/imm32
     b9/copy-to-ecx  0x180/imm32/fixed-perms
-    b8/copy-to-eax  8/imm32/creat
-    cd/syscall  0x80/imm8
+    e8/call  syscall_creat/disp32
 
-    # stream = syscall(open, Filename, O_WRONLY, 0)  # we can't use 'fd' because it looks like a hex byte
+    # stream = open(Filename, O_WRONLY, 0)  # we can't use 'fd' because it looks like a hex byte
     bb/copy-to-ebx  Filename/imm32
     b9/copy-to-ecx  1/imm32/wronly
     ba/copy-to-edx  0x180/imm32/fixed-perms
-    b8/copy-to-eax  5/imm32/open
-    cd/syscall  0x80/imm8
+    e8/call  syscall_open/disp32
     # save stream
     bb/copy-to-ebx  Stream/imm32
     89/copy                         0/mod/indirect  3/rm32/ebx    .           .             .           0/r32/eax   .               .                 # copy eax to *ebx
 
-    # syscall(write, Stream, "a", 1)
+    # write(Stream, "a", 1)
     # . load stream
     bb/copy-to-ebx  Stream/imm32
     8b/copy                         0/mod/indirect  3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # copy *ebx to ebx
     # .
     b9/copy-to-ecx  A/imm32
     ba/copy-to-edx  1/imm32/size
-    b8/copy-to-eax  4/imm32/write
-    cd/syscall  0x80/imm8
+    e8/call  syscall_write/disp32
 
-    # syscall(close, Stream)
+    # close(Stream)
     # . load stream
     bb/copy-to-ebx  Stream/imm32
     8b/copy                         0/mod/indirect  3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # copy *ebx to ebx
     # .
-    b8/copy-to-eax  6/imm32/close
-    cd/syscall  0x80/imm8
+    e8/call  syscall_close/disp32
 
-    # stream = syscall(open, Filename, O_RDONLY, 0)
+    # stream = open(Filename, O_RDONLY, 0)
     bb/copy-to-ebx  Filename/imm32
     b9/copy-to-ecx  0/imm32/rdonly
     ba/copy-to-edx  0x180/imm32/fixed-perms
-    b8/copy-to-eax  5/imm32/open
-    cd/syscall  0x80/imm8
+    e8/call  syscall_open/disp32
     # . save Stream
     bb/copy-to-ebx  Stream/imm32
     89/copy                         0/mod/indirect  3/rm32/ebx    .           .             .           0/r32/eax   .               .                 # copy eax to *ebx
 
-    # syscall(read, Stream, B, 1)
+    # read(Stream, B, 1)
     # . load stream
     bb/copy-to-ebx  Stream/imm32
     8b/copy                         0/mod/indirect  3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # copy *ebx to ebx
     # .
     b9/copy-to-ecx  B/imm32
     ba/copy-to-edx  1/imm32/size
-    b8/copy-to-eax  3/imm32/read
-    cd/syscall  0x80/imm8
+    e8/call  syscall_read/disp32
 
-    # syscall(close, Stream)
+    # close(Stream)
     # . load stream
     bb/copy-to-ebx  Stream/imm32
     8b/copy                         0/mod/indirect  3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # copy *ebx to ebx
     #
-    b8/copy-to-eax  6/imm32/close
-    cd/syscall  0x80/imm8
+    e8/call  syscall_close/disp32
 
-    # syscall(unlink, filename)
+    # unlink(filename)
     bb/copy-to-ebx  Filename/imm32
-    b8/copy-to-eax  0xa/imm32/unlink
-    cd/syscall  0x80/imm8
+    e8/call  syscall_unlink/disp32
 
-    # syscall(exit, b)
+    # exit(b)
     # . load b
     bb/copy-to-ebx  B/imm32
     8b/copy                         0/mod/indirect  3/rm32/ebx    .           .             .           3/r32/ebx   .               .                 # copy *ebx to ebx
     #
-    b8/copy-to-eax  1/imm32/exit
-    cd/syscall  0x80/imm8
+    e8/call  syscall_exit/disp32
 
-== data 0x0a000000
+== data
 
 Stream:
     0/imm32
diff --git a/examples/ex8 b/examples/ex8
index 5be0e1e6..78f1773d 100755
--- a/examples/ex8
+++ b/examples/ex8
Binary files differdiff --git a/examples/ex8.subx b/examples/ex8.subx
index 56dc1556..25191d85 100644
--- a/examples/ex8.subx
+++ b/examples/ex8.subx
@@ -14,7 +14,7 @@
 #   ...
 # Locals start from esp-4 downwards.
 
-== code 0x09000000
+== 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
@@ -32,8 +32,7 @@ Entry:
 
     # exit(eax)
     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           0/r32/eax   .               .                 # copy eax to ebx
-    b8/copy-to-eax  1/imm32/exit
-    cd/syscall  0x80/imm8
+    e8/call  syscall_exit/disp32
 
 ascii-length:  # s : (address array byte) -> n/eax
     # edx = s
@@ -56,6 +55,6 @@ $ascii-length:end:
     # return eax
     c3/return
 
-== data 0x0a000000
+== data
 
 # . . vim:nowrap:textwidth=0
diff --git a/examples/ex9 b/examples/ex9
index fce7629c..5140cf68 100755
--- a/examples/ex9
+++ b/examples/ex9
Binary files differdiff --git a/examples/ex9.subx b/examples/ex9.subx
index 8793e941..9a6105de 100644
--- a/examples/ex9.subx
+++ b/examples/ex9.subx
@@ -17,7 +17,7 @@
 #   ...
 # Locals start from esp-4 downwards.
 
-== code 0x09000000
+== 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
@@ -34,10 +34,9 @@ Entry:
     e8/call  ascii-difference/disp32
     # . . discard args
     81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
-    # syscall(exit, eax)
+    # exit(eax)
     89/copy                         3/mod/direct    3/rm32/ebx    .           .             .           0/r32/eax   .               .                 # copy eax to ebx
-    b8/copy-to-eax  1/imm32/exit
-    cd/syscall  0x80/imm8
+    e8/call  syscall_exit/disp32
 
 ascii-difference:  # (s1, s2) : null-terminated ascii strings
     # a = first letter of s1 (ecx)
@@ -50,6 +49,4 @@ ascii-difference:  # (s1, s2) : null-terminated ascii strings
     29/subtract                     3/mod/direct    0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # subtract ecx from eax
     c3/return
 
-== data 0x0a000000
-
 # . . vim:nowrap:textwidth=0
diff --git a/test_apps b/test_apps
index b5659aef..b19c837e 100755
--- a/test_apps
+++ b/test_apps
@@ -26,7 +26,7 @@ echo "== translating and running using C++"
 # example programs
 
 echo ex1
-./subx translate examples/ex1.subx  -o examples/ex1
+./subx translate 049init.linux examples/ex1.subx  -o examples/ex1
 test "$1" = 'record'  ||  git diff --exit-code examples/ex1
 test $EMULATED  &&  {
   ./subx run examples/ex1  ||  ret=$?
@@ -38,7 +38,7 @@ test $NATIVE  &&  {
 }
 
 echo ex2
-./subx translate examples/ex2.subx  -o examples/ex2
+./subx translate 049init.linux examples/ex2.subx  -o examples/ex2
 test "$1" = 'record'  ||  git diff --exit-code examples/ex2
 test $EMULATED  &&  {
   ./subx run examples/ex2  ||  ret=$?
@@ -50,7 +50,7 @@ test $NATIVE  &&  {
 }
 
 echo ex3
-./subx translate examples/ex3.subx  -o examples/ex3
+./subx translate 049init.linux examples/ex3.subx  -o examples/ex3
 test "$1" = 'record'  ||  git diff --exit-code examples/ex3
 test $EMULATED  &&  {
   ./subx run examples/ex3  ||  ret=$?
@@ -62,7 +62,7 @@ test $NATIVE  &&  {
 }
 
 echo ex4
-./subx translate examples/ex4.subx  -o examples/ex4
+./subx translate 049init.linux examples/ex4.subx  -o examples/ex4
 test "$1" = 'record'  ||  git diff --exit-code examples/ex4
 test $EMULATED  &&  {
   echo a | ./subx run examples/ex4 >ex4.out  ||  true
@@ -74,7 +74,7 @@ test $NATIVE  &&  {
 }
 
 echo ex5
-./subx translate examples/ex5.subx  -o examples/ex5
+./subx translate 049init.linux examples/ex5.subx  -o examples/ex5
 test "$1" = 'record'  ||  git diff --exit-code examples/ex5
 test $EMULATED  &&  {
   echo a | ./subx run examples/ex5 >ex5.out  ||  true
@@ -86,7 +86,7 @@ test $NATIVE  &&  {
 }
 
 echo ex6
-./subx translate examples/ex6.subx  -o examples/ex6
+./subx translate 049init.linux examples/ex6.subx  -o examples/ex6
 test "$1" = 'record'  ||  git diff --exit-code examples/ex6
 test $EMULATED  &&  {
   ./subx run examples/ex6 >ex6.out  ||  true
@@ -98,7 +98,7 @@ test $NATIVE  &&  {
 }
 
 echo ex7
-./subx translate examples/ex7.subx  -o examples/ex7
+./subx translate 049init.linux examples/ex7.subx  -o examples/ex7
 test "$1" = 'record'  ||  git diff --exit-code examples/ex7
 test $EMULATED  &&  {
   ./subx run examples/ex7  ||  ret=$?
@@ -110,7 +110,7 @@ test $NATIVE  &&  {
 }
 
 echo ex8
-./subx translate examples/ex8.subx  -o examples/ex8
+./subx translate 049init.linux examples/ex8.subx  -o examples/ex8
 test "$1" = 'record'  || git diff --exit-code examples/ex8
 test $EMULATED  &&  {
   ./subx run examples/ex8 abcd  ||  ret=$?
@@ -122,7 +122,7 @@ test $NATIVE  &&  {
 }
 
 echo ex9
-./subx translate examples/ex9.subx  -o examples/ex9
+./subx translate 049init.linux examples/ex9.subx  -o examples/ex9
 test "$1" = 'record'  || git diff --exit-code examples/ex9
 test $EMULATED  &&  {
   ./subx run examples/ex9 z x  ||  ret=$?
@@ -134,7 +134,7 @@ test $NATIVE  &&  {
 }
 
 echo ex10
-./subx translate examples/ex10.subx  -o examples/ex10
+./subx translate 049init.linux examples/ex10.subx  -o examples/ex10
 test "$1" = 'record'  || git diff --exit-code examples/ex10
 test $EMULATED  &&  {
   ./subx run examples/ex10 abc abc  ||  ret=$?
@@ -148,7 +148,7 @@ test $NATIVE  &&  {
 }
 
 echo ex11
-./subx translate examples/ex11.subx  -o examples/ex11
+./subx translate 049init.linux examples/ex11.subx  -o examples/ex11
 test "$1" = 'record'  || git diff --exit-code examples/ex11
 test $EMULATED  &&  {
   ./subx run examples/ex11
@@ -160,7 +160,7 @@ test $NATIVE  &&  {
 }
 
 echo ex12
-./subx translate examples/ex12.subx  -o examples/ex12
+./subx translate 049init.linux examples/ex12.subx  -o examples/ex12
 test "$1" = 'record'  || git diff --exit-code examples/ex12
 test $EMULATED  &&  ./subx run examples/ex12  # final byte of mmap'd address is well-nigh guaranteed to be 0
 test $NATIVE  &&  examples/ex12
@@ -168,7 +168,7 @@ test $NATIVE  &&  examples/ex12
 # Larger apps that use the standard library.
 
 echo factorial
-./subx translate 0*.subx apps/factorial.subx  -o apps/factorial
+./subx translate 049init.linux 0*.subx apps/factorial.subx  -o apps/factorial
 test "$1" = 'record'  ||  git diff --exit-code apps/factorial
 test $EMULATED  &&  {
   ./subx run apps/factorial  ||  ret=$?
@@ -184,7 +184,7 @@ test $NATIVE  &&  {
 }
 
 echo crenshaw2-1
-./subx translate 0*.subx apps/crenshaw2-1.subx  -o apps/crenshaw2-1
+./subx translate 049init.linux 0*.subx apps/crenshaw2-1.subx  -o apps/crenshaw2-1
 test "$1" = 'record'  ||  git diff --exit-code apps/crenshaw2-1
 test $EMULATED  &&  {
   ./subx run apps/crenshaw2-1 test
@@ -196,7 +196,7 @@ test $NATIVE  &&  {
 }
 
 echo crenshaw2-1b
-./subx translate 0*.subx apps/crenshaw2-1b.subx  -o apps/crenshaw2-1b
+./subx translate 049init.linux 0*.subx apps/crenshaw2-1b.subx  -o apps/crenshaw2-1b
 test "$1" = 'record'  ||  git diff --exit-code apps/crenshaw2-1b
 test $EMULATED  &&  {
   ./subx run apps/crenshaw2-1b test
@@ -208,7 +208,7 @@ test $NATIVE  &&  {
 }
 
 echo handle
-./subx translate 0*.subx apps/handle.subx  -o apps/handle
+./subx translate 049init.linux 0*.subx apps/handle.subx  -o apps/handle
 test "$1" = 'record'  ||  git diff --exit-code apps/handle
 test $EMULATED  &&  {
   ./subx run apps/handle > handle.out 2>&1  ||  true
@@ -224,7 +224,7 @@ test $NATIVE  &&  {
 # Phases of the self-hosted SubX translator.
 
 echo hex
-./subx translate 0*.subx apps/subx-common.subx apps/hex.subx  -o apps/hex
+./subx translate 049init.linux 0*.subx apps/subx-common.subx apps/hex.subx  -o apps/hex
 test "$1" = 'record'  ||  git diff --exit-code apps/hex
 test $EMULATED  &&  {
   ./subx run apps/hex test
@@ -236,7 +236,7 @@ test $NATIVE  &&  {
 }
 
 echo survey
-./subx translate 0*.subx apps/subx-common.subx apps/survey.subx  -o apps/survey
+./subx translate 049init.linux 0*.subx apps/subx-common.subx apps/survey.subx  -o apps/survey
 test "$1" = 'record'  ||  git diff --exit-code apps/survey
 test $EMULATED  &&  {
   ./subx run apps/survey test
@@ -248,7 +248,7 @@ test $NATIVE  &&  {
 }
 
 echo pack
-./subx translate 0*.subx apps/subx-common.subx apps/pack.subx  -o apps/pack
+./subx translate 049init.linux 0*.subx apps/subx-common.subx apps/pack.subx  -o apps/pack
 test "$1" = 'record'  ||  git diff --exit-code apps/pack
 test $EMULATED  &&  {
   ./subx run apps/pack test
@@ -260,7 +260,7 @@ test $NATIVE  &&  {
 }
 
 echo assort
-./subx translate 0*.subx apps/subx-common.subx apps/assort.subx  -o apps/assort
+./subx translate 049init.linux 0*.subx apps/subx-common.subx apps/assort.subx  -o apps/assort
 test "$1" = 'record'  ||  git diff --exit-code apps/assort
 test $EMULATED  &&  {
   ./subx run apps/assort test
@@ -272,7 +272,7 @@ test $NATIVE  &&  {
 }
 
 echo dquotes
-./subx translate 0*.subx apps/subx-common.subx apps/dquotes.subx  -o apps/dquotes
+./subx translate 049init.linux 0*.subx apps/subx-common.subx apps/dquotes.subx  -o apps/dquotes
 test "$1" = 'record'  ||  git diff --exit-code apps/dquotes
 test $EMULATED  &&  {
   ./subx run apps/dquotes test
@@ -284,7 +284,7 @@ test $NATIVE  &&  {
 }
 
 echo tests
-./subx translate 0*.subx apps/subx-common.subx apps/tests.subx  -o apps/tests
+./subx translate 049init.linux 0*.subx apps/subx-common.subx apps/tests.subx  -o apps/tests
 test "$1" = 'record'  ||  git diff --exit-code apps/tests
 test $EMULATED  &&  {
   ./subx run apps/tests test
@@ -298,7 +298,7 @@ test $NATIVE  &&  {
 # Higher-level syntax.
 
 echo sigils
-./subx translate 0*.subx apps/subx-common.subx apps/sigils.subx  -o apps/sigils
+./subx translate 049init.linux 0*.subx apps/subx-common.subx apps/sigils.subx  -o apps/sigils
 [ "$1" != record ]  &&  git diff --exit-code apps/sigils
 ./subx run apps/sigils test
 echo
@@ -313,7 +313,7 @@ test $NATIVE  ||  exit 0
 
 echo calls
 cat 0*.subx apps/subx-common.subx apps/calls.subx  |  apps/sigils  > a.sigils
-./subx translate a.sigils -o apps/calls
+./subx translate 049init.linux a.sigils -o apps/calls
 [ "$1" != record ]  &&  git diff --exit-code apps/calls
 ./subx run apps/calls test
 echo
@@ -329,7 +329,7 @@ echo "== translating using SubX"
 for n in `seq 1 12`
 do
   echo ex$n
-  ./ntranslate examples/ex$n.subx
+  ./ntranslate 049init.linux examples/ex$n.subx
   diff examples/ex$n a.elf
 done
 
@@ -338,7 +338,7 @@ done
 for app in factorial crenshaw2-1 crenshaw2-1b handle
 do
   echo $app
-  ./ntranslate 0*.subx apps/$app.subx
+  ./ntranslate 049init.linux 0*.subx apps/$app.subx
   diff apps/$app a.elf
 done
 
@@ -347,7 +347,7 @@ done
 for app in hex survey pack assort dquotes tests sigils calls
 do
   echo $app
-  ./ntranslate 0*.subx apps/subx-common.subx apps/$app.subx
+  ./ntranslate 049init.linux 0*.subx apps/subx-common.subx apps/$app.subx
   diff apps/$app a.elf
 done