#10biForthOS a full 8086 OS in 46 bytes
10biForthOS = 10b(2) i(nstructions) Forth OS is a very primitive Forth with only two instructions:
- 1 is compile
- 0 is execute
It is heavily inspired by Frank Sergeant 3-Instruction Forth and is a strip down exercise following up SectorForth, SectorLisp, SectorC (the C compiler used here) and milliForth.
Here is the full OS code in 46 bytes of 8086 assembly opcodes:
50b8 8e00 31d8 e8ff 0017 003c 0575 00ea 5000 3c00 7401 eb02 e8ee 0005 0588 eb47 b8e6 0200 d231 14cd e480 7580 c3f4#Overview
When loaded after the boot, 10biForthOS listen on the serial port for instructions (a keyboard version and an x64 port in 217 bytes are also provided).
The 1 instuction should be followed by a byte of an assembly opcode to be compiled into a fixed memory location.
The 0 instruction launch the compiled program.
And that's it!
On a host computer you can then send commands to 10biForthOS.
As examples a subleq-eForth or even SectorC can be used to code in eForth or C.
#Usage
Build 10biForthOS floppy
$ make 10biForthOS.flp nasm -f bin 10biForthOS.asm -o 10biForthOS.com wc -c 10biForthOS.com 46 10biForthOS.com nasm -DPAD_ZERO -f bin 10biForthOS.asm -o 10biForthOS.com dd status=noxfer conv=notrunc if=10biForthOS.com of=10biForthOS.flp 1+0 records in 1+0 records outBoot the machine (here qemu) or simply type make to build and boot the machine:
$ ./boot &The OS is waiting input on the serial port.
Send the hello world example on the serial port:
The send command translate the above opcodes in a sequence of 1 command followed with a byte of the opcode.
1 B8 1 00 1 7E 1 8E 1 C0 1 30 1 FF 1...Formatted like the disassembled code it looks like this:
00000000 1 B8 1 00 1 7E mov ax,0x7e00 00000003 1 8E 1 C0 mov es,ax 00000005 1 30 1 FF xor bh,bh ... ...Send a 0
$ ./send 0Enjoy!
Test the keyboard:
$ ./send examples/echo-kbd.asm 00000000 E81200 call 0x15 00000003 3C0D cmp al,0xd 00000005 741A jz 0x21 ... ... 00000026 B00A mov al,0xa 00000028 E8EFFF call 0x1a 0000002B EBD3 jmp short 0x0Send a 0
$ ./send 0Ok the keyboard is up:
Then send the subleq-eForth example to start programming in Forth:
$ ./send examples/subleq-eForth/subleq-eForth.asm 00000000 30E4 xor ah,ah 00000002 B002 mov al,0x2 00000004 CD10 int 0x10 ... ... 00004FAC 94 xchg ax,sp 00004FAD 0B39 or di,[bx+di] 00004FAF 04 db 0x04Send a 0
$ ./send 0Write your code in Forth!!
Then send the fat :-) SectorC example to program in C:
./send examples/sectorc/sectorc.s 00000000 680030 push word 0x3000 00000003 1F pop ds 00000004 680020 push word 0x2000 ... ... 000001E5 009EC099 add [bp-0x6640],bl 000001E9 009DC000 add [di+0xc0],bl 000001ED 00 db 0x00Send a 0
$ ./send 0Write your code in C!!!
$ ./cat_sectorc hello.c | ./to-serialor (you have to reset the machine for now)
$ ./cat_sectorc sinwave.c | ./to-serialSend a 0
$ ./send 0Shutdown the machine:
$ ./send examples/shutdown.asm 00000000 B80010 mov ax,0x1000 00000003 8ED0 mov ss,ax 00000005 BC00F0 mov sp,0xf000 ... ... 0000000B BB0100 mov bx,0x1 0000000E B90300 mov cx,0x3 00000011 CD15 int 0x15Send a 0
$ ./send 0The machine shutdown.
#How this works
Pseudocode description:
- Initialize the processor.
- Initialize the communication channel (serial port, keyboard...).
- Initialize a position pointer to a fixed position.
- Repeat the following forever:
Get a byte from the communication channel.
If byte = 0 [execute]
Jump to the subroutine at the fixed position.
Else If byte = 1 [compile]
A. Get a byte from the communication channel.
B. Store the byte at the position pointer.
C. Increment the position pointer.
End If.
#Full code:
#Keyboard version:
Boot the machine (here qemu)
$ ./boot &The OS is waiting input from the keyboard.
Type the hello world example with the keyboard (1 [opcode] 1 [opcode] ...).
transl type it for you:
Type a 0 with the keyboard and tada:
#Questions
-
Is this a Forth?
It seems to be: it has an outer interpreter which understand assembly opcodes and an inner interpreter: the standard machine code.
You can load/redefine code at will.Even if it lacks stacks, dictionnary, defining words, etc. It has the simplicity and hacky feeling of Forth.
-
Is this an OS?
Once booted you can interract with the screen, the keyboard, the file system and so on.
Once the Forth interpreter or the C compiler are loaded, you can program in Forth or C.Doesn't it look like an OS?
-
Why?
Why not? More seriously. It's quite pleasant to be able to write an OS with so little code and be able to extend it while it is running.