Skip to content
Browse files

Got the compiler to the point where it can successfully compile a pro…

…gram that just exits.

So now the program's execution environment is set up to the point where it
won't crash instantly, and it can make system calls.
  • Loading branch information...
1 parent 46f331e commit a7dc22860eb247ad9d4dea1d9b3c1b4b931d37ea @kragen committed Oct 9, 2008
Showing with 35 additions and 2 deletions.
  1. +1 −0 .gitignore
  2. +2 −0 Q.tbf1
  3. +3 −0 build
  4. +3 −0 tinyboot.s
  5. +26 −2 tinyboot1.tbf1
View
1 .gitignore
@@ -5,3 +5,4 @@ tb2
hello42
a.out
tmp.*
+Q
View
2 Q.tbf1
@@ -0,0 +1,2 @@
+( program that just quits, in tbf1 tinybootforth )
+^ Q
View
3 build
@@ -3,6 +3,9 @@ set -ve
if ! ./tinyboot.py hello42.tbf1 > hello42; then cat hello42; exit 1; fi
chmod 755 hello42
./hello42 || echo $?
+if ! ./tinyboot.py tinyboot1.tbf1 < Q.tbf1 > Q; then cat Q; exit 1; fi
+chmod 755 Q
+strace ./Q
if ! ./tinyboot.py tinyboot1.tbf1 < tinyboot1.tbf1 > tb1; then cat tb1; exit 1; fi
chmod 755 tb1
./tb1 || echo $?
View
3 tinyboot.s
@@ -40,3 +40,6 @@ jump: test %eax, %eax
bar: nop
rshift: pop %ecx
sar %cl, %eax
+init: mov %esp, %ebp
+ sub $2048, %ebp
+
View
28 tinyboot1.tbf1
@@ -14,6 +14,7 @@ space, newline — ignored
: — defines a function
Run-time primitives:
+G — gets a byte from stdin
W — given an address and size on the stack, writes the specified number of
bytes to stdout
Q — exits the program with a return code of 0
@@ -23,6 +24,9 @@ Q — exits the program with a return code of 0
~ — bitwise-negates a word
; — returns from a function
< — a less-than test
+m — not used directly since the interpreter doesn't implement it,
+ this invokes an arbitrary system call with up to three arguments.
+ The compiler's implementations of G, W, and Q use this.
Defined in this file, all necessarily run-time:
h — the ELF header
@@ -63,6 +67,7 @@ n — parse a number from input and push it on the compile-time stack
J — compile a forward conditional jump [
P — resolve a forward conditional jump ]
j — compile a backwards negative conditional jump }
+M — the location in the compiler's memory for the system call routine
)
v h ( ELF header, Elf32_Ehdr )
@@ -89,9 +94,21 @@ v h ( ELF header, Elf32_Ehdr )
( p_flags:) # 7 ( p_align:) # 4096
v `
+( some simple code that doesn't do anything useful )
( mov bl, 42) b 179 b 42
( inc eax) b 64
( int 0x80) b 205 b 128
+
+v M ( system call routine; called in program with lowercase `m`)
+ ( syscall number already in %eax )
+( xchg %ebp, %esp) b 135 b 236
+ ( pop %ebx) b 91
+ ( pop %ecx) b 89
+ ( pop %edx) b 90
+ ( int 0x80) b 205 b 128
+( xchg %ebp, %esp) b 135 b 236
+ ( ret) b 195
+
v $ * 4096 ( 4096 bytes should be plenty for ANY program! ☺ )
( this space for compiling the program eventually has to move to the end of
everything, so it can expand. something like : $ h 8192 + ; )
@@ -179,13 +196,20 @@ v B # 0 ( buffer for w )
d F T + @ [ & ; ] ( if it’s in the table, dispatch to & )
d I [ 48 - n L ; ] ( if it’s a digit, parse a number, compile code
to push that number immediate )
+ d 81 = [ p 0 L 0 L 0 L ( Q calls _exit(0, 0, 0)
+ 1 L 109 & ; ] ( system call #1 (__NR_exit) ( syscall is `m` )
+ d 87 = [ p 1 L 4 L 109 & ; ] ( W calls write(1, x, y) ( syscall #4 )
+ d 94 = [ p H @ h - o @ + e ! ( ^ sets the entry point e, a virtual address )
+ 137 . 229 . ( mov %esp, %ebp to initialize %ebp to %esp-2048 )
+ 129 . 237 . 0 . 8 . 0 . 0 . ; ] ( sub $2048, %ebp )
. ; ( default is to copy to output )
: K ( routine to "kompile" input to output )
{ G d 0 1 - = [ p ; ] ( return if char is -1 )
D 1 }
-^ ` h - o @ + e ! ( set entry point correctly wrt origin )
+^
+M H ! 109 C ( register `m` routine for system calls using dummy `H` )
$ H ! ( initialize H )
-K ( copy input into output )
+K ( compile input into output )
H @ h - S ! ( subtract h from H to get size of whole program )
h S @ W Q

0 comments on commit a7dc228

Please sign in to comment.
Something went wrong with that request. Please try again.