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
assembler. The Stack Pointer will start 2 bytes above the video memory start.
\section{STOB (Store Byte)}
\OpcodeTable{0x20}{stob}{Register}{Address}\\[6pt]
Stores a single byte (the lower nibble) from a register to a memory address.
\OpcodeTable{0x20}{stob}{Register}{Register}\\[6pt]
Stores a single byte (the lower nibble) from a register to a memory address store in a register.
\section{STOW (Store Machine Word)}
\OpcodeTable{0x20}{stow}{Register}{Address}\\[6pt]
Stores a machine word from a register to a memory address.
\OpcodeTable{0x20}{stow}{Register}{Register}\\[6pt]
Stores a machine word from a register to a memory address stored in a register.
\section{LAA (Load Absolute Address)}
\OpcodeTable{0x00}{laa}{Register}{Address}\\[6pt]
Loads an address (2 bytes) into the register.
+1 -1
View File
@@ -13,7 +13,7 @@ typedef enum {
typedef enum {
ADD, SUB, JZ, INT, YLD, RET,
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;
typedef enum {
+2 -1
View File
@@ -1,7 +1,8 @@
;.include "./another_test.asm"
.db video_start 0xF37F
.db msg "Hello, world!", 0
.db NOTERM "No terminating byte here"
.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/parser.h"
List* LIST;
void print(void);
int main(int argc, char* args[]) {
if (argc == 1) {
printf("Usage: assm <file1.asm>\n");
return EX_USAGE;
}
atexit(print);
char* source_code;
size_t bytes_read;
if (!ReadAllString(args[1], &source_code, &bytes_read)) return EX_IOERR;
List* list = GenerateTokenList(source_code);
char mnemonic[12];
LIST = GenerateTokenList(source_code);
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) {
printf("EOF\n");
@@ -75,8 +91,4 @@ int main(int argc, char* args[]) {
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}
{ "lodwi", LODWI, RegisterParameter, ConstantParameter },
{ "je", JE, AddressParameter, NoParameter },
{ "lodb", LOADB, RegisterParameter, RegisterParameter },
{ "stob", STOB, RegisterParameter, AddressParameter },
{ "stow", STOW, RegisterParameter, AddressParameter },
{ "laa", LAA, RegisterParameter, AddressParameter },
@@ -41,7 +40,8 @@ struct _instruction instructions[OPCODECOUNT] = {
{ "shl", SHL, RegisterParameter, ConstantParameter },
{ "nop", NOP, NoParameter, 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) {
@@ -119,7 +119,7 @@ void GetRegisterText(Registers reg, char buffer[3]) {
int IsOpcode(const char* text, Mnemonic* opcode) {
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 (opcode) *opcode = instructions[i].Mnemonic;
return 1;
+93 -7
View File
@@ -1,6 +1,7 @@
#include "../includes/parser.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
List* TokensList;
int CurrentToken = 0;
@@ -14,8 +15,12 @@ void AdvanceParser(void);
void IgnoreParserLine(void);
Token* PeekToken(void);
int ParserAtEnd(void);
int Expect(TokenClass class, void* value);
IRState MachineState;
//int ExpectPuncuation(TokenPunctuation punctuation);
//int ExpectIdentifier();
int HeapSize = 0;
int PC = 0;
@@ -29,11 +34,11 @@ IRState* ParseTokens(List* tokens) {
while(!ParserAtEnd()) {
Token* t = PeekToken();
if (!t) break;
if (!t || t->EndOfFile) break;
Symbol* tmp;
switch(t->Class) {
case DirectiveClass: //Maybe these should be ignored, let another process handle that.
case DirectiveClass:
HandleAssemblerDirective();
break;
case MnemonicClass:
@@ -58,8 +63,6 @@ IRState* ParseTokens(List* tokens) {
//IgnoreParserLine();
break;
}
RemoveCurrentToken();
}
PrintSymbols();
@@ -69,12 +72,19 @@ IRState* ParseTokens(List* tokens) {
void HandleAssemblerDirective() {
Token* directive = PeekToken();
RemoveCurrentToken();
switch(directive->Value.Directive){
case DB:
{
RemoveCurrentToken();
Token* identifier = PeekToken();
if (identifier->Class != IdentifierClass) {
fprintf(stderr, "[Line %d] Expected Identifier '%c'\n", identifier->LineNumber, identifier->Value.Punctuation);
exit(30);
}
Symbol* 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);
exit(1);
}
if (found) {
symbol->Address = HeapSize;
symbol->Resolved = 1;
@@ -128,18 +139,93 @@ void HandleAssemblerDirective() {
}
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;
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);
}
}
void HandleOperation(void) {
}
void PrintSymbols(void) {
//char mn[12];
printf("-----SYMBOLS-----\n");
+8
View File
@@ -291,6 +291,14 @@ Token* ParseIdentifier(void) {
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);