more assembler stuff
This commit is contained in:
@@ -9,7 +9,8 @@ sources = files(
|
|||||||
)
|
)
|
||||||
|
|
||||||
asmSources = files(
|
asmSources = files(
|
||||||
'src/assembler/main.c'
|
'src/assembler/main.c',
|
||||||
|
'src/assembler/assemble.c'
|
||||||
)
|
)
|
||||||
|
|
||||||
args = ['-Wall', '-Wextra']
|
args = ['-Wall', '-Wextra']
|
||||||
|
|||||||
@@ -1,9 +1,170 @@
|
|||||||
#include "assemble.h"
|
#include "assemble.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "../instruction.h"
|
#include "../instruction.h"
|
||||||
|
|
||||||
void assemble(const char* input, const char* outputFileName) {
|
// Table of strings to instructions
|
||||||
|
struct _stringToInstructionOpcodeTable {char* str; InstructionOpcode opcode;} stringToInstructionOpcodeTable[] = {
|
||||||
|
{"mov", INST_MOV},
|
||||||
|
{"mvi", INST_MVI},
|
||||||
|
{"add", INST_ADD},
|
||||||
|
{"sub", INST_SUB},
|
||||||
|
{"load", INST_LOAD},
|
||||||
|
{"store", INST_STORE},
|
||||||
|
{"and", INST_AND},
|
||||||
|
{"or", INST_OR},
|
||||||
|
{"xor", INST_XOR},
|
||||||
|
{"shf", INST_SHF},
|
||||||
|
{"jmp", INST_JMP},
|
||||||
|
{"jiz", INST_JIZ},
|
||||||
|
{"call", INST_CALL},
|
||||||
|
{"ret", INST_RET},
|
||||||
|
{"sys", INST_SYS},
|
||||||
|
{"hlt", INST_HLT},
|
||||||
|
};
|
||||||
|
|
||||||
|
InstructionOpcode stringToInstructionOpcode(const char* string) {
|
||||||
|
for (size_t i = 0; i < sizeof(stringToInstructionOpcodeTable) / sizeof(struct _stringToInstructionOpcodeTable)); i++) {
|
||||||
|
if (strcmp(stringToInstructionOpcodeTable[i].str, string) == 0) {
|
||||||
|
return stringToInstructionOpcodeTable[i].opcode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Invalid instruction string %s\n", string);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Program newProgram(void) {
|
||||||
|
Program program = {
|
||||||
|
.at = malloc(sizeof(Instruction) * 16),
|
||||||
|
.len = 0,
|
||||||
|
.capacity = 16
|
||||||
|
};
|
||||||
|
|
||||||
|
if (program.at == NULL) {
|
||||||
|
fprintf(stderr, "malloc failed while creating new program\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addInstructionToProgram(Program* program, Instruction inst) {
|
||||||
|
if (program->at == NULL) {
|
||||||
|
fprintf(stderr, "unexpected NULL value when adding instruction to program\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (program->len + 1 >= program->capacity) {
|
||||||
|
Instruction* tmp = malloc(sizeof(Instruction) * program->capacity * 2);
|
||||||
|
if (tmp == NULL) {
|
||||||
|
fprintf(stderr, "malloc failed while expanding program\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
program->at = tmp;
|
||||||
|
program->capacity *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
program->at[program->len] = inst;
|
||||||
|
program->len++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeProgram(Program* program) {
|
||||||
|
if (program->at != NULL) {
|
||||||
|
free(program->at);
|
||||||
|
}
|
||||||
|
program->capacity = 0;
|
||||||
|
program->len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Essentially a lexer for the assembly language.
|
||||||
|
* @param [input] The text to create a program from. NOT the file name
|
||||||
|
* @return A new program, with all instructions from the input
|
||||||
|
*/
|
||||||
|
Program createProgramFromText(const char* input) {
|
||||||
|
Program program = newProgram();
|
||||||
|
|
||||||
|
char buf[16] = {'\0'};
|
||||||
|
size_t bufSize = 0;
|
||||||
|
size_t programLen = strlen(input);
|
||||||
|
size_t current = 0;
|
||||||
|
|
||||||
|
bool processingInstWord = true;
|
||||||
|
uint8_t processingArgNum = 0;
|
||||||
|
|
||||||
|
Instruction currentInst = {};
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
// scan through until we hit a space, colon or new line
|
||||||
|
char c = input[current];
|
||||||
|
switch (c) {
|
||||||
|
case ' ': {
|
||||||
|
if (bufSize == 0) {
|
||||||
|
// Ignore extra spaces
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (processingInstWord) {
|
||||||
|
currentInst.opcode = stringToInstructionOpcode(buf);
|
||||||
|
} else {
|
||||||
|
if (processingArgNum >= 3) {
|
||||||
|
fprintf(stderr, "expecting new line after instruction args, got %s\n", buf);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
OperandType type = INSTRUCTION_OPERAND_TYPES[currentInst.opcode][processingArgNum];
|
||||||
|
if (type == OP_NONE) {
|
||||||
|
fprintf(stderr, "expecting new line after instruction args, got %s\n", buf);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[0] = '\0';
|
||||||
|
bufSize = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '\n': {
|
||||||
|
if (processingInstWord && bufSize == 0) {
|
||||||
|
// Ignore extra new lines
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ':': {
|
||||||
|
if (!processingInstWord) {
|
||||||
|
fprintf(stderr, "label must be first word on a new line");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '\t': {
|
||||||
|
// Ignore tabs
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case '\r': {
|
||||||
|
// Ignore Windows specific formatting
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
buf[bufSize] = c;
|
||||||
|
buf[bufSize + 1] = '\0';
|
||||||
|
bufSize++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
current++;
|
||||||
|
if (current >= programLen) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
void assemble(const char* input, const char* outputFileName) {
|
||||||
|
Program program = createProgramFromText(input);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,17 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "../instruction.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Instruction* at;
|
||||||
|
size_t len;
|
||||||
|
size_t capacity;
|
||||||
|
} Program;
|
||||||
|
|
||||||
|
Program newProgram(void);
|
||||||
|
void addInstructionToProgram(Program* program, Instruction inst);
|
||||||
|
void freeProgram(Program* program);
|
||||||
|
|
||||||
|
Program createProgramFromText(const char* input);
|
||||||
|
|
||||||
void assemble(const char* input, const char* outputFileName);
|
void assemble(const char* input, const char* outputFileName);
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
dingus:
|
||||||
|
|
||||||
mvi a 2
|
mvi a 2
|
||||||
mvi b 2
|
mvi b 2
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user