我正在尝试使用 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
:src
dest
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!BNE
F7
$400B
$4002
因此,如果您要手动执行此操作,您只需将其他所有内容转换为机器代码,然后当您进行跳转时,您会计算下一条指令的起始地址和跳转目标地址之间的差异。向后跳跃应该是负数,向前跳跃应该是正数。
分支指令采用单字节带符号的相对地址操作数,将其添加到下一条指令的地址以产生分支目标。由于分支指令总是占用 2 个字节,因此目标地址是分支指令的地址加上(符号扩展的)操作数减 2。
示例:
$D0 $00
:no-op:无论条件如何,分支都会转到下一条指令
$D0 $FE
:分支指向自身,创建一个无限循环 if Z=0
。
声明的while
真正含义是:
使用 6502,除非您可以做出很多假设,否则这一切都不会非常简单。如果您要测试的条件始终是寄存器,那么比较指令(cmp、cpx、cpy)和分支指令显然是您需要的 1。
如果它将是存储在内存中的单个字节,那么您需要加载该字节,然后进行比较。
如果是存储在两个字节中的 16 位值,则需要加载并测试该字节的每个值。
处理浮动?如果您已经编写或有一个浮点包(例如 Commodore 64 ROM BASIC 浮点例程),您将需要使用它们。
你可以看到为什么高级语言有数据类型。
所以真的,这取决于你正在处理的数据类型,但是while
6502 中的任何实现都应该遵循上述内容。
如果您知道要比较的数据将始终在 X 中并且您的目的地将始终在 +127/-128 字节之外(Bxx 指令的范围限制),那么您在问题中确定的具体情况是可以的。