Started rethinking how this machine should behave. Updated and refactoring some things with a few new ideas.

This commit is contained in:
2023-02-23 22:22:07 -06:00
parent 9a602824b6
commit 1b246e90bc
8 changed files with 68 additions and 193 deletions
+8 -2
View File
@@ -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}
+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
STOB, STOW, JG, JL, AND, XOR, OR, NOT, SHR, SHL, POP, PUSH
} Mnemonic;
typedef enum {
+1 -1
View File
@@ -23,7 +23,7 @@ typedef enum {
typedef enum {
DB,
Origin,
Include,
Byte
} Directive;
+3
View File
@@ -0,0 +1,3 @@
some_stub:
pop r8
jmp [r8] ;return to the calling code.
+6 -2
View File
@@ -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
+40 -177
View File
@@ -4,14 +4,9 @@
#include <string.h>
#include <sysexits.h>
#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 <file1.asm>\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");
}
+3 -3
View File
@@ -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) {
+6 -7
View File
@@ -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();