Z80组件(1MHz)CP / M:如何使用按钮获得正确的物理输入

时间:2018-11-03 21:02:50

标签: assembly z80 cpm

我是一名学习计算机科学的新生。在计算机工程领域,我们正在研究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,但在这种情况下我不知道如何做-遗憾的是,该手册仅包含基本操作,所以我很茫然。

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

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

感谢您的时间,祝您愉快!

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

[。edit]更新了* .txt文件中的代码-现在更简单,更有效

[EDIT]使用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检查特定位置的位。不过,我的说明手册中没有提到任何此类指令,作业本身也没有提及。

我很清楚这可能是一个微不足道的问题,也许我只是陷入了通过过度思考而建立自己的心理循环中,但此刻我不知道该如何去做(即使我能看到地平线上的城堡-感谢卡夫卡!)。

非常感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

首先,如果使用MOV,则可能使用的是8080语法而不是Z80语法。出于历史上的法律原因,Z80不仅扩展了8080的汇编语言,而且还重命名了所有现有的助记符(例如,将MOV更改为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.

我不知道8080或Z80风格的语法中的TEST

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

答案 1 :(得分:0)

经过几天的思考和思考,在大家的大力支持下,我终于找到了解决问题的方法。最后,我最担心的是我不知道如何正确检查输入。

正如我所假设的,问题出在我被误解的困扰,所幸我的实验室合作伙伴纠正了这个误解。因此,毕竟,我们能够使我们的程序能够正常工作-在最后一分钟而不是100%正常运行,但是它可以正常工作并满足要求。

那我的误解是什么?有趣的是,我知道我们必须去的地方,而且这个想法是正确的。问题是我跳过了逻辑运算的主要部分-我已经在脑海中进行了计算,然后将实际的工作解决方案与过时的AND结合使用,从而破坏了功能。

总而言之,XORAND的正确组合如下:

programloop:
MOV A,40h       ;state of button 2, inverted (XOR FFh)
MOV B,A         ;save state to register B
IN A,03h        ;input at port-address 03h
AND B           ;find out if button is pressed
JPNZ blink      ;if yes, jump to blink

MOV A,20h       ;state of button 3, inverted (XOR FFh)
MOV B,A         ;save state to register B
IN A,03h        ;input at port-address 03h
AND B           ;find out if button is pressed
JPNZ goright    ;if yes, jump to goright

MOV A,10h       ;state of button 4, inverted (XOR FFh)
MOV B,A         ;save state to register B
IN A,03h        ;input at port-address 03h
AND B           ;find out if button is pressed
JPNZ goleft     ;if yes, jump to goleft
JP programloop  ;go back to beginning (input has to be checked constantly)

这涉及到三个按钮,这些按钮改变了LED的行为。

关于频率,由于时间紧迫,我们不得不将复杂性降低到仅两个状态(我们错误地理解了分配,并错误地从奖金问题开始,这花了我们大约50%的开发时间-是的。学到的:始终从顶部开始阅读,仔细阅读。)

但是由于频率改变有效,所以结果很好。

MOV A,03h       ;state of button five being pressed (inverted)
MOV B,A         ;saved state into register B for later use
IN A,03h        ;physical input over button
AND B           ;find out if button is pressed
JPNZ freq025Hz  ;if yes, jump to freq025Hz
JPZ freq4Hz     ;if no, jump to freq4Hz

就这样!

再次感谢大家的帮助。

如果还有任何疑问,请随时提问!