From 1b246e90bc8e6d4b340013e4a72b4b7007371d70 Mon Sep 17 00:00:00 2001 From: Garritt McCune Date: Thu, 23 Feb 2023 22:22:07 -0600 Subject: [PATCH] Started rethinking how this machine should behave. Updated and refactoring some things with a few new ideas. --- docs/document.tex | 10 +- includes/opcodes.h | 2 +- includes/token.h | 2 +- misc/another_test.asm | 3 + misc/test.asm | 8 +- src/main.c | 217 ++++++++---------------------------------- src/opcodes.c | 6 +- src/scanner.c | 13 ++- 8 files changed, 68 insertions(+), 193 deletions(-) create mode 100644 misc/another_test.asm diff --git a/docs/document.tex b/docs/document.tex index 4bf1568..afdeceb 100644 --- a/docs/document.tex +++ b/docs/document.tex @@ -71,7 +71,7 @@ For the opcodes that load or store data at the assembly language level we could have the mnemonics "store" and "load" and have the assembler pick the opcode based on the inclusion of the word "byte" or "word" for two bytes. That would make the assembly easier to read but put a bit more work on the - assembler. + 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. @@ -104,7 +104,7 @@ Performs subtraction on a register with a value from another (or the same) register. \section{JMP (Jump)} \OpcodeTable{0x20}{jmp}{Address}{None}\\[6pt] - Jumps unconditionally to a memory address. + Jumps unconditionally to a memory address. Sets the Program Counter to Address. \section{JZ (Jump if Zero)} \OpcodeTable{0x20}{jz}{Register}{None}\\[6pt] Jumps to a memory address if the status flag is zero. @@ -141,4 +141,10 @@ \section{NOP (No Operation)} \OpcodeTable{0x00}{nop}{None}{None}\\[6pt] Skips a clock cycle, incrementing the program counter. + \section{Push} + \OpcodeTable{0x00}{push}{Register}{None} + Pushes the value of Register onto the stack, decrementing the Stack Pointer by 2. + \section{Pop} + \OpcodeTable{0x00}{pop}{Register}{None} + Pops the top of the stack into Register, incrementing the Stack Pointer by 2. \end{document} diff --git a/includes/opcodes.h b/includes/opcodes.h index 321f4f4..53d00e4 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 + STOB, STOW, JG, JL, AND, XOR, OR, NOT, SHR, SHL, POP, PUSH } Mnemonic; typedef enum { diff --git a/includes/token.h b/includes/token.h index 52a94c0..a26acdd 100644 --- a/includes/token.h +++ b/includes/token.h @@ -23,7 +23,7 @@ typedef enum { typedef enum { DB, - Origin, + Include, Byte } Directive; diff --git a/misc/another_test.asm b/misc/another_test.asm new file mode 100644 index 0000000..7ad2976 --- /dev/null +++ b/misc/another_test.asm @@ -0,0 +1,3 @@ +some_stub: + pop r8 + jmp [r8] ;return to the calling code. \ No newline at end of file diff --git a/misc/test.asm b/misc/test.asm index 652d5f5..7bc3d3a 100644 --- a/misc/test.asm +++ b/misc/test.asm @@ -1,9 +1,11 @@ +.include "/another_test.asm" + .db video_start 0xF37F .db msg "Hello, world!", 0 .db NOTERM "No terminating byte here" .db null_byte 0 -load r1, [msg] ; Because the lod* instructions can't load an address +load r1, msg ; Because the lod* instructions can't load an address ; from anything but a register, this becomes laa r1, [msg] ;Routine: string_length @@ -26,4 +28,6 @@ start: jmp start end: -ret + +pop r8 ;pop the return address from the stack into register 8 +jmp [r8] ;jump to that address diff --git a/src/main.c b/src/main.c index 13b8a1e..0753371 100644 --- a/src/main.c +++ b/src/main.c @@ -4,14 +4,9 @@ #include #include #include "../includes/list.h" -#include "../includes/parser.h" #include "../includes/futil.h" #include "../includes/scanner.h" -unsigned char Memory[2000]; - -void Setup(IRState*); - int main(int argc, char* args[]) { if (argc == 1) { printf("Usage: assm \n"); @@ -24,197 +19,65 @@ int main(int argc, char* args[]) { if (!ReadAllString(args[1], &source_code, &bytes_read)) return EX_IOERR; List* list = GenerateTokenList(source_code); - // char mnemonic[12]; + char mnemonic[12]; - // for(int i = 0; i < list->size; i++) { - // Token* t = (Token*) list->content[i]; + for(int i = 0; i < list->size; i++) { + Token* t = (Token*) list->content[i]; - // if (t->EndOfFile) { - // printf("EOF\n"); - // break; - // } + if (t->EndOfFile) { + printf("EOF\n"); + break; + } - // if (t->Class == PunctuationClass){ - // if(t->Value.Punctuation == NewLine) { - // printf("\n"); - // continue; - // } + if (t->Class == PunctuationClass){ + if(t->Value.Punctuation == NewLine) { + printf("\n"); + continue; + } - // printf("<%d>", t->LineNumber); + printf("<%d>", t->LineNumber); - // printf("%c ", t->Value.Punctuation); - // continue; - // } + printf("%c ", t->Value.Punctuation); + continue; + } - // printf("<%d>", t->LineNumber); + printf("<%d>", t->LineNumber); - // if (t->Class == LabelClass) { - // printf("[L]%s* ", t->Lemexe); - // continue; - // } + if (t->Class == LabelClass) { + printf("[L]%s* ", t->Lemexe); + continue; + } - // if (t->Class == IdentifierClass) { - // printf("[I]%s ", t->Lemexe); - // continue; - // } + if (t->Class == IdentifierClass) { + printf("[I]%s ", t->Lemexe); + continue; + } - // if (t->Class == RegisterClass) { - // printf("[R]%d", t->Value.Register); - // continue; - // } - - // if (t->Class == NumberClass) { - // printf("[N]%d ", t->Value.Number); - // continue; - // } - - // if (t->Class == MnemonicClass) { - // GetMnemonicText(t->Value.Mnemonic, mnemonic); - // printf("[M]%s ", mnemonic); - // continue; - // } - - // if (t->Class == DirectiveClass) { - // printf("[D]%d ", t->Value.Directive); - - // } - - // if (t->Class == CharacterClass) { - // printf("%s ", t->Lemexe); - // } - // } - - IRState* image = ParseTokens(list); - char instruction[12]; - char reg[3]; - - for(int i = 0; i < image->Instructions->size; i++) { - Instruction* ins = image->Instructions->content[i]; - - GetMnemonicText(ins->Mnemonic, instruction); - - printf("%s ", instruction); - - if (!ins->ParameterOne) { - printf("\n"); + if (t->Class == RegisterClass) { + printf("[R]%d", t->Value.Register); continue; } - switch(ins->ParameterOne->ParameterType) { - case RegisterParameter: - GetRegisterText(ins->ParameterOne->Value.Register, reg); - - if (ins->ParameterOne->InterpretedAs == AddressParameter) printf("[%s]", reg); - else printf("%s", reg); - break; - case ConstantParameter: - if (ins->ParameterOne->InterpretedAs == AddressParameter) printf("[%d]", ins->ParameterOne->Value.Number); - else printf("%d", ins->ParameterOne->Value.Number); - break; - case AddressParameter: - if (ins->ParameterOne->InterpretedAs == AddressParameter) printf("[%s]", ins->ParameterOne->Value.Symbol); - else { - Symbol* s = TryGetSymbol(ins->ParameterOne->Value.Symbol, image->SymbolsTable); - - switch(s->Type) { - case NumericSymbol: - printf("%s {%d}", s->Name, s->Value.Number); - break; - default: - printf("%s", ins->ParameterOne->Value.Symbol); - } - } - break; - default: - printf("\n"); - } - - if (!ins->ParameterTwo) { - printf("\n"); + if (t->Class == NumberClass) { + printf("[N]%d ", t->Value.Number); continue; } - switch(ins->ParameterTwo->ParameterType) { - case RegisterParameter: - GetRegisterText(ins->ParameterTwo->Value.Register, reg); + if (t->Class == MnemonicClass) { + GetMnemonicText(t->Value.Mnemonic, mnemonic); + printf("[M]%s ", mnemonic); + continue; + } - if (ins->ParameterTwo->InterpretedAs == AddressParameter) printf(", [%s]\n", reg); - else printf(", %s\n", reg); - break; - case ConstantParameter: - if (ins->ParameterTwo->InterpretedAs == AddressParameter) printf(", [%d]\n", ins->ParameterTwo->Value.Number); - else printf(", %d\n", ins->ParameterTwo->Value.Number); - break; - case AddressParameter: - if (ins->ParameterTwo->InterpretedAs == AddressParameter) printf(", [%s]\n", ins->ParameterTwo->Value.Symbol); - else { - Symbol* s = TryGetSymbol(ins->ParameterTwo->Value.Symbol, image->SymbolsTable); + if (t->Class == DirectiveClass) { + printf("[D]%d ", t->Value.Directive); - switch(s->Type) { - case NumericSymbol: - printf(", %s {%d}\n", s->Name, s->Value.Number); - break; - default: - printf(", %s\n", ins->ParameterTwo->Value.Symbol); - } - } - break; - default: - printf("\n"); + } + + if (t->Class == CharacterClass) { + printf("%s ", t->Lemexe); } } - Setup(image); - //free(image); - //Disassemble(image); - //for(int i = 0; i < image->Opcodes->size; i++) { - // printf("%d\n", ((IROpcode*) image->Opcodes->content[i])->Mnemonic); - //} - - //FILE* program = fopen("program.bin", "w+b"); - - //fwrite(image, 1, image[2] + image[3], program); - - //fclose(program); - free(source_code); -} - -void Setup(IRState* state) { - int start = 4; - int end = start; - - for(int i = 0; i < state->SymbolsTable->Size; i++) { - Symbol* symbol = state->SymbolsTable->Symbols[i]; - - switch(symbol->Type) { - case StringSymbol: - memccpy(&Memory[end], symbol->Value.String->String, 0, strlen(symbol->Value.String->String)); - - end += strlen(symbol->Value.String->String); - - if (symbol->Value.String->Terminated) { - Memory[end] = symbol->Value.String->TerminatingByte; - end++; - } - - //end++; - break; - case NumericSymbol: - Memory[end] = symbol->Value.Number >> 8 & 0xFF; - Memory[end + 1] = symbol->Value.Number & 0xFF; - end += 2; - break; - case InstructionPointerSymbol: - break; - default: - break; - } - } - - for(int i = 0; i < end; i++) { - if (i != 0 && i % 8 == 0) printf("\n"); - printf("%02x ", Memory[i]); - } - printf("\n"); } \ No newline at end of file diff --git a/src/opcodes.c b/src/opcodes.c index 1450540..aacd83a 100644 --- a/src/opcodes.c +++ b/src/opcodes.c @@ -15,9 +15,7 @@ struct _instruction instructions[OPCODECOUNT] = { { "add", ADD, RegisterParameter, RegisterParameter }, { "sub", SUB, RegisterParameter, RegisterParameter },//, Reg, Reg | Constant }, { "jz", JZ, AddressParameter, NoParameter },//, Address, None }, - { "int", INT, ConstantParameter, NoParameter },//, Constant, None }, { "yld", YLD, NoParameter, NoParameter },//, None, None }, - { "ret", RET, NoParameter, NoParameter },//, None, None }, { "cmp", CMP, RegisterParameter, RegisterParameter },//, Reg, Reg | Constant }, { "cmpi", CMPI, RegisterParameter, ConstantParameter }, { "inc", INC, RegisterParameter, NoParameter },//, Constant | Reg, None}, @@ -41,7 +39,9 @@ struct _instruction instructions[OPCODECOUNT] = { { "not", NOT, RegisterParameter, NoParameter }, { "shr", SHR, RegisterParameter, ConstantParameter }, { "shl", SHL, RegisterParameter, ConstantParameter }, - { "nop", NOP, NoParameter, NoParameter } + { "nop", NOP, NoParameter, NoParameter }, + { "pop", POP, RegisterParameter, NoParameter }, + { "push", PUSH, RegisterParameter, NoParameter } }; void ExpectParameters(Mnemonic mnemonic, OpcodeParameter* paramOne, OpcodeParameter* paramTwo) { diff --git a/src/scanner.c b/src/scanner.c index d193f4c..f3c5011 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -67,7 +67,7 @@ List* GenerateTokenList(const char* source) { Line++; } break; - case '.': //directive like ".org" or ".db" + case '.': //directive like ".include" or ".db" token = ParseDirective(); if (token) AddListItem(token, tokens); break; @@ -191,17 +191,16 @@ Token* ParseDirective(void) { return token; } - else if (strcmp(directive, ".org") == 0) { - fprintf(stderr, "[Warning] Org is not a supported directive.\n"); - free(directive); - free(token); - IgnoreLine(); - return NULL; + else if (strcmp(directive, ".include") == 0) { + token->Value.Directive = Include; + + return token; } fprintf(stderr, "[Error] Unknown assembler directive '%s'\n", directive); free(directive); + free(token); IgnoreLine();