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:
+4
-4
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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");
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user