about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKartik Agaram <vc@akkartik.com>2020-03-15 21:03:12 -0700
committerKartik Agaram <vc@akkartik.com>2020-03-15 21:03:12 -0700
commitc48ce3c8bfb6d1578f2530ed84b8e7b25d435b6d (patch)
tree9a7b23b95d9960853aad1be4e6e95b12f300ade8
parentf559236bdf9103c5f88d8dfc098f3afe3de64e4a (diff)
downloadmu-c48ce3c8bfb6d1578f2530ed84b8e7b25d435b6d.tar.gz
6153 - switch 'main' to use Mu strings
At the SubX level we have to put up with null-terminated kernel strings
for commandline args. But so far we haven't done much with them. Rather
than try to support them we'll just convert them transparently to standard
length-prefixed strings.

In the process I realized that it's not quite right to treat the combination
of argc and argv as an array of kernel strings. Argc counts the number
of elements, whereas the length of an array is usually denominated in bytes.
-rw-r--r--069allocate.subx32
-rw-r--r--102kernel-string.subx89
-rwxr-xr-xapps/assortbin40852 -> 40886 bytes
-rwxr-xr-xapps/bracesbin42658 -> 42692 bytes
-rwxr-xr-xapps/callsbin47319 -> 47353 bytes
-rwxr-xr-xapps/crenshaw2-1bin40260 -> 40294 bytes
-rwxr-xr-xapps/crenshaw2-1bbin40807 -> 40841 bytes
-rwxr-xr-xapps/dquotesbin44502 -> 44536 bytes
-rwxr-xr-xapps/factorialbin39279 -> 39313 bytes
-rw-r--r--apps/factorial.mu14
-rwxr-xr-xapps/handlebin40177 -> 40211 bytes
-rwxr-xr-xapps/hexbin43099 -> 43133 bytes
-rwxr-xr-xapps/mubin210747 -> 210914 bytes
-rwxr-xr-xapps/packbin53244 -> 53278 bytes
-rwxr-xr-xapps/sigilsbin55043 -> 55077 bytes
-rwxr-xr-xapps/surveybin50093 -> 50127 bytes
-rwxr-xr-xapps/testsbin39650 -> 39684 bytes
-rw-r--r--mu-init-test.subx8
-rw-r--r--mu-init.subx45
19 files changed, 170 insertions, 18 deletions
diff --git a/069allocate.subx b/069allocate.subx
index 48ba9413..503d151f 100644
--- a/069allocate.subx
+++ b/069allocate.subx
@@ -234,4 +234,36 @@ $allocate-region:abort:
     cd/syscall  0x80/imm8
     # never gets here
 
