diff --git a/src/assets/error.png b/src/assets/error.png
new file mode 100644
index 0000000..5365ce3
Binary files /dev/null and b/src/assets/error.png differ
diff --git a/src/assets/ok.png b/src/assets/ok.png
new file mode 100644
index 0000000..d12c49d
Binary files /dev/null and b/src/assets/ok.png differ
diff --git a/src/assets/pause.png b/src/assets/pause.png
new file mode 100644
index 0000000..4f55430
Binary files /dev/null and b/src/assets/pause.png differ
diff --git a/src/components/ControlPanel.vue b/src/components/ControlPanel.vue
index e947463..6a81685 100644
--- a/src/components/ControlPanel.vue
+++ b/src/components/ControlPanel.vue
@@ -1,18 +1,32 @@
@@ -25,11 +35,15 @@ runner.AddEventListener("PCChanged", (_) => {
-
{{ index + 1 }}
+
{{ index }}
{{ instruction[0] }}
{{ instruction[1] }}
{{ instruction[2] }}
+
+
{{ asmCode[index][0] }}
+
{{ asmCode[index][1] }},
+
{{ asmCode[index][2] }}
@@ -81,10 +95,31 @@ span {
.operand {
color: rgb(224, 108, 117);
+
}
.gutter {
display: inline;
width: 9px;
}
+
+.split {
+ margin-left: 10px;
+ background-color: #9e9e9e;
+ width: 1px;
+ height: 28px;
+}
+
+.asm-mnemonic {
+ color: rgb(198, 120, 221);
+ margin-left: 10px;
+ padding-right: 10px;
+ width: 50px;
+}
+
+.asm-operand {
+ color: rgb(224, 108, 117);
+ margin-left: 5px;
+ width: 30px;
+}
\ No newline at end of file
diff --git a/src/components/MemoryLayout.vue b/src/components/MemoryLayout.vue
index fb2f697..6ab76cc 100644
--- a/src/components/MemoryLayout.vue
+++ b/src/components/MemoryLayout.vue
@@ -96,7 +96,7 @@ let memory = computed(() => {
}
.register-loose-layout {
- grid-template-columns: repeat(7, 1fr);
+ grid-template-columns: repeat(8, 1fr);
}
.register-compact-layout {
@@ -150,6 +150,7 @@ span {
.screen-row {
color: rgb(224, 188, 105);
+ white-space: nowrap;
}
.screen-memory {
diff --git a/src/utils/Complier.ts b/src/utils/Complier.ts
index 815217d..dcdaec0 100644
--- a/src/utils/Complier.ts
+++ b/src/utils/Complier.ts
@@ -5,7 +5,6 @@ export class CompileError extends Error {
super(message);
this.index = index;
}
-
index: number;
}
@@ -204,6 +203,8 @@ export class Compiler {
mnemonicAndVals[i] = this.Labels.get(mnemonicAndVals[i])!.toString(16).padStart(2,'0');
else
mnemonicAndVals[i] = parseInt(mnemonicAndVals[i]).toString(16).padStart(2,'0');
+ if (mnemonicAndVals[1] === 'NaN'||mnemonicAndVals[2] === 'NaN')
+ throw new CompileError("Invalid operand", index);
this.PCToMachineCode.set(pc, Compiler.KeyWordsToMachineCode.get(mnemonicAndVals[0])! + mnemonicAndVals[1] + mnemonicAndVals[2]);
});
} catch (e) {
diff --git a/src/utils/Runner.ts b/src/utils/Runner.ts
index 1f74a5a..8a7a6ab 100644
--- a/src/utils/Runner.ts
+++ b/src/utils/Runner.ts
@@ -1,6 +1,15 @@
import {MemoryManager, Byte} from "./MemoryManager";
import {Compiler} from "./Complier.ts";
+export class RunningError extends Error {
+ constructor(message: string, index: number) {
+ super(message);
+ this.index = index;
+ }
+
+ index: number;
+}
+
export enum RunnerState {
Stop,
Running,
@@ -9,7 +18,7 @@ export enum RunnerState {
export class Runner {
// 与Compiler 类似的事件机制 要是再来一个我就把这段逻辑单独抽出来
- //[PCChanged,RegistersChanged]
+ //[PCChanged,RegistersChanged,RunningError(string,RunningError)]
_events: Map void)[]> = new Map void)[]>();
AddEventListener(event: string, callback: (arg0: string, arg1?: any) => void) {
@@ -28,6 +37,7 @@ export class Runner {
}
State: RunnerState = RunnerState.Stop;
+ _runningSpeed: number = 20;
_processor: Processor;
_memory: MemoryManager;
_processCounter: number = 0;
@@ -35,6 +45,18 @@ export class Runner {
_stack: [Byte[], number][] = [];
_intervalId: NodeJS.Timeout | null = null;
+ set RunningSpeed(speed: number) {
+ this._runningSpeed = speed;
+ if (this.State === RunnerState.Running) {
+ this.Pause();
+ this.Resume();
+ }
+ }
+
+ get RunningSpeed() {
+ return this._runningSpeed;
+ }
+
StartInterval() {
if (this._intervalId === null)
this._intervalId = setInterval(() => {
@@ -43,7 +65,7 @@ export class Runner {
return;
}
this.RunOneLineCode();
- }, 20);
+ }, this._runningSpeed);
}
StopInterval() {
@@ -73,30 +95,44 @@ export class Runner {
if (this._compiler.PCToCode.has(this._processCounter))
code = this._compiler.PCToCode.get(this._processCounter) as string;
else
- throw new Error("PC out of range");
+ throw new RunningError("PC out of range", 0);
this._processCounter++;
let mnemonicAndVals = code.split(/[\s,]+/);
// 如果指令不合法 Compiler应该会有异常抛出 则不能执行到这里
if (mnemonicAndVals.length !== 3)
- throw new Error("Invalid code");
+ throw new RunningError("Invalid code", this._processCounter);
let mnemonic = mnemonicAndVals[0];
- function getVal(runner:Runner, val: string) {
+
+ function getVal(runner: Runner, val: string) {
if (runner._processor._registers.has(val))
return val;
- else if(runner._compiler.Labels.has(val))
+ else if (runner._compiler.Labels.has(val))
return runner._compiler.Labels.get(val) as number;
else {
let t = parseInt(val);
- if(isNaN(t))
- throw new Error("Invalid argument");
+ if (isNaN(t)) {
+ throw new RunningError("Invalid argument", runner._processCounter);
+ }
return t;
}
}
- return [mnemonic, getVal(this,mnemonicAndVals[1]), getVal(this,mnemonicAndVals[2])];
+
+ return [mnemonic, getVal(this, mnemonicAndVals[1]), getVal(this, mnemonicAndVals[2])];
}
RunOneLineCode() {
- this._processor.RunCode(...this.CommandParsing(), this.GetMemory, this.SetMemory, this.SetPC, this.SaveEnv, this.RestoreEnv);
+ try {
+ this._processor.RunCode(...this.CommandParsing(), this.GetMemory, this.SetMemory, this.SetPC, this.SaveEnv, this.RestoreEnv);
+ }catch (e:any)
+ {
+ console.log(e);
+ e = e as RunningError;
+ if(e === undefined)
+ throw new RunningError("Unknown error",this._processCounter);
+ e.index = e.index === -1? this._processCounter : e.index;
+ this.Pause();
+ this.Notify("RunningError", e);
+ }
this.Notify("PCChanged");
this.Notify("RegistersChanged");
}
@@ -128,9 +164,16 @@ export class Runner {
this.RunOneLineCode()
}
+ Pause() {
+ this.State = RunnerState.Stop;
+ this.StopInterval()
+ }
+
Stop() {
this.State = RunnerState.Stop;
this.StopInterval()
+ this._processCounter = 0;
+ this._memory.clear();
}
Refresh() {
@@ -138,38 +181,31 @@ export class Runner {
}
GetMemory(t: number): Byte {
- console.log(this._memory)
return this._memory.GetVal(t);
}
SetMemory(t: number, val: Byte): void {
- console.log("mem Test:")
- console.log(this)
- console.log(this._memory)
-
this._memory.SetVal(t, val);
}
SaveEnv() {
if (this._stack.length > 8)
- throw new Error("Stack overflow");
- this._stack.push([this._processor.GetRegisters().map(x=>x.Copy()), this._processCounter]);
+ throw new RunningError("Stack overflow",this._processCounter);
+ this._stack.push([this._processor.GetRegisters().map(x => x.Copy()), this._processCounter]);
}
RestoreEnv() {
if (this._stack.length === 0) {
- this.Stop();
+ this.Pause();
return;
}
let [regs, pc] = this._stack.pop()!;
- console.log('restore',regs);
this._processor.SetRegisters(regs);
this._processCounter = pc;
}
SetPC(addr: number) {
this._processCounter = addr;
- console.log("PC set to", addr);
}
GetRegisters(): Byte[] {
@@ -202,17 +238,15 @@ class Processor {
if (this._registers.has(register as string))
return this._registers.get(register as string)!;
else
- throw new Error("Invalid register");
+ throw new RunningError("Invalid register",-1);
}
GetRegisters(): Byte[] {
- console.log("Get", this._registers.values());
return Array.from(this._registers.values());
}
SetRegisters(registers: Byte[]) {
for (let i = 0; i < 7; i++) {
- console.log("Set", String.fromCharCode('A'.charCodeAt(0) + i) + 'X',registers[i].value);
this._registers.get(String.fromCharCode('A'.charCodeAt(0) + i) + 'X')!.SetValue(registers[i]);
}
}
@@ -222,7 +256,12 @@ class Processor {
}
SetRegisterValue(register: string | number, value: number) {
- this.GetRegister(register).SetValue(value);
+ try {
+ this.GetRegister(register).SetValue(value);
+ }catch (e)
+ {
+ throw new RunningError("Invalid value",-1);
+ }
}
InRegister(register: string | number): boolean {
@@ -230,11 +269,15 @@ class Processor {
}
RunCode(mnemonic: string, operandA: number | string, operandB: number | string, getMemory: (addr: number) => Byte, setMemory: (addr: number, value: Byte) => void, setPC: (addr: number) => void, saveEnv: () => void, restoreEnv: () => void) {
- console.log(mnemonic, operandA, operandB);
- if(this.InRegister(operandA))
- console.log(this.GetRegisterValue(operandA));
- if(this.InRegister(operandB))
- console.log(this.GetRegisterValue(operandB));
+ {
+ let a = operandA;
+ let b = operandB;
+ if (this.InRegister(a))
+ a = a + '(' + this.GetRegisterValue(a) + ')';
+ if (this.InRegister(b))
+ b = b + '(' + this.GetRegisterValue(b) + ')';
+ console.log(mnemonic,a,b);
+ }
switch (mnemonic) {
case "nop":
break;
@@ -301,7 +344,6 @@ class Processor {
}
break;
case "st":
- console.log(operandA, operandB);
if (this.InRegister(operandA) && typeof operandB === 'number') {
setMemory(operandB as number, this.GetRegister(operandA));
return;
@@ -311,18 +353,15 @@ class Processor {
if (this.InRegister(operandA) && this.InRegister(operandB)) {
this.GetRegister(operandA).SetValue(this.GetRegister(operandB));
return;
- }
- else if(this.InRegister(operandA) && typeof operandB === 'number') {
+ } else if (this.InRegister(operandA) && typeof operandB === 'number') {
this.GetRegister(operandA).SetValue(operandB);
return;
}
break;
case "cp":
- console.log(operandA, operandB);
operandA = this.InRegister(operandA) ? this.GetRegisterValue(operandA) : operandA;
operandB = this.InRegister(operandB) ? this.GetRegisterValue(operandB) : operandB;
if (typeof operandA === 'number' && typeof operandB === 'number') {
- console.log(operandA, operandB);
for (let i = 0; i < (this._registers.get("BX")!.GetValue() as number); i++)
setMemory(operandB + i, getMemory(operandA + i));
return;
@@ -368,7 +407,9 @@ class Processor {
return;
}
break
+ default:
+ throw new RunningError("Invalid mnemonic",-1);
}
- throw new Error("Invalid argument");
+ throw new RunningError("Invalid argument",-1);
}
}