首页 > 解决方案 > Z80 Assembly (1MHz) CP/M:如何使用按钮获得正确的物理输入

问题描述

我是一名学习计算机科学的大一新生。在计算机工程中,我们正在研究 Zilog Z80 8 位微处理器 (1MHz) 和一组需要使用面包板和电缆手动连接的组件。

连接部分并不让我担心,但我确实有关于我需要编写以使我的程序正常工作的装配程序的问题(LED 运行灯,手动输入行为和频率)。

我已经阅读了手册并知道可以使用的一组说明(仅是必需品)。首先,我并不是要尽可能地获得最干净、最好看的代码。不过不用担心,我稍后会对其进行美化,因为我喜欢干净高效的代码。

目前,该程序似乎在模拟器中运行良好,因此语法似乎没问题。不过,我不确定如何解决某些逻辑问题。

该练习具有以下规格:

  1. 起始地址 RAM:E000h
  2. 输入端口1:03h
  3. 输出端口1:05h
  4. 端口的 I/O 映射
  5. 电路自动打开 (1),因此 LED 为低电平有效 (0)
  6. 输入 2、3、4 改变 LED 移动行为
  7. 输入 5,6 改变 LED 闪烁频率

我已经使用 设置了起始地址ORG E000h并使用MOV SP,FFFFh. 对于输入(三种不同类型的闪烁/运行,以及两种不同的频率,总共等于五个按钮),我创建了不同的标签。

我目前的问题是我不太确定如何正确输入物理输入 - IIRC,我需要通过使用 XOR 来指定一个位模式,所有内容都是 1 但所需的输入,以便我可以使用信息在我的程序中。

但即使我确实知道它应该如何工作(至少我认为我知道),我还是不能完全理解软件实现。此外,我遇到了条件问题:按下一个开关将闪烁频率更改为 1/4 Hz,而按下另一个开关将其更改为 4Hz。在高级语言中,我在这里只使用 IF/ELSE,但在这种情况下我不知道该怎么做 - 遗憾的是,手册只包括基本操作,所以我不知所措。

因此,我想我会试试运气并向社区寻求帮助。

对于那些有兴趣的人,我会发布我的代码。正如我已经提到的,这是非常基本的,但我暂时只需要它来完成工作。由于我不喜欢大量格式笨拙的代码,因此我在此处发布了文件。该文件是通过 GoogleDrive 托管的 *.txt。

感谢您的宝贵时间,祝您有美好的一天!

[编辑] 根据用户 Ruud Helderman 的输入,在帖子中添加了特定代码

[编辑] 更新 *.txt 文件中的代码 - 现在更简单、更高效

[编辑] 使用 HTML 格式在帖子中突出显示指令

具体代码片段:

blink:       ;function: all LED blinking, activated via input[2]
MOV A,FFh
OUT 05h,A     ;all LED out
CALL pause1   ;frequency 1/4Hz, activated via input[5]
MOV A,00h
OUT 05h,A     ;all LED on
CALL pause1
JP blink      ;jump back to begin of function

上述功能使用输入开关板上的不同特定物理开关更改 LED 行为(在这种情况下:闪烁)以及频率,总共有 8 个开关(1 到 8,停用状态 = 1;使用开关 2 到 6)。我知道获取输入应该是小菜一碟——它应该只是使用位模式为 0 和恰好一个 1 的 XOR 的问题。

在尝试为我的问题找到解决方案时,我在网上遇到了不同的方法,例如TEST用于检查特定位置的位。尽管如此,我的说明手册没有提到任何这样的指令,作业本身也没有提到它。

我很清楚这可能是一个微不足道的问题,也许我只是陷入了我通过过度思考创造自己的心理循环,但目前我不知道如何去做我需要的(即使我可以看到地平线上的城堡——感谢卡夫卡!)。

任何帮助是极大的赞赏。

标签: assemblyz80cpm

解决方案


首先要做的事情:如果您正在使用,MOV那么您可能使用的是 8080 语法而不是 Z80 语法。由于历史上的法律原因,Z80 不仅扩展了 8080 的汇编语言,它还重命名了所有现有的助记符(例如MOVto LD)。如果您正在搜索 Z80 代码并找到您不认识的说明,那很可能是其中的一部分。

实现 if/else 类型条件的常用方法是:

  1. 执行任何以适当方式设置状态标志的操作;和
  2. 根据状态标志,使用条件跳转之一来跳过某些代码。

在您的情况下,您想根据是否设置某个位来做某事或不做某事,因此一种方法是ANI(z80: AND)。这计算累加器和操作数的逻辑与,将其存储在累加器中,但除其他外,它还设置零标志。因此,您可以使用JNZ(/ JP NZ) 和JZ(/ JP Z) 根据是否设置了某个位来做某事。例如

; upon entry, A has an unknown value, loaded from somewhere.

ANI 08h    ; Set a = a & 8; so either bit 2 was originally set and a now
           ; has the value 8, or bit 2 wasn't set and a now has the value 0.

           ; Also: the zero flag is now set if a is zero, reset otherwise.

           ; So you've loaded NOT (a.bit2) into the zero flag.

           ; You've also lost the rest of the accumulator, but such is life.
           ; Keep a copy somewhere, or grab it again via IN as required.

JZ bitnotset

; code here will be performed only if bit 2 was originally unset.

bitnotset:

; this code will happen regardless of whether bit 2 was set.

我不知道TEST8080 或 Z80 样式的语法。

您可能还会看到一种破坏性较小且效率更高的解决方案,通过将它们移入进位位来按顺序测试一个字节中的多个位。这是另一种选择,但不一定值得担心,除非你的课程笔记强烈暗示这是你应该关注的方向。


推荐阅读