diff --git a/assembler.js b/assembler.js index 941ba99..059f68a 100644 --- a/assembler.js +++ b/assembler.js @@ -74,7 +74,7 @@ function preparseSourceCode(source) { } return lines.map((line, index) => { - console.log('pre-parsing ', line); + dbg('2', ` ${line}`); let info = { number: index, source: line, @@ -87,7 +87,7 @@ function preparseSourceCode(source) { if (op_arg_array[0] !== 'undefined') { info.operation = op_arg_array[0]; } - if (op_arg_array[1] !== 'undefined') { + if (op_arg_array.length === 2) { info.argument = op_arg_array[1]; } } @@ -124,9 +124,10 @@ function handleLabelDefinition(op, IP, labels) { bytesToReplace: [], }; } - dbg(2, `pointsToByte: ${labels[label].pointsToByte}`); - dbg(2, `bytesToReplace: ${labels[label].bytesToReplace}`); - dbg(3, `IP: $${num2hex(IP)}, new code: none`); + dbg(2, ` Label definition:`); + dbg(2, ` Points to byte: ${labels[label].pointsToByte}`); + dbg(2, ` Bytes to replace: ${labels[label].bytesToReplace}`); + dbg(3, ` IP: $${num2hex(IP)}, new code: none`); dbgGroupEnd(1, 'Input line'); return labels; } @@ -144,8 +145,9 @@ function handleConstantDefinitions(op, arg, IP, constants) { constantValue = IP.toString(); } constants[constantName] = constantValue; - dbg(2, `constants:`); - dbg(2, constants); + dbg(1, `Constants:`); + dbg(1, constants); + dbg(1, ''); return constants; } @@ -159,6 +161,7 @@ function assembleMnemonicsWithOptionalArgs(line) { throw new Error("Missing opcode"); } let opcode = decodeNumericOp(line.operation); + console.log('decoding op without operand', line); let operand = line.argument !== null ? decodeNumericOp(line.argument) : 0; return [opcode, operand]; } @@ -174,7 +177,12 @@ function assembleMnemonicsWithOptionalArgs(line) { * @return TODO **/ function decodeInstructions(source) { + dbg(2, 'Pre-parsing...'); let lines = preparseSourceCode(source); + dbg(2, ''); + dbg(2, 'Done pre-parsing.'); + dbg(2, ''); + dbg(2, 'Assembling...'); // Figure out where to start assembly... @@ -207,12 +215,13 @@ function decodeInstructions(source) { // Decode line by line... for (let i = 0; i < lines.length; i++) { let line = lines[i]; - console.log(line); + // dbg(2, `line info:`); + // dbg(2, line); if (line.type === 'code') { const op = line.operation; - const arg = null; + let arg = null; if (typeof line.argument != 'undefined') { - const arg = line.argument; + arg = line.argument; } @@ -250,6 +259,14 @@ function decodeInstructions(source) { // Now that it can't be a label or a constant, normalize the opcode line.operation = line.operation.toLowerCase(); + // Opcodes - Handle mnemonics without operands (eg END) + if (arg === null) { + if (mnemonicsWithOptionalArgs.indexOf(line.operation) < 0) { + console.error(`Missing opcode for line ${line.number}: ${line.source}`); + throw new Error("Missing opcode"); + } + decodedArg = 0; + } // Operands - Handle references to labels if (arg !== null && arg.startsWith(ASM_LABEL_PREFIX)) { @@ -263,28 +280,28 @@ function decodeInstructions(source) { bytesToReplace: [IP + 1], }; } - dbg(2, `pointsToByte: ${labels[label].pointsToByte}`); - dbg(2, `bytesToReplace: ${labels[label].bytesToReplace}`); - let code = [decodeNumericOp(line.operation), 0] // Return 0 for operand for now -- we'll replace it later + dbg(2, ` Label reference:`); + dbg(2, ` Points to byte: ${labels[label].pointsToByte}`); + dbg(2, ` Bytes to replace: ${labels[label].bytesToReplace}`); + decodedArg = 0; // Return 0 for operand for now -- we'll replace it later } // Operands - Handle references to the Instruction Pointer if (arg !== null && arg === ASM_IP_LABEL) { - dbg(2, `operand references current address`); + dbg(2, ` References current IP - ${IP}`); decodedArg = IP; - dbg(2, `arg_num: ${num2hex(decodedArg)}`); } // Operands - Handle references to constants if (arg !== null && arg.startsWith(ASM_CONSTANT_PREFIX)) { - dbg(2, `operand references '${arg}'`); + dbg(2, ` References '${arg}'`); decodedArg = constants[arg.substring(1)]; // substring(1) strips '>' } // Operands - Handle references to constants in indirect mode if (arg !== null && arg.startsWith(`(${ASM_CONSTANT_PREFIX}`)) { addressingMode = "indirect"; - dbg(2, `IND - operand references '${arg}'`); + dbg(2, ` (Indirectly) References '${arg}'`); let constTemp = arg.replace(`(${ASM_CONSTANT_PREFIX}`, "").replace(")", ""); decodedArg = constants[constTemp]; } @@ -296,39 +313,44 @@ function decodeInstructions(source) { decodedArg = decodeNumericOp(indyTemp); } - // Opcodes - Handle mnemonics without operands (eg END) - if (arg === null) { - if (mnemonicsWithOptionalArgs.indexOf(line.operation) < 0) { - console.error(`Missing opcode for line ${line.number}: ${line.source}`); - throw new Error("Missing opcode"); - } - decodedOp = decodeNumericOp(line.operation); - decodedArg = line.argument !== null ? decodeNumericOp(line.argument) : 0; - } - + // Decode regular opcodes if (decodedOp === null) { decodedOp = mnemonics2opcodes[line.operation][addressingMode]; } - machineCode.push(decodedOp); - machineCode.push(decodedArg); - dbg(3, `IP: $${num2hex(IP)}, new code: $${num2hex(decodedOp)} $${num2hex(decodedArg)}`); + // Decode regular operands + if (decodedArg === null) { + decodedArg = decodeNumericOp(line.argument); + } + + machineCode[IP] = decodedOp; + machineCode[IP + 1] = decodedArg; + + dbg(3, ``); + dbg(3, `Line ${line.number}: ${line.source}`); + if (line.argument) { + dbg(3, ` Asm operation: ${line.operation.toUpperCase()} ${line.argument}`); + } else if (line.operation) { + dbg(3, ` Asm operation: ${line.operation.toUpperCase()}`); + } + + dbg(3, ` Machine code: $${num2hex(decodedOp)} $${num2hex(decodedArg)}`); + dbg(3, ` IP: $${num2hex(IP)}`); + dbg(3, ''); IP += 2; - dbgGroupEnd(1, 'Input line'); }; } - dbg(1, ''); dbgGroup(1, 'Memory before filling in label constants'); dbgExec(1, () => logMemory(new Uint8Array(machineCode))); - dbgGroupEnd(1, 'Memory before filling in label constants'); + dbgGroupEnd(1); // Backfill label references for (let k of Object.keys(labels)) { dbgGroup(2, `${ASM_LABEL_PREFIX}${k}`); let label = labels[k]; - dbg(2, `pointsToByte: ${label.pointsToByte}`); - dbg(2, `bytesToReplace: ${label.bytesToReplace}`); + dbg(2, `Points to byte: ${label.pointsToByte}`); + dbg(2, `Bytes to replace: ${label.bytesToReplace}`); dbgGroupEnd(2, `label`); for (let j = 0; j < label.bytesToReplace.length; j++) { machineCode[label.bytesToReplace[j]] = label.pointsToByte; diff --git a/run-assembler.js b/run-assembler.js index 3bf2e3a..e8671ac 100755 --- a/run-assembler.js +++ b/run-assembler.js @@ -17,6 +17,7 @@ let machineCode; if (mode === "debug") { machineCode = assembler.assemble(inputFile_str, true); + console.log(''); console.group("Machine code output"); logMemory(machineCode); console.groupEnd();