我正在尝试使用 6502 处理器在汇编中编写一个 while 循环,但我无法弄清楚如何编写十六进制代码。我已经看到使用速记编写的示例,其中有一个循环应该开始和结束的标签,但我没有看到任何实际的十六进制代码。
我认为有用的两个代码是:
- 将内存中的一个字节与 X reg 进行比较(速记:CPX,十六进制:EC)。这会将 Z 标志设置为零,如果相等并且
- 如果 Z 标志 = 0,则转移 X 字节(简写:BNE,十六进制:D0)
我正在尝试使用 6502 处理器在汇编中编写一个 while 循环,但我无法弄清楚如何编写十六进制代码。我已经看到使用速记编写的示例,其中有一个循环应该开始和结束的标签,但我没有看到任何实际的十六进制代码。
我认为有用的两个代码是:
这是您开始的地方。该页面具有一个可以在 PC 上运行的交叉汇编程序。这对你来说可能是一个很好的开发平台。
在做任何事情之前,您必须了解 6502 的工作原理。然后您必须了解软件开发过程,包括:
-- 准备一个所谓的“源文件”,你称之为“速记”的符号指令
-- 使用汇编程序,将该源文件翻译成 6502 可以理解的机器指令
-- 将翻译加载到 6502
-- 告诉6502 执行翻译后的机器指令
您的示例程序尝试将LEN内存字节从复制SRC到DST。
你像这样格式化它:
LDX #0 ; Start with the first byte
_LOOP LDA SRC,X ; load a byte from SRC into the A register
STA DST,X ; store that byte into DST
INX ; bump the index register to point to the next SRC and DST locations
CPX #LEN ; have we moved LEN characters?
BNE _LOOP ; if not, go move the next one
添加更多语句行之后(例如END,例如);在定义SRC,DST和之后LEN,将整个内容保存在一个名为的文件中,比如说cploop.txt.
然后你告诉汇编器翻译它。汇编程序带有一个二进制 6502 机器代码文件,该文件可以表示为您正在谈论的十六进制字节。
您将该机器代码文件提供给模拟的 6502。然后您以某种方式告诉 6502 执行机器代码所包含的操作。
这是一个显示程序集(您称之为“速记”)和机器代码之间对应关系的示例。首先,这里是算法的汇编代码,抽象了一些参数:
* = 4000 ; This is the address where our program will be stored
LDX #len
loop LDA src,X
STA dest,X
DEX
BNE loop
当然,您不能将其直接转换为机器代码。您还需要填写 和的值len:srcdest
src = $1234
dest = $5678
len = 10
关于loop名称要理解的是,就像src被赋值一样$1234,loop将被赋值给它后面的指令的地址。所以在这种情况下,因为LDX #len占用 2 个字节(我将很快向您展示),loop设置为$4000 + 2 = $4002. 这是由汇编程序自动完成的,当然你也可以在纸上完成所有这些。
那么上述汇编程序的6502机器码是什么?
A2 0A
BD 34 12
9D 78 56
CA
D0 F7
我怎么知道这个?好吧,我刚刚将上述程序粘贴到http://www.masswerk.at/6502/assembler.html的在线 6502 汇编器中。它甚至向您展示了汇编代码和机器代码之间的详细映射:
4000 LDX #LEN A2 0A
4002 LOOP LDA SRC,X BD 34 12
4005 STA DEST,X 9D 78 56
4008 DEX CA
4009 BNE LOOP D0 F7
400B
注意 的实际值LOOP甚至不用于计算 的机器码,只使用它与指令本身BNE LOOP相比的相对地址:是-9,和之间的差 是-9!BNEF7$400B$4002
因此,如果您要手动执行此操作,您只需将其他所有内容转换为机器代码,然后当您进行跳转时,您会计算下一条指令的起始地址和跳转目标地址之间的差异。向后跳跃应该是负数,向前跳跃应该是正数。
分支指令采用单字节带符号的相对地址操作数,将其添加到下一条指令的地址以产生分支目标。由于分支指令总是占用 2 个字节,因此目标地址是分支指令的地址加上(符号扩展的)操作数减 2。
示例:
$D0 $00:no-op:无论条件如何,分支都会转到下一条指令
$D0 $FE:分支指向自身,创建一个无限循环 if Z=0。
声明的while真正含义是:
使用 6502,除非您可以做出很多假设,否则这一切都不会非常简单。如果您要测试的条件始终是寄存器,那么比较指令(cmp、cpx、cpy)和分支指令显然是您需要的 1。
如果它将是存储在内存中的单个字节,那么您需要加载该字节,然后进行比较。
如果是存储在两个字节中的 16 位值,则需要加载并测试该字节的每个值。
处理浮动?如果您已经编写或有一个浮点包(例如 Commodore 64 ROM BASIC 浮点例程),您将需要使用它们。
你可以看到为什么高级语言有数据类型。
所以真的,这取决于你正在处理的数据类型,但是while6502 中的任何实现都应该遵循上述内容。
如果您知道要比较的数据将始终在 X 中并且您的目的地将始终在 +127/-128 字节之外(Bxx 指令的范围限制),那么您在问题中确定的具体情况是可以的。