commit ba898f21322607c5025b3b911022b536a5d0d943 Author: Quinten Kock Date: Mon Jul 17 08:21:15 2023 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dcade53 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +sectcl.bin diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f9f9a0c --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +sectcl.bin: sectcl.nasm + nasm sectcl.nasm -f bin -o sectcl.bin + +hexdump: sectcl.bin + hexdump -C sectcl.bin + +qemu: sectcl.bin + qemu-system-i386 -fda sectcl.bin + +gdb: sectcl.bin + gdb -ex "target remote | qemu-system-i386 -S -gdb stdio -fda sectcl.bin -m 16" -ex "break *0x7c00" -ex "continue" + +objdump: sectcl.bin + objdump -D -Mintel,i8086 -b binary -m i386 sectcl.bin + +quecl: quecl.c + gcc -Os -o quecl quecl.c -Wall -Wextra + +clean: + rm sectcl.bin diff --git a/README.md b/README.md new file mode 100644 index 0000000..7f6f6fc --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# An attempt at a single-sector x86-16 Tcl interpreter +Inspired by sectorFORTH, sectorLISP and Picol. diff --git a/quecl.c b/quecl.c new file mode 100644 index 0000000..bab931d --- /dev/null +++ b/quecl.c @@ -0,0 +1,64 @@ +// Quecl - a quecto-sized Tcl-inspired programming language + +#include +#include +#define MEM_SIZE 32 * 1024 // 32 kilobytes +char MEMORY[MEM_SIZE]; +size_t basepointer = 0; +size_t stack = 0; + +size_t GetLine() { + // reads a line of user input into MEMORY + char c; + size_t ptr = stack; + do { + c = getchar(); + MEMORY[stack++] = c; + } while (c != '\n'); + MEMORY[stack++] = 0; + return ptr; +} + +size_t GetVerbatim(size_t start) { + // Verbatim words are words that start with { + // Braces nest and can be escaped + unsigned int level = 0; // first char is { + size_t ptr = stack; + char c; + do { + c = MEMORY[start++]; + // TODO: implement \-escaping + if(c == '{') level++; + if(c == '}') level--; + MEMORY[stack++] = 0; + } while(c != 0 && level > 0); + MEMORY[stack++] = 0; + return ptr; +} + +size_t GetWord(size_t start) { + // Start indicates a memory address + // Returns a single "word" + // Rules of tcl words: [] (and $) work everywhere + // having { at the start means that the string is verbatim + // {} can be nested + // [] is command substitution: essentially calling eval + if(MEMORY[start] == '{') return GetVerbatim(start); + + int quote = MEMORY[start] == '"'; + + char c; + size_t ptr = stack; + do { + c = MEMORY[start++]; + // TODO: implement [] and maybe $ + if(c == '\\') c = MEMORY[start++]; + // TODO: implement 'smarter' escaping, e.g. \n + MEMORY[stack++] = c; + } while(c != '"' || (quote && c <= ' ')); + return ptr; +} + +int main() { + +} diff --git a/sectcl.nasm b/sectcl.nasm new file mode 100644 index 0000000..a947e7b --- /dev/null +++ b/sectcl.nasm @@ -0,0 +1,32 @@ +; x86-16 BIOS bootloader +[BITS 16] +[ORG 0x7C00] +; jmp 0x7C00:start +start: + +call GetChar +jmp start + +; REGISTERS +; SP: 'top of memory' +; BP: points to variable map +; others: general purpose +GetChar: +xor AX,AX ; clear AH +int 0x16 ; read key via BIOS +; read key is now in AL +; fallthrough to PutChar to echo read key + +PutChar: +mov AH,0xe ; TTY mode +int 0x10 ; print character in AL +cmp AL, 13 ; if \r, print \r\n and return \n +jne .ret +mov AL, 10 +call PutChar +.ret: ret + + +; fill up sector, add boot signature +TIMES 510 - ($ - $$) db 0 +DW 0xAA55