Prefix non-ARM instructions with X: XHLT, XDIV, XMOD, XOUT
This commit is contained in:
@@ -57,7 +57,7 @@ function hl(line) {
|
|||||||
let h = line.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>')
|
let h = line.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>')
|
||||||
h = h.replace(/(;.*)$/, '<span class="sc">$1</span>')
|
h = h.replace(/(;.*)$/, '<span class="sc">$1</span>')
|
||||||
h = h.replace(/^(\s*\w+\s*:)/, '<span class="sl">$1</span>')
|
h = h.replace(/^(\s*\w+\s*:)/, '<span class="sl">$1</span>')
|
||||||
h = h.replace(/\b(MOV|ADD|SUB|MUL|DIV|MOD|AND|ORR|EOR|MVN|LSL|LSR|CMP|BEQ|BNE|BGT|BLT|BGE|BLE|LDR|STR|PUSH|POP|OUT|HLT|NOP|B)\b/gi,
|
h = h.replace(/\b(MOV|ADD|SUB|MUL|XDIV|XMOD|AND|ORR|EOR|MVN|LSL|LSR|CMP|BEQ|BNE|BGT|BLT|BGE|BLE|LDR|STR|PUSH|POP|XOUT|XHLT|NOP|B)\b/gi,
|
||||||
'<span class="sk">$1</span>')
|
'<span class="sk">$1</span>')
|
||||||
h = h.replace(/\b(R[0-7])\b/gi, '<span class="sr">$1</span>')
|
h = h.replace(/\b(R[0-7])\b/gi, '<span class="sr">$1</span>')
|
||||||
h = h.replace(/(\[[^\]]+\])/g, '<span class="sm">$1</span>')
|
h = h.replace(/(\[[^\]]+\])/g, '<span class="sm">$1</span>')
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ tutorial:
|
|||||||
code: |
|
code: |
|
||||||
MOV R0, #42 ; 把 42 放进 R0
|
MOV R0, #42 ; 把 42 放进 R0
|
||||||
MOV R1, #100 ; 把 100 放进 R1
|
MOV R1, #100 ; 把 100 放进 R1
|
||||||
- title: HLT 指令
|
- title: XHLT 指令
|
||||||
text: >
|
text: >
|
||||||
程序最后要写 `HLT`(halt = 停止),告诉机器"运行结束!"
|
程序最后要写 `XHLT`(halt = 停止),告诉机器"运行结束!"
|
||||||
code: |
|
code: |
|
||||||
MOV R0, #42
|
MOV R0, #42
|
||||||
HLT
|
XHLT
|
||||||
|
|
||||||
goal: 把数字 **42** 放进 **R0** 寄存器
|
goal: 把数字 **42** 放进 **R0** 寄存器
|
||||||
|
|
||||||
@@ -34,7 +34,7 @@ testCases:
|
|||||||
hints:
|
hints:
|
||||||
- "MOV 的格式:MOV 寄存器, #数字"
|
- "MOV 的格式:MOV 寄存器, #数字"
|
||||||
- "试试:MOV R0, #???"
|
- "试试:MOV R0, #???"
|
||||||
- "答案:MOV R0, #42 然后 HLT"
|
- "答案:MOV R0, #42 然后 XHLT"
|
||||||
|
|
||||||
starThresholds: [2, 3, 5]
|
starThresholds: [2, 3, 5]
|
||||||
|
|
||||||
@@ -43,6 +43,6 @@ starterCode: |
|
|||||||
; 提示:数字前面要加 # 号
|
; 提示:数字前面要加 # 号
|
||||||
|
|
||||||
|
|
||||||
HLT
|
XHLT
|
||||||
|
|
||||||
showMemory: false
|
showMemory: false
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ testCases:
|
|||||||
hints:
|
hints:
|
||||||
- "MOV 寄存器, 寄存器 —— 把右边复制到左边"
|
- "MOV 寄存器, 寄存器 —— 把右边复制到左边"
|
||||||
- "MOV R1, R0 可以把 R0 复制到 R1"
|
- "MOV R1, R0 可以把 R0 复制到 R1"
|
||||||
- "答案:MOV R1, R0 / MOV R2, R0 / HLT"
|
- "答案:MOV R1, R0 / MOV R2, R0 / XHLT"
|
||||||
|
|
||||||
starThresholds: [3, 4, 6]
|
starThresholds: [3, 4, 6]
|
||||||
|
|
||||||
@@ -39,6 +39,6 @@ starterCode: |
|
|||||||
; 把 R0 复制到 R1 和 R2
|
; 把 R0 复制到 R1 和 R2
|
||||||
|
|
||||||
|
|
||||||
HLT
|
XHLT
|
||||||
|
|
||||||
showMemory: false
|
showMemory: false
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ testCases:
|
|||||||
hints:
|
hints:
|
||||||
- "ADD 第一个参数放结果,后两个参数相加"
|
- "ADD 第一个参数放结果,后两个参数相加"
|
||||||
- "ADD R2, R0, R1 —— 结果存入 R2"
|
- "ADD R2, R0, R1 —— 结果存入 R2"
|
||||||
- "答案:ADD R2, R0, R1 / HLT"
|
- "答案:ADD R2, R0, R1 / XHLT"
|
||||||
|
|
||||||
starThresholds: [2, 3, 5]
|
starThresholds: [2, 3, 5]
|
||||||
|
|
||||||
@@ -47,6 +47,6 @@ starterCode: |
|
|||||||
; 计算 R0 + R1,结果存入 R2
|
; 计算 R0 + R1,结果存入 R2
|
||||||
|
|
||||||
|
|
||||||
HLT
|
XHLT
|
||||||
|
|
||||||
showMemory: false
|
showMemory: false
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
id: 4
|
id: 4
|
||||||
title: 乘法与除法
|
title: 乘法与除法
|
||||||
subtitle: 更强的算术能力
|
subtitle: 更强的算术能力
|
||||||
description: 学习 MUL 和 DIV 指令
|
description: 学习 MUL 和 XDIV 指令
|
||||||
|
|
||||||
tutorial:
|
tutorial:
|
||||||
- title: MUL —— 乘法
|
- title: MUL —— 乘法
|
||||||
@@ -11,13 +11,13 @@ tutorial:
|
|||||||
MOV R0, #6
|
MOV R0, #6
|
||||||
MOV R1, #7
|
MOV R1, #7
|
||||||
MUL R2, R0, R1 ; R2 = 6 × 7 = 42
|
MUL R2, R0, R1 ; R2 = 6 × 7 = 42
|
||||||
- title: DIV —— 除法(取整)
|
- title: XDIV —— 除法(取整)
|
||||||
text: >
|
text: >
|
||||||
DIV 做整数除法(只留整数部分):
|
XDIV 做整数除法(只留整数部分):
|
||||||
code: |
|
code: |
|
||||||
MOV R0, #100
|
MOV R0, #100
|
||||||
MOV R1, #4
|
MOV R1, #4
|
||||||
DIV R2, R0, R1 ; R2 = 100 ÷ 4 = 25
|
XDIV R2, R0, R1 ; R2 = 100 ÷ 4 = 25
|
||||||
|
|
||||||
goal: 计算 **6 × 7** 存入 R0,**100 ÷ 4** 存入 R1
|
goal: 计算 **6 × 7** 存入 R0,**100 ÷ 4** 存入 R1
|
||||||
|
|
||||||
@@ -31,9 +31,9 @@ testCases:
|
|||||||
R1: 25
|
R1: 25
|
||||||
|
|
||||||
hints:
|
hints:
|
||||||
- "先 MOV 数字到寄存器,再 MUL/DIV"
|
- "先 MOV 数字到寄存器,再 MUL/XDIV"
|
||||||
- "MUL R0, R2, R3 可以把 R2×R3 的结果放到 R0"
|
- "MUL R0, R2, R3 可以把 R2×R3 的结果放到 R0"
|
||||||
- "答案:MOV R2, #6 / MOV R3, #7 / MUL R0, R2, R3 / MOV R2, #100 / MOV R3, #4 / DIV R1, R2, R3 / HLT"
|
- "答案:MOV R2, #6 / MOV R3, #7 / MUL R0, R2, R3 / MOV R2, #100 / MOV R3, #4 / XDIV R1, R2, R3 / XHLT"
|
||||||
|
|
||||||
starThresholds: [7, 9, 12]
|
starThresholds: [7, 9, 12]
|
||||||
|
|
||||||
@@ -42,6 +42,6 @@ starterCode: |
|
|||||||
; 计算 100÷4 存入 R1
|
; 计算 100÷4 存入 R1
|
||||||
|
|
||||||
|
|
||||||
HLT
|
XHLT
|
||||||
|
|
||||||
showMemory: false
|
showMemory: false
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ testCases:
|
|||||||
hints:
|
hints:
|
||||||
- "AND 用来保留某些位,把其他位清零"
|
- "AND 用来保留某些位,把其他位清零"
|
||||||
- "低4位的掩码是 15(二进制 00001111)"
|
- "低4位的掩码是 15(二进制 00001111)"
|
||||||
- "答案:AND R0, R0, #15 / HLT"
|
- "答案:AND R0, R0, #15 / XHLT"
|
||||||
|
|
||||||
starThresholds: [2, 3, 5]
|
starThresholds: [2, 3, 5]
|
||||||
|
|
||||||
@@ -52,6 +52,6 @@ starterCode: |
|
|||||||
; 用 AND 提取低4位
|
; 用 AND 提取低4位
|
||||||
|
|
||||||
|
|
||||||
HLT
|
XHLT
|
||||||
|
|
||||||
showMemory: false
|
showMemory: false
|
||||||
|
|||||||
@@ -41,13 +41,13 @@ hints:
|
|||||||
- "就这一条指令!"
|
- "就这一条指令!"
|
||||||
|
|
||||||
starThresholds: [2, 3, 5]
|
starThresholds: [2, 3, 5]
|
||||||
blockedOps: [MUL, DIV]
|
blockedOps: [MUL, XDIV]
|
||||||
|
|
||||||
starterCode: |
|
starterCode: |
|
||||||
; R0 = 5
|
; R0 = 5
|
||||||
; 用 LSL 让 R0 变成 40(不能用 MUL)
|
; 用 LSL 让 R0 变成 40(不能用 MUL)
|
||||||
|
|
||||||
|
|
||||||
HLT
|
XHLT
|
||||||
|
|
||||||
showMemory: false
|
showMemory: false
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ testCases:
|
|||||||
hints:
|
hints:
|
||||||
- "先用 LDR 把内存值读到寄存器,算完用 STR 写回"
|
- "先用 LDR 把内存值读到寄存器,算完用 STR 写回"
|
||||||
- "MOV R3, #0 设基地址,LDR R0, [R3, #0] 读第一个值"
|
- "MOV R3, #0 设基地址,LDR R0, [R3, #0] 读第一个值"
|
||||||
- "答案:MOV R3, #0 / LDR R0, [R3, #0] / LDR R1, [R3, #1] / ADD R2, R0, R1 / STR R2, [R3, #2] / HLT"
|
- "答案:MOV R3, #0 / LDR R0, [R3, #0] / LDR R1, [R3, #1] / ADD R2, R0, R1 / STR R2, [R3, #2] / XHLT"
|
||||||
|
|
||||||
starThresholds: [6, 8, 10]
|
starThresholds: [6, 8, 10]
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ starterCode: |
|
|||||||
; 然后用 LDR/STR 读写内存
|
; 然后用 LDR/STR 读写内存
|
||||||
|
|
||||||
|
|
||||||
HLT
|
XHLT
|
||||||
|
|
||||||
showMemory: true
|
showMemory: true
|
||||||
memoryRange: [0, 15]
|
memoryRange: [0, 15]
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ tutorial:
|
|||||||
big:
|
big:
|
||||||
MOV R1, #1 ; R0 > 10
|
MOV R1, #1 ; R0 > 10
|
||||||
done:
|
done:
|
||||||
HLT
|
XHLT
|
||||||
|
|
||||||
goal: R0=**15**。如果 R0 > 10 则 R1 = **1**;否则 R1 = **0**
|
goal: R0=**15**。如果 R0 > 10 则 R1 = **1**;否则 R1 = **0**
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ testCases:
|
|||||||
hints:
|
hints:
|
||||||
- "先设 R1=#0(默认),再比较 R0 和 10"
|
- "先设 R1=#0(默认),再比较 R0 和 10"
|
||||||
- "如果 R0 > 10,跳到标签把 R1 改成 1"
|
- "如果 R0 > 10,跳到标签把 R1 改成 1"
|
||||||
- "答案:MOV R1, #0 / CMP R0, #10 / BLE done / MOV R1, #1 / done: HLT"
|
- "答案:MOV R1, #0 / CMP R0, #10 / BLE done / MOV R1, #1 / done: XHLT"
|
||||||
|
|
||||||
starThresholds: [5, 7, 9]
|
starThresholds: [5, 7, 9]
|
||||||
|
|
||||||
@@ -72,6 +72,6 @@ starterCode: |
|
|||||||
; 否则 R1 = 0
|
; 否则 R1 = 0
|
||||||
|
|
||||||
|
|
||||||
HLT
|
XHLT
|
||||||
|
|
||||||
showMemory: false
|
showMemory: false
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ tutorial:
|
|||||||
ADD R4, R4, #1 ; ②③ 计数+1
|
ADD R4, R4, #1 ; ②③ 计数+1
|
||||||
CMP R4, #5 ; ④ 到5了吗?
|
CMP R4, #5 ; ④ 到5了吗?
|
||||||
BLE loop ; 没到就跳回
|
BLE loop ; 没到就跳回
|
||||||
HLT
|
XHLT
|
||||||
- title: 注意!
|
- title: 注意!
|
||||||
text: >
|
text: >
|
||||||
忘了更新计数器 = **死循环**(别担心,超过10000步会自动停止)。
|
忘了更新计数器 = **死循环**(别担心,超过10000步会自动停止)。
|
||||||
@@ -34,7 +34,7 @@ testCases:
|
|||||||
hints:
|
hints:
|
||||||
- "R0 累加结果,R4 做计数器(1到10)"
|
- "R0 累加结果,R4 做计数器(1到10)"
|
||||||
- "循环体:ADD R0, R0, R4 / ADD R4, R4, #1 / CMP R4, #10 / BLE loop"
|
- "循环体:ADD R0, R0, R4 / ADD R4, R4, #1 / CMP R4, #10 / BLE loop"
|
||||||
- "完整:MOV R0, #0 / MOV R4, #1 / loop: ADD R0, R0, R4 / ADD R4, R4, #1 / CMP R4, #10 / BLE loop / HLT"
|
- "完整:MOV R0, #0 / MOV R4, #1 / loop: ADD R0, R0, R4 / ADD R4, R4, #1 / CMP R4, #10 / BLE loop / XHLT"
|
||||||
|
|
||||||
starThresholds: [7, 9, 12]
|
starThresholds: [7, 9, 12]
|
||||||
|
|
||||||
@@ -45,6 +45,6 @@ starterCode: |
|
|||||||
; 提示:用一个寄存器做计数器
|
; 提示:用一个寄存器做计数器
|
||||||
|
|
||||||
|
|
||||||
HLT
|
XHLT
|
||||||
|
|
||||||
showMemory: false
|
showMemory: false
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ starterCode: |
|
|||||||
; 用 MOV + LDR 读取内存
|
; 用 MOV + LDR 读取内存
|
||||||
|
|
||||||
|
|
||||||
HLT
|
XHLT
|
||||||
|
|
||||||
showMemory: true
|
showMemory: true
|
||||||
memoryRange: [0, 15]
|
memoryRange: [0, 15]
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
const REGISTERS = ['R0','R1','R2','R3','R4','R5','R6','R7']
|
const REGISTERS = ['R0','R1','R2','R3','R4','R5','R6','R7']
|
||||||
const OPCODES = [
|
const OPCODES = [
|
||||||
'MOV','ADD','SUB','MUL','DIV','MOD',
|
'MOV','ADD','SUB','MUL','XDIV','XMOD',
|
||||||
'AND','ORR','EOR','MVN','LSL','LSR',
|
'AND','ORR','EOR','MVN','LSL','LSR',
|
||||||
'CMP','B','BEQ','BNE','BGT','BLT','BGE','BLE',
|
'CMP','B','BEQ','BNE','BGT','BLT','BGE','BLE',
|
||||||
'LDR','STR','PUSH','POP','OUT','HLT','NOP',
|
'LDR','STR','PUSH','POP','XOUT','XHLT','NOP',
|
||||||
]
|
]
|
||||||
const BRANCH_OPS = ['B','BEQ','BNE','BGT','BLT','BGE','BLE']
|
const BRANCH_OPS = ['B','BEQ','BNE','BGT','BLT','BGE','BLE']
|
||||||
const MAX_STEPS = 10000
|
const MAX_STEPS = 10000
|
||||||
@@ -198,7 +198,7 @@ export function createVM() {
|
|||||||
try {
|
try {
|
||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case 'NOP': break
|
case 'NOP': break
|
||||||
case 'HLT': state.halted = true; break
|
case 'XHLT': state.halted = true; break
|
||||||
|
|
||||||
case 'MOV':
|
case 'MOV':
|
||||||
setReg(ops[0], getVal(ops[1]), changes)
|
setReg(ops[0], getVal(ops[1]), changes)
|
||||||
@@ -207,11 +207,11 @@ export function createVM() {
|
|||||||
case 'ADD': { const r = arith3(ops, (a,b) => a+b); state.flags.carry = r > 0xFFFF; setReg(ops[0], r, changes); updateFlags(r); break }
|
case 'ADD': { const r = arith3(ops, (a,b) => a+b); state.flags.carry = r > 0xFFFF; setReg(ops[0], r, changes); updateFlags(r); break }
|
||||||
case 'SUB': { const r = arith3(ops, (a,b) => a-b); state.flags.carry = r < 0; setReg(ops[0], r, changes); updateFlags(r); break }
|
case 'SUB': { const r = arith3(ops, (a,b) => a-b); state.flags.carry = r < 0; setReg(ops[0], r, changes); updateFlags(r); break }
|
||||||
case 'MUL': { const r = arith3(ops, (a,b) => a*b); state.flags.carry = r > 0xFFFF; setReg(ops[0], r, changes); updateFlags(r); break }
|
case 'MUL': { const r = arith3(ops, (a,b) => a*b); state.flags.carry = r > 0xFFFF; setReg(ops[0], r, changes); updateFlags(r); break }
|
||||||
case 'DIV': {
|
case 'XDIV': {
|
||||||
const r = arith3(ops, (a,b) => { if(b===0) throw new Error('除以零!'); return Math.floor(a/b) })
|
const r = arith3(ops, (a,b) => { if(b===0) throw new Error('除以零!'); return Math.floor(a/b) })
|
||||||
setReg(ops[0], r, changes); updateFlags(r); break
|
setReg(ops[0], r, changes); updateFlags(r); break
|
||||||
}
|
}
|
||||||
case 'MOD': {
|
case 'XMOD': {
|
||||||
const r = arith3(ops, (a,b) => { if(b===0) throw new Error('除以零!'); return a%b })
|
const r = arith3(ops, (a,b) => { if(b===0) throw new Error('除以零!'); return a%b })
|
||||||
setReg(ops[0], r, changes); updateFlags(r); break
|
setReg(ops[0], r, changes); updateFlags(r); break
|
||||||
}
|
}
|
||||||
@@ -274,7 +274,7 @@ export function createVM() {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'OUT': {
|
case 'XOUT': {
|
||||||
const v = getVal(ops[0])
|
const v = getVal(ops[0])
|
||||||
state.output.push(v)
|
state.output.push(v)
|
||||||
changes.push({ type: 'output', val: v })
|
changes.push({ type: 'output', val: v })
|
||||||
|
|||||||
Reference in New Issue
Block a user