private IEnumerable <string> ExpandMacros(string assemblyFilePath) { logger.log("PHASE: EXPAND MACROS"); var parser = new AssemblyParser(assemblyFilePath, null, this.logger); while (parser.HasMoreCommands() && parser.Advance()) { //if the current command is a storage macro, we should do a conversion like: //symbol = 100 //is transformed to: //////////////// //LOADAIMMEDIATE //100 //STOREA //symbol //////////////// if (parser.CommandType() == CommandType.ASSEM_STORE_MACRO) { parser.output.Add(nameof(CommandType.LOADAIMMEDIATE)); parser.output.Add(parser.Operands()[1]); parser.output.Add(nameof(CommandType.STOREA)); parser.output.Add(parser.Operands()[0]); logger.log("JUST EXPANDED A STORAGE MACRO"); logger.log(string.Join(",", parser.output.TakeLast(4))); } //all other commands are unchanged else { parser.output.Add(parser.currentLine); if (parser.HasOperands()) { parser.output = parser.output.Concat(parser.Operands()).ToList(); } logger.log("JUST EXPANDED NOTHING"); logger.log(string.Join(Environment.NewLine, parser.output.Last())); } } return(parser.output); }
private IEnumerable <string> ConvertOpCodes(IEnumerable <string> code) { logger.log("PHASE: CONVERT OPCODES TO OUTPUT FORMAT"); var parser = new AssemblyParser(null, code, this.logger); var converter = new CodeConverter(); while (parser.HasMoreCommands() && parser.Advance()) { //dont do anything for labels or defines - we already made symbols for them //in the first pass. if (parser.CommandType() != CommandType.ASSEM_LABEL && parser.CommandType() != CommandType.ASSEM_DEFINE) { //first convert the opcode. parser.output.Add(converter.InstructionAsHexString(parser.CommandType())); //then check if this opcode has symbols if (parser.HasSymbols()) { //get the symbol and lookup the memory address it points to - //store this as the next line in the output string array. // always assume a default offset of addding 0. int symbolOffset = 0; var symbol = parser.Operands()[0]; if (parser.SymbolHasOffset()) { symbolOffset = parser.symbolOffsetExpressionInfo().Item2; symbol = parser.symbolOffsetExpressionInfo().Item1; } if (this.symbolTable.ContainsKey(symbol)) { parser.output.Add(converter.NumberAsHexString(this.symbolTable[symbol] + symbolOffset)); } //new symbol store it. //increment the symbolTable offset so variables are stored at next free space at offset 255+500 ( so first one is at 755) //this means programs have a max length currently of 500 lines - and can store 1000 - 755 symbols - //to increase this we just need to modify the bootloader - we have 64k address space to play with in the cpu. //transfer time will just increase. else { var symbolTableCurrentLocation = MemoryMap[MemoryMapKeys.symbols].AbsoluteStart + this.currentSymbolTableOffset; if (symbolTableCurrentLocation > MemoryMap[MemoryMapKeys.symbols].AbsoluteEnd) { throw new Exception(" symbol table has more variables than allocated memory space for symbols"); } logger.log($"adding symbol, {symbol} at line: {symbolTableCurrentLocation}"); this.symbolTable[symbol] = symbolTableCurrentLocation; //increment the offset. this.currentSymbolTableOffset = this.currentSymbolTableOffset + 1; parser.output.Add(converter.NumberAsHexString(this.symbolTable[symbol])); } } //if no symbols check if it has any operands else if (parser.HasOperands()) { var convertedOperandsToHex = parser.Operands().Select(x => converter.NumberAsHexString(int.Parse(x))).ToArray(); parser.output = parser.output.Concat(convertedOperandsToHex).ToList(); } } } return(parser.output); }