Updated the parser to handle processing a simple load byte instruction. Added the LODB opcode to the opcode enum listing and updated the Scanner to look for 'byte' and mark it as a directive.

This commit is contained in:
2023-03-24 23:24:24 -05:00
parent f96e1c6380
commit 95ed2143ea
7 changed files with 131 additions and 24 deletions
+4 -4
View File
@@ -73,11 +73,11 @@
or "word" for two bytes. That would make the assembly easier to read but put a bit more work on the or "word" for two bytes. That would make the assembly easier to read but put a bit more work on the
assembler. The Stack Pointer will start 2 bytes above the video memory start. assembler. The Stack Pointer will start 2 bytes above the video memory start.
\section{STOB (Store Byte)} \section{STOB (Store Byte)}
\OpcodeTable{0x20}{stob}{Register}{Address}\\[6pt] \OpcodeTable{0x20}{stob}{Register}{Register}\\[6pt]
Stores a single byte (the lower nibble) from a register to a memory address. Stores a single byte (the lower nibble) from a register to a memory address store in a register.
\section{STOW (Store Machine Word)} \section{STOW (Store Machine Word)}
\OpcodeTable{0x20}{stow}{Register}{Address}\\[6pt] \OpcodeTable{0x20}{stow}{Register}{Register}\\[6pt]
Stores a machine word from a register to a memory address. Stores a machine word from a register to a memory address stored in a register.
\section{LAA (Load Absolute Address)} \section{LAA (Load Absolute Address)}
\OpcodeTable{0x00}{laa}{Register}{Address}\\[6pt] \OpcodeTable{0x00}{laa}{Register}{Address}\\[6pt]
Loads an address (2 bytes) into the register. Loads an address (2 bytes) into the register.
+1 -1
View File
@@ -13,7 +13,7 @@ typedef enum {
typedef enum { typedef enum {
ADD, SUB, JZ, INT, YLD, RET, ADD, SUB, JZ, INT, YLD, RET,
CMP, CMPI, NOP, JMP, CALL, LODW, LAA, LODWI, JE, INC, DEC, LOADB, CMP, CMPI, NOP, JMP, CALL, LODW, LAA, LODWI, JE, INC, DEC, LOADB,
STOB, STOW, JG, JL, AND, XOR, OR, NOT, SHR, SHL, POP, PUSH STOB, STOW, JG, JL, AND, XOR, OR, NOT, SHR, SHL, POP, PUSH, LODB
} Mnemonic; } Mnemonic;
typedef enum { typedef enum {
+2 -1
View File
@@ -1,7 +1,8 @@
;.include "./another_test.asm" ;.include "./another_test.asm"
.db video_start 0xF37F .db video_start 0xF37F
.db msg "Hello, world!", 0 .db msg "Hello, world!", 0
.db NOTERM "No terminating byte here" .db NOTERM "No terminating byte here"
.db null_byte 0 .db null_byte 0
;load r2, label
load byte r1, r3
+20 -8
View File
@@ -8,22 +8,38 @@
#include "../includes/scanner.h" #include "../includes/scanner.h"
#include "../includes/parser.h" #include "../includes/parser.h"
List* LIST;
void print(void);
int main(int argc, char* args[]) { int main(int argc, char* args[]) {
if (argc == 1) { if (argc == 1) {
printf("Usage: assm <file1.asm>\n"); printf("Usage: assm <file1.asm>\n");
return EX_USAGE; return EX_USAGE;
} }
atexit(print);
char* source_code; char* source_code;
size_t bytes_read; size_t bytes_read;
if (!ReadAllString(args[1], &source_code, &bytes_read)) return EX_IOERR; if (!ReadAllString(args[1], &source_code, &bytes_read)) return EX_IOERR;
List* list = GenerateTokenList(source_code); LIST = GenerateTokenList(source_code);
char mnemonic[12];
ParseTokens(LIST);
for(int i = 0; i < list->size; i++) {
Token* t = (Token*) list->content[i]; free(source_code);
}
void print(void) {
char mnemonic[12];
printf("printing tokens...\n");
for(int i = 0; i < LIST->size; i++) {
Token* t = (Token*) LIST->content[i];
if (t->EndOfFile) { if (t->EndOfFile) {
printf("EOF\n"); printf("EOF\n");
@@ -75,8 +91,4 @@ int main(int argc, char* args[]) {
printf("[C]'%s'", t->Lemexe); printf("[C]'%s'", t->Lemexe);
} }
} }
ParseTokens(list);
free(source_code);
} }
+3 -3
View File
@@ -25,7 +25,6 @@ struct _instruction instructions[OPCODECOUNT] = {
{ "call", CALL, AddressParameter, NoParameter },//, Address, None} { "call", CALL, AddressParameter, NoParameter },//, Address, None}
{ "lodwi", LODWI, RegisterParameter, ConstantParameter }, { "lodwi", LODWI, RegisterParameter, ConstantParameter },
{ "je", JE, AddressParameter, NoParameter }, { "je", JE, AddressParameter, NoParameter },
{ "lodb", LOADB, RegisterParameter, RegisterParameter },
{ "stob", STOB, RegisterParameter, AddressParameter }, { "stob", STOB, RegisterParameter, AddressParameter },
{ "stow", STOW, RegisterParameter, AddressParameter }, { "stow", STOW, RegisterParameter, AddressParameter },
{ "laa", LAA, RegisterParameter, AddressParameter }, { "laa", LAA, RegisterParameter, AddressParameter },
@@ -41,7 +40,8 @@ struct _instruction instructions[OPCODECOUNT] = {
{ "shl", SHL, RegisterParameter, ConstantParameter }, { "shl", SHL, RegisterParameter, ConstantParameter },
{ "nop", NOP, NoParameter, NoParameter }, { "nop", NOP, NoParameter, NoParameter },
{ "pop", POP, RegisterParameter, NoParameter }, { "pop", POP, RegisterParameter, NoParameter },
{ "push", PUSH, RegisterParameter, NoParameter } { "push", PUSH, RegisterParameter, NoParameter },
{ "lodb", LODB, RegisterParameter, RegisterParameter}
}; };
void ExpectParameters(Mnemonic mnemonic, OpcodeParameter* paramOne, OpcodeParameter* paramTwo) { void ExpectParameters(Mnemonic mnemonic, OpcodeParameter* paramOne, OpcodeParameter* paramTwo) {
@@ -119,7 +119,7 @@ void GetRegisterText(Registers reg, char buffer[3]) {
int IsOpcode(const char* text, Mnemonic* opcode) { int IsOpcode(const char* text, Mnemonic* opcode) {
if (!text) return 0; if (!text) return 0;
for(int i = 0; i < OPCODECOUNT; i++) { for(int i = 0; i < sizeof(instructions) / sizeof(struct _instruction); 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;
+93 -7
View File
@@ -1,6 +1,7 @@
#include "../includes/parser.h" #include "../includes/parser.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
List* TokensList; List* TokensList;
int CurrentToken = 0; int CurrentToken = 0;
@@ -14,8 +15,12 @@ void AdvanceParser(void);
void IgnoreParserLine(void); void IgnoreParserLine(void);
Token* PeekToken(void); Token* PeekToken(void);
int ParserAtEnd(void); int ParserAtEnd(void);
int Expect(TokenClass class, void* value);
IRState MachineState; IRState MachineState;
//int ExpectPuncuation(TokenPunctuation punctuation);
//int ExpectIdentifier();
int HeapSize = 0; int HeapSize = 0;
int PC = 0; int PC = 0;
@@ -29,11 +34,11 @@ IRState* ParseTokens(List* tokens) {
while(!ParserAtEnd()) { while(!ParserAtEnd()) {
Token* t = PeekToken(); Token* t = PeekToken();
if (!t) break; if (!t || t->EndOfFile) break;
Symbol* tmp; Symbol* tmp;
switch(t->Class) { switch(t->Class) {
case DirectiveClass: //Maybe these should be ignored, let another process handle that. case DirectiveClass:
HandleAssemblerDirective(); HandleAssemblerDirective();
break; break;
case MnemonicClass: case MnemonicClass:
@@ -58,8 +63,6 @@ IRState* ParseTokens(List* tokens) {
//IgnoreParserLine(); //IgnoreParserLine();
break; break;
} }
RemoveCurrentToken();
} }
PrintSymbols(); PrintSymbols();
@@ -69,12 +72,19 @@ IRState* ParseTokens(List* tokens) {
void HandleAssemblerDirective() { void HandleAssemblerDirective() {
Token* directive = PeekToken(); Token* directive = PeekToken();
RemoveCurrentToken();
switch(directive->Value.Directive){ switch(directive->Value.Directive){
case DB: case DB:
{ {
RemoveCurrentToken();
Token* identifier = PeekToken(); Token* identifier = PeekToken();
if (identifier->Class != IdentifierClass) {
fprintf(stderr, "[Line %d] Expected Identifier '%c'\n", identifier->LineNumber, identifier->Value.Punctuation);
exit(30);
}
Symbol* symbol; Symbol* symbol;
int found = TryGetSymbol(identifier->Lemexe, MachineState.SymbolsTable, &symbol); int found = TryGetSymbol(identifier->Lemexe, MachineState.SymbolsTable, &symbol);
@@ -83,6 +93,7 @@ void HandleAssemblerDirective() {
fprintf(stderr, "Redefinition of %s on line %d.\n", identifier->Lemexe, identifier->LineNumber); fprintf(stderr, "Redefinition of %s on line %d.\n", identifier->Lemexe, identifier->LineNumber);
exit(1); exit(1);
} }
if (found) { if (found) {
symbol->Address = HeapSize; symbol->Address = HeapSize;
symbol->Resolved = 1; symbol->Resolved = 1;
@@ -128,18 +139,93 @@ void HandleAssemblerDirective() {
} }
HeapSize += symbol->Length; HeapSize += symbol->Length;
RemoveCurrentToken(); //Wipe the line end token
} }
break;
case Load:
{
AdvanceParser();
Token* reg = PeekToken();
if (reg->Class != RegisterClass && reg->Class != DirectiveClass) {
fprintf(stderr, "Syntax error line %d: Expected register or directive 'byte', got %d.", reg->LineNumber, reg->Class);
exit(1);
}
if (reg->Class == RegisterClass) {
AdvanceParser();
if (PeekToken()->Class != PunctuationClass || PeekToken()->Value.Punctuation != Comma) {
exit(1);
}
AdvanceParser(); //Save the comma
if (PeekToken()->Class != IdentifierClass && PeekToken()->Class != NumberClass){
exit(2);
}
if (PeekToken()->Class == NumberClass) {
printf("LODWI\n");
directive->Class = MnemonicClass;
directive->Value.Mnemonic = LODWI;
directive->Lemexe = "LODWI";
}
else {
printf("LAA\n");
directive->Class = MnemonicClass;
directive->Value.Mnemonic = LAA;
directive->Lemexe = "LAA";
}
AdvanceParser();
}
else if (reg->Class == DirectiveClass) {
if (reg->Value.Directive != Byte) {
fprintf(stderr, "Syntax error: Line %d expected keyword 'byte'.\n", reg->LineNumber);
exit(3);
}
RemoveCurrentToken(); AdvanceParser(); //byte
if (PeekToken()->Class != RegisterClass) {
exit(3);
}
AdvanceParser(); //reg
if (PeekToken()->Class != PunctuationClass) {
exit(7);
}
AdvanceParser(); //Comma
if (PeekToken()->Class != RegisterClass) {
exit(4);
}
AdvanceParser(); //Reg
directive->Class = MnemonicClass;
directive->Value.Mnemonic = LODB;
directive->Lemexe = "LODB";
}
}
break; break;
default: default:
fprintf(stderr, "Synatx error on line %d.\n", directive->LineNumber); fprintf(stderr, "Synatx error on line %d, %s.\n", directive->LineNumber, directive->Lemexe);
exit(1); exit(1);
} }
} }
void HandleOperation(void) { void HandleOperation(void) {
} }
void PrintSymbols(void) { void PrintSymbols(void) {
//char mn[12]; //char mn[12];
printf("-----SYMBOLS-----\n"); printf("-----SYMBOLS-----\n");
+8
View File
@@ -291,6 +291,14 @@ Token* ParseIdentifier(void) {
return token; return token;
} }
if (strcmp(lexeme, "byte") == 0) {
Token* token = CreateToken(Line, DirectiveClass);
token->Lemexe = lexeme;
token->Value.Directive = Byte;
return token;
}
Token* token = CreateToken(Line, IdentifierClass); Token* token = CreateToken(Line, IdentifierClass);