nandgame中的asm编程 Escape Labyrinth(逃离迷宫)

发布于:2024-04-09 ⋅ 阅读:(149) ⋅ 点赞:(0)

先翻译题目:

逃离迷宫

计算机被困在火星上的迷宫中。编写一个程序,让它逃离迷宫。

计算机配备了连接的轮子和前方障碍物探测器。与轮子和探测器的输入/输出是内存映射在地址7FFF上:

对外设的输出信号:
位	设置为1代表:
2	向前移动(1步)
3	向左转(90度)
4	向右转(90度)
移动/转向在位从0变为1时开始,但需要一段时间才能完成。

从外设输入:
位	当为18	前方探测到障碍物
9	设备正在转向
10	设备正在向前移动

帮助信息的翻译:

汇编语言快速参考
语法为 destination = calculation ; jump-condition 目标和跳转条件是可选的。
D 和 A 是两个寄存器。*A 表示 RAM 中地址所包含的值。

示例:
D=D+1   计算 D+1 并将结果存储在 D 中。
D-1;JGE 计算 D-1。如果结果大于 0,则跳转。(结果不被存储。)
A = 1234  将数字 1234 存储在 A 寄存器中。
# Hello   注释 - 编译器忽略

计算
D + A
D-A 或 A-D
D&A(按位与)
D|A(按位或)
A+1 或 D+1
A-1 或 D-1
-A 或 -D
~A 或 ~D(按位反转)
10-1
在所有情况下,可以使用 *A 代替 A。

目标
D、A 和 *A 的任意组合都可以用作目标。多个目标用逗号分隔,例如 D,A = 1。

跳转条件
    当计算结果为时跳转:
JEQ 等于       0
JNE 不等于     0
JGT 大于       0
JGE 大于或等于  0
JLT 小于       0
JLE 小于或等于  0
JMP 无条件跳转(不管计算结果如何)。

数字指令
可以直接将数字赋给 A。例如:A = 47。
十六进制数以 0x 为前缀,例如:A = 0x7FFF
二进制数以 0b 为前缀,例如:A = 0b010111。
可以使用下划线来分隔数字组,例如:A = 0b_0101_1100。

注释
以 # 开头的行会被编译器忽略。可以用于注释和文档。

标签
关键字 LABEL 后跟一个名称,使名称代表下一条指令的地址。可以在跳转之前将该地址分配给 A,例如:A = LOOP

定义
关键字 DEFINE 后跟名称和数字,当它出现在其他指令中时,会将名称替换为数字。例如,以下两行:
DEFINE foo 0X7FFF
A = foo
等同于:A = 0x7FFF

多目标
可以将结果分配给多个寄存器。
例如 D,A = D - *A 计算的结果将同时写入 A 和 D。可以指定 A、D 和 *A 的任意组合作为目标。

题目隐含的意思:
迷宫不会中途变更。
输出控制信号后,先得读取寄存器的值,判断是否已经执行完毕。

源码参考:
https://zhuanlan.zhihu.com/p/613188641
解题思路:一直直走,撞墙就左拐。
测试运行,检查结果是正确的。

界面说明:
Show Assembler Help 显示帮助信息
Reset state 可以重置程序
Check solution 检查结果,如果通过就是过关
computer区域,Tick按钮单步执行,Run直接跑,Reset重置机器状态。
最右边是robot的当前状态的文字显示,很像二十多年前的mud游戏。
在这里插入图片描述
跑完后的效果:
在这里插入图片描述

先简单注释下源码:

LOOP_FORWARD :
A = 0x7fff
D = *A
A = 0x0100  //判断bit8是否为1,前方是否有障碍。实际也判断了bit9、bit10是否为0
D = D - A
A = LOOP_TURN_LEFT
D; JEQ      //撞墙了,调左转函数
A = LOOP_RE_READ
D; JGT      //D大于0,说明bit9、bit10不为0,需要等待前面的动作执行完毕
A = 0x0004  //bit2设置为1,控制直走
D = A
A = 0x7fff
*A = D
A = LOOP_FORWARD
JMP

LOOP_TURN_LEFT : //左转函数
A = 0x0008  //bit3设置为1,控制左转
D = A
A = 0x7fff
*A = D
A = LOOP_FORWARD
JMP

LOOP_RE_READ :  //重新探测robot状态
A = 0x7fff
D = *A
A = LOOP_FORWARD  //寄存器为0时,控制直走
D; JEQ      
A = 0x7fff
D = *A
A = 0x0100  //判断前方是否有障碍
D = D - A
A = LOOP_TURN_LEFT
D; JEQ      //调左转
A = LOOP_RE_READ
JMP         //接着等前面的执行完毕

有三个LOOP,可以理解为三个函数
A = LOOP_FORWARD
JMP
就是无条件调用LOOP_FORWARD函数

A = LOOP_TURN_LEFT
D; JEQ
是指D寄存器中的值==0时,调用LOOP_TURN_LEFT函数

A = LOOP_RE_READ
D; JGT
同理,D寄存器中的值>0时,调用LOOP_RE_READ函数

如果语法错误
会被标红,无法执行,例如:
在这里插入图片描述
鼠标放在标红的错误代码上时,会有错误提示信息弹出窗。


网站公告

今日签到

点亮在社区的每一天
去签到