Initial commit
This commit is contained in:
commit
ba898f2132
|
|
@ -0,0 +1 @@
|
||||||
|
sectcl.bin
|
||||||
|
|
@ -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
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
# An attempt at a single-sector x86-16 Tcl interpreter
|
||||||
|
Inspired by sectorFORTH, sectorLISP and Picol.
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
// Quecl - a quecto-sized Tcl-inspired programming language
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#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() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue