Add constants to assembler
This commit is contained in:
parent
297daafc89
commit
d3134aa9e6
59
assembler.js
59
assembler.js
|
|
@ -34,9 +34,10 @@ function decodeInstructions(str) {
|
|||
machineCode[0] = POINTER_TO_START_OF_DISPLAY_MEM;
|
||||
|
||||
let labels = {};
|
||||
let constants = {};
|
||||
let IP = INITIAL_IP_ADDRESS;
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
dbg(1, '');
|
||||
dbg(2, '');
|
||||
dbgGroup(1, `Input line ${i}, IP ${num2hex(IP)}`);
|
||||
dbg(3, `> ${lines[i]}`);
|
||||
let line = stripWhitespaceFromEnds(stripComments(lines[i]));
|
||||
|
|
@ -49,11 +50,14 @@ function decodeInstructions(str) {
|
|||
continue;
|
||||
}
|
||||
|
||||
// Handle labels -- anchors
|
||||
|
||||
// HANDLE OPS
|
||||
|
||||
// Handle label definitions
|
||||
if (line.startsWith('@')) {
|
||||
// TODO: validate label
|
||||
// validateLabel(line);
|
||||
label = line.substring(1); // strip '@'
|
||||
let label = line.substring(1); // strip '@'
|
||||
|
||||
if (label in labels) {
|
||||
labels[label].pointsToByte = IP;
|
||||
|
|
@ -72,21 +76,36 @@ function decodeInstructions(str) {
|
|||
|
||||
let op_arg_array = line.split(" "); // split line into an array of [op, arg]
|
||||
let opName = op_arg_array[0].toLowerCase();
|
||||
let addressingMode = 'direct'; // Must be "direct" or "indirect"
|
||||
let arg_str = op_arg_array[1];
|
||||
let arg_num = null;
|
||||
let addressingMode = 'direct'; // Must be "direct" or "indirect"
|
||||
|
||||
// Handle constant definitions
|
||||
if (opName.startsWith('=')) {
|
||||
// TODO: validate constant
|
||||
let constantName = opName.substring(1); // strip '>'
|
||||
let constantValue = arg_str;
|
||||
constants[constantName] = constantValue;
|
||||
dbg(2, `constants:`);
|
||||
dbg(2, constants);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle mnemonics without arguments (eg END) ...
|
||||
if (typeof arg_str === 'undefined') {
|
||||
// Handle mnemonics without arguments (eg END) ...
|
||||
if (mnemonicsWithOptionalArgs.indexOf(opName) < 0) {
|
||||
console.error(`Missing opcode: ${line}`);
|
||||
throw new Error("Missing opcode");
|
||||
}
|
||||
arg_num = 0;
|
||||
|
||||
|
||||
// HANDLE ARGUMENTS
|
||||
|
||||
// Handle references to labels
|
||||
} else if (arg_str.startsWith('@')) {
|
||||
// Handle mnemonics with pointers to labels
|
||||
// TODO: validate label // validateLabel(line);
|
||||
label = arg_str.substring(1); // strip '@'
|
||||
let label = arg_str.substring(1); // strip '@'
|
||||
arg_num = 0;
|
||||
|
||||
if (label in labels) {
|
||||
|
|
@ -100,8 +119,24 @@ function decodeInstructions(str) {
|
|||
}
|
||||
dbg(2, `pointsToByte: ${labels[label].pointsToByte}`);
|
||||
dbg(2, `bytesToReplace: ${labels[label].bytesToReplace}`);
|
||||
|
||||
// Handle references to constants
|
||||
} else if (arg_str.startsWith('=')) {
|
||||
arg_str = arg_str.substring(1) // strip '>'
|
||||
dbg(2, `argument references '${arg_str}'`);
|
||||
arg_str = constants[arg_str];
|
||||
dbg(2, `arg_str from '${arg_str}`);
|
||||
|
||||
// Handle references to constants in indirect mode
|
||||
} else if (arg_str.startsWith("(=")) {
|
||||
addressingMode = "indirect";
|
||||
arg_str = arg_str.replace("(=", "");
|
||||
arg_str = arg_str.replace(")", "");
|
||||
dbg(2, `INDY - argument references '${arg_str}'`);
|
||||
arg_str = constants[arg_str];
|
||||
|
||||
// Handle indirect expressions
|
||||
} else if (arg_str.startsWith("(")) {
|
||||
// Handle indirect expressions
|
||||
addressingMode = "indirect";
|
||||
arg_str = arg_str.replace("(", "");
|
||||
arg_str = arg_str.replace(")", "");
|
||||
|
|
@ -119,7 +154,7 @@ function decodeInstructions(str) {
|
|||
}
|
||||
}
|
||||
|
||||
// Decode!
|
||||
// DECODE!
|
||||
op = mnemonics2opcodes[opName][addressingMode];
|
||||
|
||||
machineCode.push(op);
|
||||
|
|
@ -130,11 +165,11 @@ function decodeInstructions(str) {
|
|||
};
|
||||
|
||||
dbg(1, '');
|
||||
dbgGroup(1, 'Memory before filling in label pointers');
|
||||
dbgGroup(1, 'Memory before filling in label constants');
|
||||
dbgExec(1, () => logMemory(machineCode));
|
||||
dbgGroupEnd(1, 'Memory before filling in label pointers');
|
||||
dbgGroupEnd(1, 'Memory before filling in label constants');
|
||||
|
||||
// Backfill label pointers
|
||||
// Backfill label references
|
||||
for (let k of Object.keys(labels)) {
|
||||
dbgGroup(2, `@${k}`);
|
||||
let label = labels[k];
|
||||
|
|
|
|||
13
readme.md
13
readme.md
|
|
@ -10,12 +10,14 @@
|
|||
|
||||
### Features
|
||||
|
||||
- [ ] Make $0F a NOP
|
||||
- [ ] Assembler: pad to 256 bytes, OR, to start, always add an END
|
||||
- [x] Add constants to assembler
|
||||
- [ ] Keypad
|
||||
- [ ] Add single-stepping
|
||||
- [x] Make $0F a NOP
|
||||
- [ ] In assembler.js: validateLabel()
|
||||
- [ ] In assemble.js: print better output to stdout
|
||||
- [ ] Add a function for logging just a specific range of memory
|
||||
- [ ] Add single-stepping
|
||||
- [ ] Add variables to assembler
|
||||
|
||||
### Under-the-hood improvements
|
||||
|
||||
|
|
@ -104,5 +106,10 @@ Assemble and run, with debug output:
|
|||
; the label will be replaced with
|
||||
; the address of the label
|
||||
|
||||
=foo $FF ; define a constant
|
||||
; (must be defined before it is referenced)
|
||||
|
||||
ADD =foo ; use a constant as an operand
|
||||
|
||||
- Hexadecimal numbers are preceded by a `$`
|
||||
- Whitespace is ignored
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
;; Test constants
|
||||
=foo $01
|
||||
=bar $02
|
||||
ADD =foo
|
||||
STO =bar
|
||||
STO (=bar)
|
||||
END
|
||||
Loading…
Reference in New Issue