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.
This commit is contained in:
parent
f559236bdf
commit
c48ce3c8bf
|
@ -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
|
||||
|
|
|
@ -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
|
BIN
apps/assort
BIN
apps/assort
Binary file not shown.
BIN
apps/braces
BIN
apps/braces
Binary file not shown.
BIN
apps/calls
BIN
apps/calls
Binary file not shown.
BIN
apps/crenshaw2-1
BIN
apps/crenshaw2-1
Binary file not shown.
Binary file not shown.
BIN
apps/dquotes
BIN
apps/dquotes
Binary file not shown.
BIN
apps/factorial
BIN
apps/factorial
Binary file not shown.
|
@ -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-=
|
||||
|
|
BIN
apps/handle
BIN
apps/handle
Binary file not shown.
BIN
apps/sigils
BIN
apps/sigils
Binary file not shown.
BIN
apps/survey
BIN
apps/survey
Binary file not shown.
BIN
apps/tests
BIN
apps/tests
Binary file not shown.
|
@ -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
|
||||
#
|
||||
|
|
45
mu-init.subx
45
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)
|
||||
|
|
Loading…
Reference in New Issue