9

我正在尝试使用 6502 处理器在汇编中编写一个 while 循环,但我无法弄清楚如何编写十六进制代码。我已经看到使用速记编写的示例,其中有一个循环应该开始和结束的标签,但我没有看到任何实际的十六进制代码。

我认为有用的两个代码是:

  1. 将内存中的一个字节与 X reg 进行比较(速记:CPX,十六进制:EC)。这会将 Z 标志设置为零,如果相等并且
  2. 如果 Z 标志 = 0,则转移 X 字节(简写:BNE,十六进制:D0)
4

4 回答 4

6

这是您开始的地方。该页面具有一个可以在 PC 上运行的交叉汇编程序。这对你来说可能是一个很好的开发平台。

在做任何事情之前,您必须了解 6502 的工作原理。然后您必须了解软件开发过程,包括:

-- 准备一个所谓的“源文件”,你称之为“速记”的符号指令
-- 使用汇编程序,将该源文件翻译成 6502 可以理解的机器指令
-- 将翻译加载到 6502
-- 告诉6502 执行翻译后的机器指令

您的示例程序尝试将LEN内存字节从复制SRCDST

你像这样格式化它:

      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 执行机器代码所包含的操作。

于 2011-05-16T17:27:01.300 回答
3

这是一个显示程序集(您称之为“速记”)和机器代码之间对应关系的示例。首先,这里是算法的汇编代码,抽象了一些参数:

* = 4000          ; This is the address where our program will be stored

      LDX #len
loop  LDA src,X 
      STA dest,X 
      DEX       
      BNE loop

当然,您不能将其直接转换为机器代码。您还需要填写 和的值lensrcdest

src = $1234
dest = $5678
len = 10

关于loop名称要理解的是,就像src被赋值一样$1234loop将被赋值给它后面的指令的地址。所以在这种情况下,因为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

因此,如果您要手动执行此操作,您只需将其他所有内容转换为机器代码,然后当您进行跳转时,您会计算下一条指令的起始地址和跳转目标地址之间的差异。向后跳跃应该是负数,向前跳跃应该是正数。

于 2014-06-12T03:08:58.427 回答
2

分支指令采用单字节带符号的相对地址操作数,将其添加到下一条指令的地址以产生分支目标。由于分支指令总是占用 2 个字节,因此目标地址是分支指令的地址加上(符号扩展的)操作数减 2。

示例:
$D0 $00:no-op:无论条件如何,分支都会转到下一条指令
$D0 $FE:分支指向自身,创建一个无限循环 if Z=0

于 2013-08-18T18:11:46.433 回答
1

声明的while真正含义是:

  1. 测试条件
  2. 如果条件为假,则转到 5
  3. 做一点事
  4. 返回 1(简单的 JMP 或分支)
  5. 程序的其余部分

使用 6502,除非您可以做出很多假设,否则这一切都不会非常简单。如果您要测试的条件始终是寄存器,那么比较指令(cmp、cpx、cpy)和分支指令显然是您需要的 1。

如果它将是存储在内存中的单个字节,那么您需要加载该字节,然后进行比较。

如果是存储在两个字节中的 16 位值,则需要加载并测试该字节的每个值。

处理浮动?如果您已经编写或有一个浮点包(例如 Commodore 64 ROM BASIC 浮点例程),您将需要使用它们。

你可以看到为什么高级语言有数据类型。

所以真的,这取决于你正在处理的数据类型,但是while6502 中的任何实现都应该遵循上述内容。

如果您知道要比较的数据将始终在 X 中并且您的目的地将始终在 +127/-128 字节之外(Bxx 指令的范围限制),那么您在问题中确定的具体情况是可以的。

于 2013-08-18T14:38:49.233 回答