diff --git a/docs/document.tex b/docs/document.tex index afdeceb..e7a01ca 100644 --- a/docs/document.tex +++ b/docs/document.tex @@ -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. diff --git a/includes/opcodes.h b/includes/opcodes.h index 53d00e4..695af54 100644 --- a/includes/opcodes.h +++ b/includes/opcodes.h @@ -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 { diff --git a/misc/test.asm b/misc/test.asm index 8021152..64892e5 100644 --- a/misc/test.asm +++ b/misc/test.asm @@ -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 \ No newline at end of file diff --git a/src/main.c b/src/main.c index 8b9a6b0..a2616ae 100644 --- a/src/main.c +++ b/src/main.c @@ -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 \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); } \ No newline at end of file diff --git a/src/opcodes.c b/src/opcodes.c index aacd83a..93395bf 100644 --- a/src/opcodes.c +++ b/src/opcodes.c @@ -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; diff --git a/src/parser.c b/src/parser.c index b3351f8..3409585 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1,6 +1,7 @@ #include "../includes/parser.h" #include #include +#include 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"); diff --git a/src/scanner.c b/src/scanner.c index bd27284..e17e906 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -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);