249 lines
6.8 KiB
C
249 lines
6.8 KiB
C
#include <bits/types/FILE.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sysexits.h>
|
|
#include "../includes/token.h"
|
|
#include "../includes/futil.h"
|
|
#include "../includes/scanner.h"
|
|
#include "../includes/parser.h"
|
|
|
|
const char* MagicStartName = "__start";
|
|
TokenList* LIST;
|
|
SymbolTable* Symbols = NULL;
|
|
|
|
unsigned char mem[128] = {0};
|
|
void print(void);
|
|
void assemble(void);
|
|
|
|
int main(int argc, char* args[]) {
|
|
if (argc == 1) {
|
|
printf("Usage: assm <file1.asm>\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 = GenerateTokenList(source_code);
|
|
|
|
ParseTokens(LIST, &Symbols);
|
|
|
|
free(source_code);
|
|
|
|
assemble();
|
|
|
|
printf("\nBytes:\n");
|
|
for(unsigned long i = 0; i < sizeof(mem); i++) {
|
|
if (i != 0 && i % 8 == 0) printf("\n");
|
|
printf("%02X ", mem[i] & 0xFF);
|
|
}
|
|
printf("\n");
|
|
}
|
|
|
|
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");
|
|
break;
|
|
}
|
|
|
|
if (t->Class == PunctuationClass){
|
|
if(t->Value.Punctuation == NewLine) {
|
|
printf("<%d>\n", t->LineNumber);
|
|
continue;
|
|
}
|
|
|
|
printf("[P]%c", t->Value.Punctuation);
|
|
continue;
|
|
}
|
|
|
|
if (t->Class == LabelClass) {
|
|
printf("[L]%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("[C]'%s'", t->Lemexe);
|
|
}
|
|
}
|
|
}
|
|
|
|
int CurrentIndex = 0;
|
|
int PC2 = 0;
|
|
|
|
void WriteByte(unsigned char byte) {
|
|
mem[PC2] = byte;
|
|
PC2++;
|
|
}
|
|
|
|
void WriteWord(unsigned short word) {
|
|
mem[PC2] = (word >> 8) & 0xFF;
|
|
mem[PC2 + 1] = word & 0xFF;
|
|
PC2 += 2;
|
|
}
|
|
|
|
unsigned short GetValueFromToken(Token* token) {
|
|
if (token->Class & IdentifierClass) {
|
|
Symbol* symbol;
|
|
|
|
if (TryGetSymbol(token->Lemexe, Symbols, &symbol)) {
|
|
return symbol->Address;
|
|
}
|
|
else {
|
|
fprintf(stderr, "Failed to find symbol %s while assembling.\n", token->Lemexe);
|
|
|
|
exit(1);
|
|
}
|
|
}
|
|
else if (token->Class == NumberClass) return token->Value.Number;
|
|
|
|
fprintf(stderr, "Failed to find token '%d' while assmbling.\n", token->Class);
|
|
|
|
exit(1);
|
|
}
|
|
|
|
int IsAtEnd(void){
|
|
return CurrentIndex >= LIST->size;
|
|
}
|
|
|
|
void assemble() {
|
|
while(!IsAtEnd()) {
|
|
Token* current = LIST->content[CurrentIndex];
|
|
switch(current->Value.Mnemonic) {
|
|
case COPYA:
|
|
case COPYAB:
|
|
CurrentIndex++;
|
|
|
|
WriteByte(current->Value.Mnemonic | ((Token*) LIST->content[CurrentIndex])->Value.Register);
|
|
CurrentIndex++;
|
|
WriteWord(GetValueFromToken(LIST->content[CurrentIndex]));
|
|
break;
|
|
case COPYRA:
|
|
case COPYRAB:
|
|
case COPYRARA:
|
|
case COPYRARAB:
|
|
case COPY:
|
|
CurrentIndex++;
|
|
|
|
WriteByte(current->Value.Mnemonic | ((Token*) LIST->content[CurrentIndex])->Value.Register);
|
|
CurrentIndex++;
|
|
WriteByte(((Token*) LIST->content[CurrentIndex])->Value.Register);
|
|
break;
|
|
case COPYI: //TODO: should explicitly get number from value I feel
|
|
CurrentIndex++;
|
|
|
|
WriteByte(current->Value.Mnemonic | ((Token*) LIST->content[CurrentIndex])->Value.Register);
|
|
CurrentIndex++;
|
|
WriteWord(GetValueFromToken(LIST->content[CurrentIndex]));
|
|
break;
|
|
case COPYB:
|
|
CurrentIndex++;
|
|
|
|
WriteByte(current->Value.Mnemonic | ((Token*) LIST->content[CurrentIndex])->Value.Register);
|
|
CurrentIndex++;
|
|
WriteByte((unsigned char)GetValueFromToken(LIST->content[CurrentIndex]));
|
|
break;
|
|
case CMP:
|
|
CurrentIndex++;
|
|
|
|
WriteByte(current->Value.Mnemonic | ((Token*) LIST->content[CurrentIndex])->Value.Register);
|
|
CurrentIndex++;
|
|
WriteByte(((Token*) LIST->content[CurrentIndex])->Value.Register);
|
|
break;
|
|
case CMPI:
|
|
CurrentIndex++;
|
|
|
|
WriteByte(current->Value.Mnemonic | ((Token*) LIST->content[CurrentIndex])->Value.Register);
|
|
CurrentIndex++;
|
|
WriteWord(GetValueFromToken(LIST->content[CurrentIndex]));
|
|
break;
|
|
case ADD:
|
|
case SUB:
|
|
case AND:
|
|
case OR:
|
|
case XOR:
|
|
CurrentIndex++;
|
|
|
|
WriteByte(current->Value.Mnemonic | ((Token*) LIST->content[CurrentIndex])->Value.Register);
|
|
CurrentIndex++;
|
|
WriteByte(((Token*) LIST->content[CurrentIndex])->Value.Register);
|
|
break;
|
|
case SHL:
|
|
case SHR:
|
|
CurrentIndex++;
|
|
|
|
WriteByte(current->Value.Mnemonic | ((Token*) LIST->content[CurrentIndex])->Value.Register);
|
|
CurrentIndex++;
|
|
WriteWord(GetValueFromToken(LIST->content[CurrentIndex]));
|
|
break;
|
|
case INC:
|
|
case DEC:
|
|
case PUSH:
|
|
case POP:
|
|
case JMPI:
|
|
CurrentIndex++;
|
|
|
|
WriteByte(current->Value.Mnemonic | ((Token*) LIST->content[CurrentIndex])->Value.Register);
|
|
break;
|
|
case JMP:
|
|
case JZ:
|
|
case JG:
|
|
case JL:
|
|
WriteByte(current->Value.Mnemonic);
|
|
CurrentIndex++;
|
|
WriteWord(GetValueFromToken(LIST->content[CurrentIndex]));
|
|
break;
|
|
case NOP:
|
|
case RET:
|
|
WriteByte(current->Value.Mnemonic);
|
|
break;
|
|
case CALL:
|
|
WriteByte(current->Value.Mnemonic);
|
|
CurrentIndex++;
|
|
WriteWord(GetValueFromToken(LIST->content[CurrentIndex]));
|
|
default:
|
|
break;
|
|
}
|
|
|
|
CurrentIndex++;
|
|
}
|
|
}
|
|
|