Lots of changes and too much dragging my feet on this. But I think this is going in the right direction now.

This commit is contained in:
2025-06-24 23:48:26 -05:00
parent ebfd7cf94c
commit b759589e84
16 changed files with 320 additions and 51 deletions
+1 -1
View File
@@ -35,7 +35,7 @@ clean:
rm -rf $(BINDIR)/* $(OBJDIR)/* rm -rf $(BINDIR)/* $(OBJDIR)/*
test: test:
$(BIN) misc/another_test.asm $(BIN) examples/strlen.asm
disass: disass:
objdump -S --disassemble $(OBJDIR)/$(FILE).o > $(OBJDIR)/$(FILE).s objdump -S --disassemble $(OBJDIR)/$(FILE).o > $(OBJDIR)/$(FILE).s
+37
View File
@@ -0,0 +1,37 @@
namespace string 67; my string namespace here
word FRAMEBUFFER 0x00200500
asciiz Msg "Hello World!"
; fn effectively is an "Append to Namespace" command, ie string + "." + _start
fn _start:
mov FRAMEBUFFER, r32 ; imm, r
mov msg, r1 ; imm, r
call strlen ; result into r2
mov 0, r4 ; counter
loop:
mov byte [r1], r3 ; read char into r3
cmp r3, 0 ; NUL byte?
je end
mov byte r3, [r32] ; Write char to frame buffer
inc r32 ; Next space in framebuffer
inc r4 ; inc counter
inc r1 ; inc pointer to msg
jmp loop
end: ;At the moment this just writes Msg to the framebuffer.
ret
; Clobbers r2, r3
; Params: r1 - string pointer
; Returns: r2, string length
fn strlen:
mov 0, r2 ; Set the length to zero
loop:
mov byte [r1], r3 ; mov char into r3
cmp r3, 0 ; NUL byte?
je end
inc r1 ; next char
inc r2 ; length++
jmp loop
end:
ret
+4 -2
View File
@@ -2,15 +2,17 @@
#define ARRAY_H #define ARRAY_H
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h>
typedef struct _array { typedef struct _array {
int Capacity; size_t Capacity;
int Size; size_t Size;
void** Items; void** Items;
} Array; } Array;
Array* ArrayCreate(void); Array* ArrayCreate(void);
bool ArrayAdd(Array* array, void* item); bool ArrayAdd(Array* array, void* item);
void* ArrayPeek(Array* array); void* ArrayPeek(Array* array);
void* ArrayIndex(Array* array, size_t index);
#endif #endif
-4
View File
@@ -1,4 +0,0 @@
#ifndef AST_H
#define AST_H
#endif
+4 -4
View File
@@ -2,10 +2,10 @@
#define KEYWORDS_H #define KEYWORDS_H
typedef enum { typedef enum {
FN, ORG, NAMESPACE, DB, CONST FUNCTION, NAMESPACE, ASCIIZ, ASCII, WORD, SHORT, BYTE
} Keyword; } Keywords;
int IsKeyword(const char* text, Keyword* keyword); int IsKeyword(const char* text, Keywords* keyword);
void GetKeywordText(Keyword keyword, char buffer[16]); void GetKeywordText(Keywords keyword, char buffer[16]);
#endif #endif
+6 -5
View File
@@ -6,17 +6,18 @@
#include <stdio.h> #include <stdio.h>
typedef enum { typedef enum {
R1 = 0, R2, R3, R4, R5, R6, R7, R8 = 7 R1 = 1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, R13, R14, R15, R16, R17, R18, R19,
R20, R21, R22, R23, R24, R25, R26, R27, R28, R29, R30, R31, R32, RBP, RSP, RIP
} Registers; } Registers;
typedef enum { typedef enum {
ADD = 0x01, SUB, MUL, DIV, MOV, AND, OR, XOR, NOT, SHL, SHR, NOP, CMP, JMP, JZ, JG, JL, ADD = 0x01, SUB, MUL, DIV, MOV, AND, OR, XOR, NOT, SHL, SHR, NOP, CMP, JMP, JZ, JG, JL,
OUTB, INB, HLT, CLI, ENI, INT, LIVT, PUSHA, POPA, CALL, RET, PUSH, POP OUTB, INB, HLT, CLI, ENI, INT, LIVT, PUSHA, POPA, CALL, RET, PUSH, POP
} Mnemonic; } Mnemonics;
int IsOpcode(const char*, Mnemonic*); int IsOpcode(const char*, Mnemonics*);
int IsRegister(const char*, Registers*); int IsRegister(const char*, Registers*);
void GetMnemonicText(Mnemonic mnemonic, char buffer[12]); void GetMnemonicText(Mnemonics mnemonic, char buffer[12]);
void GetRegisterText(Registers reg, char buffer[4]); void GetRegisterText(Registers reg, char buffer[5]);
#endif #endif
+17
View File
@@ -0,0 +1,17 @@
#ifndef PARSER_H
#define PARSER_H
#include <stdbool.h>
#include <stdint.h>
#include "dictionary.h"
#include "opcodes.h"
#include "token.h"
#include "array.h"
#include "keywords.h"
typedef struct _instruction Instruction;
typedef Array Instructions;
Instructions* ParseTokens(Array* tokens);
#endif
+8
View File
@@ -5,12 +5,17 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
#include "opcodes.h"
#include "keywords.h"
typedef enum { typedef enum {
Empty, Empty,
String, String,
Number, Number,
Symbol, Symbol,
Register,
Mnemonic,
Keyword,
LineEnd = '\n', LineEnd = '\n',
Colon = ':', Colon = ':',
Comma = ',', Comma = ',',
@@ -32,6 +37,9 @@ typedef struct _token {
char Operator[8]; char Operator[8];
char* String; char* String;
int Number; int Number;
Mnemonics Mnemonic;
Registers Register;
Keywords Keyword;
} Value; } Value;
int LineNumber; int LineNumber;
int ColumnNumber; int ColumnNumber;
+7
View File
@@ -33,4 +33,11 @@ void* ArrayPeek(struct _array* array) {
if (array->Size == 0 || array->Capacity == 0) return NULL; if (array->Size == 0 || array->Capacity == 0) return NULL;
return array->Items[array->Size - 1]; return array->Items[array->Size - 1];
}
void* ArrayIndex(Array* array, size_t index) {
if (!array) return NULL;
if (index >= array->Size) return NULL;
return array->Items[index];
} }
View File
+13 -8
View File
@@ -1,22 +1,27 @@
#include "../includes/keywords.h" #include "../includes/keywords.h"
#include <string.h> #include <string.h>
#define KEYWORD_COUNT 5 #define KEYWORD_COUNT 7
struct _keyword { struct _keyword {
char* Name; char* Name;
Keyword Word; Keywords Word;
}; };
struct _keyword keywords[KEYWORD_COUNT] = { struct _keyword keywords[KEYWORD_COUNT] = {
{ "fn", FN }, { "fn", FUNCTION },
{ "org", ORG }, //{ "org", ORG },
{ "namespace", NAMESPACE }, { "namespace", NAMESPACE },
{ "db", DB }, { "asciiz", ASCIIZ },
{ "cosnt", CONST } { "ascii", ASCII },
{ "word", WORD },
{ "short", SHORT },
{ "byte", BYTE }
//{ "db", DB },
//{ "cosnt", CONST }
}; };
int IsKeyword(const char* text, Keyword* keyword) { int IsKeyword(const char* text, Keywords* keyword) {
if (!text) return 0; if (!text) return 0;
for(unsigned long i = 0; i < KEYWORD_COUNT; i++) { for(unsigned long i = 0; i < KEYWORD_COUNT; i++) {
@@ -30,7 +35,7 @@ int IsKeyword(const char* text, Keyword* keyword) {
return 0; return 0;
} }
void GetKeywordText(Keyword keyword, char buffer[16]) { void GetKeywordText(Keywords keyword, char buffer[16]) {
if (!buffer) return; if (!buffer) return;
memset(buffer, '\0', 16); memset(buffer, '\0', 16);
+8 -2
View File
@@ -1,6 +1,8 @@
#include <stdio.h> #include <stdio.h>
#include "../includes/futil.h" #include "../includes/futil.h"
#include "../includes/tokenizer.h" #include "../includes/tokenizer.h"
#include "../includes/opcodes.h"
#include "../includes/parser.h"
int main(int argc, char** argv) { int main(int argc, char** argv) {
char* file; char* file;
@@ -23,14 +25,15 @@ int main(int argc, char** argv) {
Dictionary* variables = DictionaryCreate(); Dictionary* variables = DictionaryCreate();
Array* tokens = Tokenize(file, &variables); Array* tokens = Tokenize(file, &variables);
if (tokens->Size == 0) { if (tokens->Size == 0) {
printf("No tokens\n"); printf("No tokens\n");
return 0; return 0;
} }
/*
char* buffer; char* buffer;
char type[32];
for(int i = 0; i < tokens->Size; i++) { for(int i = 0; i < tokens->Size; i++) {
Token* token = tokens->Items[i]; Token* token = tokens->Items[i];
@@ -41,6 +44,7 @@ int main(int argc, char** argv) {
continue; continue;
} }
//StringifyTokenType(token->Type, type);
buffer = TokenStringify(token); buffer = TokenStringify(token);
if (buffer) { if (buffer) {
@@ -51,4 +55,6 @@ int main(int argc, char** argv) {
} }
printf("\n"); printf("\n");
*/
(void) ParseTokens(tokens);
} }
+31 -18
View File
@@ -3,14 +3,14 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define OPCODE_COUNT 34 #define OPCODE_COUNT 29
struct _instruction { struct _instruction {
char* Name; char* Name;
Mnemonic Mnemonic; Mnemonics Mnemonic;
}; };
struct _instruction instructions[OPCODE_COUNT] = { struct _instruction Instructions[OPCODE_COUNT] = {
{ "add", ADD }, { "add", ADD },
{ "sub", SUB }, { "sub", SUB },
{ "mul", MUL }, { "mul", MUL },
@@ -42,32 +42,32 @@ struct _instruction instructions[OPCODE_COUNT] = {
{ "pop", POP } { "pop", POP }
}; };
void GetMnemonicText(Mnemonic mnemonic, char buffer[12]) { void GetMnemonicText(Mnemonics mnemonic, char buffer[12]) {
memset(buffer, '\0', 12); memset(buffer, '\0', 12);
for(int i = 0; i < OPCODE_COUNT; i++) { for(int i = 0; i < OPCODE_COUNT; i++) {
if (instructions[i].Mnemonic == mnemonic) { if (Instructions[i].Mnemonic == mnemonic) {
strncpy(buffer, instructions[i].Name, 11); strncpy(buffer, Instructions[i].Name, 11);
break; break;
} }
} }
} }
void GetRegisterText(Registers reg, char buffer[4]) { void GetRegisterText(Registers reg, char buffer[5]) {
memset(buffer, '\0', 4); memset(buffer, '\0', 5);
if (reg < R1 || reg > R8) return; if (reg < R1 || reg > R32) return;
buffer[0] = 'r'; buffer[0] = 'r';
buffer[1] = reg + 49; buffer[1] = reg + 49;
} }
int IsOpcode(const char* text, Mnemonic* opcode) { int IsOpcode(const char* text, Mnemonics* opcode) {
if (!text) return 0; if (!text) return 0;
for(unsigned long i = 0; i < sizeof(instructions) / sizeof(struct _instruction); i++) { for(unsigned long i = 0; i < OPCODE_COUNT; i++) {
if (strcmp(instructions[i].Name, text) == 0) { if (strcmp(Instructions[i].Name, text) == 0) {
if (opcode) *opcode = instructions[i].Mnemonic; if (opcode) *opcode = Instructions[i].Mnemonic;
return 1; return 1;
} }
} }
@@ -79,14 +79,27 @@ int IsRegister(const char* text, Registers* reg) {
if (!text) return 0; if (!text) return 0;
int length = strlen(text); int length = strlen(text);
Registers r = R8; Registers r;
if (length != 2) return 0; if (length < 2 || length > 3) return 0;
if (text[0] != 'r') return 0; if (text[0] != 'r') return 0;
if (!isdigit(text[1])) return 0; if (length == 2) {
if (!isdigit(text[1])) return 0;
r = text[1] - 0x31;
r = text[1] - 0x30;
}
else if (strcmp(text, "rbp") == 0)
r = RBP;
else if (strcmp(text, "rsp") == 0)
r = RSP;
else if (strcmp(text, "rip") == 0)
r = RIP;
else {
r = (text[1] - 0x30) * 10;
if (!isdigit(text[2])) return 0;
r += text[2] - 0x30;
}
if (reg) *reg = r; if (reg) *reg = r;
+123
View File
@@ -0,0 +1,123 @@
#include "../includes/parser.h"
#define KEYWORD_COUNT 7
static Array* Tokens;
struct _instruction {
char* Name;
bool IsDirective;
union {
Mnemonics Mnemonic;
Keywords Keyword;
} Value;
};
typedef struct parameter {
bool IsRegister;
Registers Register;
unsigned char Width;
uint32_t Offset;
} Parameter;
size_t ParserIndex = 0;
Token* ParserAdvance(void);
void ParserIgnoreLine(void);
bool ParserAtEnd(void);
Parameter* ParserExpectParameter(void);
void ParserHandleKeyword(Keywords keyword);
Token* ParserExpect(TokenType type);
Token* ParserWant(TokenType type);
void ParserExpectLineEnd(void);
Instructions* ParseTokens(Array* tokens) {
Tokens = tokens;
Keywords keyword;
while(!ParserAtEnd()) {
Token* token = ParserAdvance();
switch(token->Type) {
case Keyword:
ParserHandleKeyword(token->Value.Keyword);
break;
default:
break;
}
}
}
void ParserHandleKeyword(Keywords keyword) {
Token* namespace = NULL;
switch(keyword) {
case NAMESPACE:
namespace = ParserExpect(Symbol);
ParserExpectLineEnd();
printf("Namespace `%s` seen\n", namespace->Value.String);
break;
default:
break;
}
}
Token* ParserExpect(TokenType type) {
if (ParserAtEnd()) return NULL;
Token* token = ParserAdvance();
if (!token || token->Type != type) return NULL;
return token;
}
Token* ParserWant(TokenType type) {
if (ParserAtEnd()) return NULL;
Token* token = ParserAdvance();
if (!token || token->Type != type) return NULL;
return token;
}
void ParserExpectLineEnd(void) {
if (ParserAtEnd()) return;
Token* token = ParserAdvance();
if (token->Type != LineEnd && token->Type != FileEnd) {
//Error / sync
printf("Expected end of line on line %d.\n", token->LineNumber);
ParserIgnoreLine();
}
return;
}
void ParserIgnoreLine(void) {
while(!ParserAtEnd()) {
Token* token = ParserAdvance();
if (token->Type == LineEnd || token->Type == FileEnd)
break;
}
}
Token* ParserAdvance() {
if (ParserAtEnd()) return (Token*) ArrayPeek(Tokens);
if (ParserIndex == Tokens->Size) return (Token*) ArrayPeek(Tokens);
Token* next = ArrayIndex(Tokens, ParserIndex);
ParserIndex++;
return next;
}
bool ParserAtEnd() {
return ParserIndex >= Tokens->Size;
}
+34
View File
@@ -14,9 +14,34 @@ struct _token* TokenCreate(TokenType type, int lineNumber, int columnNumber, boo
char* TokenStringify(const struct _token* token) { char* TokenStringify(const struct _token* token) {
if (!token) return false; if (!token) return false;
char word[32];
char* buffer = NULL; char* buffer = NULL;
switch(token->Type) { switch(token->Type) {
case Register:
GetRegisterText(token->Value.Register, word);
buffer = calloc(sizeof(word), sizeof(char));
strncpy(buffer, word, sizeof(word));
break;
case Mnemonic:
GetMnemonicText(token->Value.Mnemonic, word);
buffer = calloc(sizeof(word), sizeof(char));
strncpy(buffer, word, sizeof(word));
break;
case Keyword:
GetKeywordText(token->Value.Keyword, word);
buffer = calloc(sizeof(word), sizeof(char));
strncpy(buffer, word, sizeof(word));
break;
case String: case String:
case Symbol: case Symbol:
buffer = calloc(strlen(token->Value.String) + 1, sizeof(char)); buffer = calloc(strlen(token->Value.String) + 1, sizeof(char));
@@ -64,6 +89,15 @@ int StringifyTokenType(TokenType type, char buffer[32]) {
case Empty: case Empty:
strncpy(buffer, "<empty >", 8); strncpy(buffer, "<empty >", 8);
break; break;
case Register:
strncpy(buffer, "<Reg >", 8);
break;
case Mnemonic:
strncpy(buffer, "<Mnemon>", 8);
break;
case Keyword:
strncpy(buffer, "<Key >", 8);
break;
case String: case String:
strncpy(buffer, "<string>", 8); strncpy(buffer, "<string>", 8);
break; break;
+27 -7
View File
@@ -1,14 +1,12 @@
#include "../includes/tokenizer.h" #include "../includes/tokenizer.h"
#include "../includes/keywords.h" #include "../includes/keywords.h"
#include "../includes/string_builder.h"
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <stdbool.h> #include <stdbool.h>
#define MAXWORDLENGTH 1024 #define MAXWORDLENGTH 1024
//char Word[MAXWORDLENGTH] = { 0 }; static Array* Tokens;
Array* Tokens;
const char* SourceCode; const char* SourceCode;
size_t SourceCodeLength = 0; size_t SourceCodeLength = 0;
@@ -174,15 +172,37 @@ void TokenizerExpectWord() {
wordLength++; wordLength++;
} }
if (wordLength > 0) { if (wordLength == 0) return;
Token* token = TokenCreate(Symbol, SourceLineNumber, SourceColumnNumber, false);
Token* token;
Mnemonics mnemonic;
Registers reg;
Keywords keyword;
if (IsOpcode(word, &mnemonic)) {
token = TokenCreate(Mnemonic, SourceLineNumber, SourceColumnNumber, true);
token->Value.Mnemonic = mnemonic;
}
else if (IsRegister(word, &reg)) {
token = TokenCreate(Register, SourceLineNumber, SourceColumnNumber, true);
token->Value.Register = reg;
}
else if (IsKeyword(word, &keyword)) {
token = TokenCreate(Keyword, SourceLineNumber, SourceColumnNumber, true);
token->Value.Keyword = keyword;
}
else {
token = TokenCreate(Symbol, SourceLineNumber, SourceColumnNumber, false);
token->Value.String = calloc(wordLength + 1, sizeof(char)); token->Value.String = calloc(wordLength + 1, sizeof(char));
strncpy(token->Value.String, word, wordLength); strncpy(token->Value.String, word, wordLength);
ArrayAdd(Tokens, token);
} }
ArrayAdd(Tokens, token);
} }
void TokenizerExpectString(void) { void TokenizerExpectString(void) {