+# Claim the next 'n+4' bytes of memory and initialize the first 4 to n.
+# Abort if there isn't enough memory in 'ad'.
+allocate-array:  # ad: (addr allocation-descriptor), n: int -> result/eax: (addr _)
+    # . prologue
+    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
+    # ecx = n
+    8b/copy                         1/mod/*+disp8   5/rm32/ebp    .           .             .           1/r32/ecx   0xc/disp8       .                 # copy *(ebp+0xc) to ecx
+    # var size/edx: int = n+4
+    8d/copy-address                 1/mod/*+disp8   1/rm32/ecx    .           .             .           2/r32/edx   4/disp8         .                 # copy ecx+4 to edx
+    # result = allocate(ad, size)
+    # . . push args
+    52/push-edx
+    ff          6/subop/push        1/mod/*+disp8   5/rm32/ebp    .           .             .           .           8/disp8         .                 # push *(ebp+8)
+    # . . call
+    e8/call  allocate/disp32
+    # . . discard args
+    81          0/subop/add         3/mod/direct    4/rm32/esp    .           .             .           .           .               8/imm32           # add to esp
+    # *result = n
+    89/copy                         0/mod/indirect  0/rm32/eax    .           .             .           1/r32/ecx   .               .                 # copy ecx to *eax
+$allocate-array:end:
+    # . restore registers
+    5a/pop-to-edx
+    59/pop-to-ecx
+    # . epilogue
+    89/copy                         3/mod/direct    4/rm32/esp    .           .             .           5/r32/ebp   .               .                 # copy ebp to esp
+    5d/pop-to-ebp
+    c3/return
+
 # . . vim:nowrap:textwidth=0
diff --git a/102kernel-string.subx b/102kernel-string.subx
new file mode 100644
index 00000000..ca92d813
--- /dev/null
+++ b/102kernel-string.subx
@@ -0,0 +1,89 @@
+# We can't really do much with null-terminated kernel strings, and we don't
+# want to. Let's turn them into regular length-prefixed strings at the first
+# opportunity.
+
+== code
+
+kernel-string-to-string:  # ad: (addr allocation-descriptor), in: (addr kernel-string) -> result/eax: (addr array byte)
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+    51/push-ecx
+    52/push-edx
+    53/push-ebx
+    56/push-esi
+    57/push-edi
+    # var len/ecx: int = length(in)
+    (kernel-string-length *(ebp+0xc))
+    89/<- %ecx 0/r32/eax
+    # result = allocate-array(ad, len)
+    (allocate-array *(ebp+8) %ecx)  # => eax
+    # var c/edx: byte = 0
+    ba/copy-to-edx 0/imm32
+    # var src/esi: (addr byte) = in
+    8b/-> *(ebp+0xc) 6/r32/esi
+    # var dest/edi: (addr byte) = result->data
+    8d/copy-address *(eax+4) 7/r32/edi
+    {
+$kernel-string-to-string:loop:
+      # c = *src
+      8a/byte-> *esi 2/r32/edx
+      # if (c == 0) break
+      81 7/subop/compare %edx 0/imm32
+      74/jump-if-= break/disp8
+      # *dest = c
+      88/byte<- *edi 2/r32/edx
+      # ++src
+      46/increment-esi
+      # ++dest
+      47/increment-edi
+      eb/jump loop/disp8
+    }
+$kernel-string-to-string:end:
+    # . restore registers
+    5f/pop-to-edi
+    5e/pop-to-esi
+    5b/pop-to-ebx
+    5a/pop-to-edx
+    59/pop-to-ecx
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
+
+kernel-string-length:  # in: (addr kernel-string) -> result/eax: int
+    # . prologue
+    55/push-ebp
+    89/<- %ebp 4/r32/esp
+    # . save registers
+    51/push-ecx
+    52/push-edx
+    # result = 0
+    b8/copy-to-eax 0/imm32
+    # var c/ecx: byte = 0
+    b9/copy-to-ecx 0/imm32
+    # var curr/edx: (addr byte) = in
+    8b/-> *(ebp+8) 2/r32/edx
+    {
+$kernel-string-length:loop:
+      # c = *curr
+      8a/byte-> *edx 1/r32/ecx
+      # if (c == 0) break
+      81 7/subop/compare %ecx 0/imm32
+      74/jump-if-= break/disp8
+      # ++curr
+      42/increment-edx
+      # ++result
+      40/increment-eax
+      #
+      eb/jump loop/disp8
+    }
+$kernel-string-length:end:
+    # . restore registers
+    5a/pop-to-edx
+    59/pop-to-ecx
+    # . epilogue
+    89/<- %esp 5/r32/ebp
+    5d/pop-to-ebp
+    c3/return
diff --git a/apps/assort b/apps/assort
index 980e294d..0dacda05 100755
--- a/apps/assort
+++ b/apps/assort
Binary files differdiff --git a/apps/braces b/apps/braces
index 0de3adb7..318f8309 100755
--- a/apps/braces
+++ b/apps/braces
Binary files differdiff --git a/apps/calls b/apps/calls
index 4015ed83..1ffc0b94 100755
--- a/apps/calls
+++ b/apps/calls
Binary files differdiff --git a/apps/crenshaw2-1 b/apps/crenshaw2-1
index ce6d02d7..fe3bdfc1 100755
--- a/apps/crenshaw2-1
+++ b/apps/crenshaw2-1
Binary files differdiff --git a/apps/crenshaw2-1b b/apps/crenshaw2-1b
index d429e9c6..30266c2a 100755
--- a/apps/crenshaw2-1b
+++ b/apps/crenshaw2-1b
Binary files differdiff --git a/apps/dquotes b/apps/dquotes
index fd1bae17..5a3d8aa0 100755
--- a/apps/dquotes
+++ b/apps/dquotes
Binary files differdiff --git a/apps/factorial b/apps/factorial
index e21f6dfa..73a3417f 100755
--- a/apps/factorial
+++ b/apps/factorial
Binary files differdiff --git a/apps/factorial.mu b/apps/factorial.mu
index 83b2bedf..55bee98e 100644
--- a/apps/factorial.mu
+++ b/apps/factorial.mu
@@ -31,21 +31,21 @@ fn test-factorial {
   check-ints-equal result 0x78 "F - test-factorial"
 }
 
-fn main args: (addr array kernel-string) -> exit-status/ebx: int {
-  var a/eax: (addr array kernel-string) <- copy args
+fn main args: (addr array string) -> exit-status/ebx: int {
+  var a/eax: (addr array string) <- copy args
   var tmp/ecx: int <- length a
   $main-body: {
-    compare tmp, 1
-    # if (len(args) == 1) factorial(5)
+    # if (len(args) <= 4) factorial(5)
+    compare tmp, 4
     {
-      break-if-!=
+      break-if->
       var tmp/eax: int <- factorial 5
       exit-status <- copy tmp
       break $main-body
     }
     # if (args[1] == "test") run-tests()
-    var tmp2/ecx: (addr kernel-string) <- index a, 1
-    var tmp3/eax: boolean <- kernel-string-equal? *tmp2, "test"
+    var tmp2/ecx: (addr string) <- index a, 1
+    var tmp3/eax: boolean <- string-equal? *tmp2, "test"
     compare tmp3, 0
     {
       break-if-=
diff --git a/apps/handle b/apps/handle
index 76fd78ee..77834947 100755
--- a/apps/handle
+++ b/apps/handle
Binary files differdiff --git a/apps/hex b/apps/hex
index d91286e0..2f14cc9a 100755
--- a/apps/hex
+++ b/apps/hex
Binary files differdiff --git a/apps/mu b/apps/mu
index 17916ee9..4b34fd01 100755
--- a/apps/mu
+++ b/apps/mu
Binary files differdiff --git a/apps/pack b/apps/pack
index ceeeb153..f788a54a 100755
--- a/apps/pack
+++ b/apps/pack
Binary files differdiff --git a/apps/sigils b/apps/sigils
index c738b004..7035952d 100755
--- a/apps/sigils
+++ b/apps/sigils
Binary files differdiff --git a/apps/survey b/apps/survey
index 49905f1a..58589cb5 100755
--- a/apps/survey
+++ b/apps/survey
Binary files differdiff --git a/apps/tests b/apps/tests
index 39c29b36..08005a42 100755
--- a/apps/tests
+++ b/apps/tests
Binary files differdiff --git a/mu-init-test.subx b/mu-init-test.subx
index 6cfe51b2..1b2d1683 100644
--- a/mu-init-test.subx
+++ b/mu-init-test.subx
@@ -1,10 +1,10 @@
 # Just a test stub for mu-init.subx
 #
 # Try it out like this:
-#   $ ./translate_subx init.linux 0*.subx mu-init.subx mu-init-test.subx
+#   $ ./translate_subx init.linux [0-9]*.subx mu-init.subx mu-init-test.subx
 #   $ ./a.elf  # should run all tests
 
-main:  # args: (address array kernel-string) -> result/ebx: int
+main:  # args: (addr array (addr array byte)) -> result/ebx: int
     # . prologue
     55/push-ebp
     89/<- %ebp 4/r32/esp
@@ -15,10 +15,10 @@ main:  # args: (address array kernel-string) -> result/ebx: int
     8b/-> *(ebp+8) 6/r32/esi
     {
       # if (argc <= 1) break
-      81 7/subop/compare *esi 1/imm32
+      81 7/subop/compare *esi 4/imm32
       7e/jump-if-<= break/disp8
       # if (argv[1] != "test") break
-      (kernel-string-equal? *(esi+8) "test")  # => eax
+      (string-equal? *(esi+8) "test")  # => eax
       3d/compare-eax-and 0/imm32
       74/jump-if-= break/disp8
       #
diff --git a/mu-init.subx b/mu-init.subx
index fb15efbf..2377822e 100644
--- a/mu-init.subx
+++ b/mu-init.subx
@@ -3,7 +3,7 @@
 # See translate_mu for how this file is used.
 #
 # Mu programs start at a function called 'main' with this signature:
-#   fn main args: (addr array kernel-string) -> exit-status/ebx: int
+#   fn main args: (addr array (addr array byte)) -> exit-status/ebx: int
 # If your program doesn't need commandline arguments you can drop it:
 #   fn main -> exit-status/ebx: int
 #
@@ -15,11 +15,42 @@
 Entry:
     # we don't use ebp in Entry; just initialize it
     bd/copy-to-ebp 0/imm32
-    # var args/eax: (addr array kernel-string)
-    89/<- %eax 4/r32/esp
-    # initialize the heap
+    # - save argc and argv
+    # var argc-and-argv/esi
+    89/<- %esi 4/r32/esp
+$Entry:initialize-heap:
+    # - initialize the heap
     (new-segment *Heap-size Heap)
-    # run Mu program
-    (main %eax)
-    # exit
+$Entry:initialize-args:
+    # - convert argv from null-terminated 'kernel' strings to length-prefixed Mu strings
+    # var argc/edx: int
+    8b/-> *esi 2/r32/edx
+    # argc is in words; convert it to bytes
+    c1/shift 4/subop/left %edx 2/imm8
+    # var args/edi: (addr array (addr array byte))
+    (allocate-array Heap %edx)  # => eax
+    89/<- %edi 0/r32/eax
+    # var curr/ecx: (addr kernel-string) = argv
+    8d/copy-address *(esi+4) 1/r32/ecx
+    # var max/edx: (addr kernel-string) = argv+4+argc
+    8d/copy-address *(ecx+edx) 2/r32/edx
+    # var dest/esi: (addr (addr array byte)) = args+4
+    8d/copy-address *(edi+4) 6/r32/esi
+    {
+      # if (curr >= max) break
+      39/compare %ecx 2/r32/edx
+      73/jump-if-addr>= break/disp8
+      # *dest = kernel-string-to-string(*curr)
+      (kernel-string-to-string Heap *ecx)  # => eax
+      89/<- *esi 0/r32/eax
+      # curr += 4
+      81 0/subop/add %ecx 4/imm32
+      # dest += 4
+      81 0/subop/add %esi 4/imm32
+      #
+      eb/jump loop/disp8
+    }
+    # - run Mu program
+    (main %edi)  # => ebx
+    # - exit
     (syscall_exit)