【问题标题】:Writing a while loop in assembly在汇编中编写一个while循环
【发布时间】:2011-08-26 15:03:13
【问题描述】:

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

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

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

【问题讨论】:

  • 为什么要使用十六进制代码而不是汇编程序?
  • @jnhyf“十六进制代码”?您使用的是哪个 IDE、汇编器或编译器?您已经有 6502 组装的哪些经验?
  • 我希望您没有告诉我们您正在编写一个不使用汇编程序的 6502 程序。你用什么开发系统?苹果 ][ ?还是什么?
  • 尝试编写一个生成十六进制代码的编译器,以便它可以在模拟的 6502 微处理器上运行。
  • 他可能正在使用微处理器训练器(例如innovision-group.net/catalog/images/…)。这些是您直接用机器代码编程的简单计算机。您仍然可以使用汇编程序来生成机器码,但您仍然需要手动将机器码输入到系统中。

标签: loops assembly while-loop hex 6502


【解决方案1】:

Here's a place for you to start。该页面具有一个可以在 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);在定义了SRCDSTLEN 之后,将整个内容保存在一个名为cploop.txt 的文件中。

然后你告诉汇编器翻译它。汇编器带有一个二进制 6502 机器代码文件,可以表示为您正在谈论的十六进制字节。

您将该机器代码文件提供给模拟的 6502。然后您以某种方式告诉 6502 执行机器代码所包含的操作。

【讨论】:

  • 谢谢,这有帮助,但我仍然不清楚该网站上的这个例子如何:“ LDX #0 ;从第一个字节开始 _LOOP LDA SRC,X ;移动它 STA DST,X INX ;然后碰撞索引... CPX #LEN ;... 直到我们达到极限 BNE _LOOP " 可以用十六进制表示。 _loop 标签在速记中很重要,但我看不出如何在实际机器代码中使用类似的东西。抱歉,我不知道如何格式化该代码。
  • @jnhyf 您真的需要将您的问题拆分为“我怎样才能用 6502 机器代码编写这段代码”和“我怎样才能将该代码转换为十六进制表示法” .就目前而言,很难为您提供帮助。
  • @jnhyf -- 有两个步骤: (1) 用汇编语言编写程序,也就是所谓的“速记”(顺便说一句,我从未听说过这个术语); (2) 将该汇编语言文件提供给汇编器,然后它会吐出你想要的十六进制代码。
  • 顺便说一下,递减循环更有效——它们不需要比较指令,而且除了保存这两个字节之外,每次迭代也快 2-6 个时钟(取决于比较和寻址模式):LDX #LEN ;从最后一个字节开始 _LOOP LDA SRC,X ;从 SRC 加载一个字节到 A 寄存器 STA DST,X ;将该字节存储到 DST DEX 中;碰撞索引寄存器以指向下一个 SRC 和 DST 位置 BNE _LOOP ;如果不为零,则移动下一个
  • @jnhyf - 您似乎坚持的一件事是汇编代码中存在“_LOOP”标签。这只是一个汇编程序指令,表示指令开始位置的地址。它不会被组装成机器代码中的任何内容,在它被定义的时候输出。当它用作操作数的一部分(即汇编指令的参数)时,它会替换为定义时所在指令的地址。在 6502 上,它首先写出最低有效字节 - 地址 $0300 在机器代码中写出“00 03”。
【解决方案2】:

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

* = 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 的机器码,仅用于计算 BNE 指令本身的相对地址:F7 是 -9,两者之间的差异$400B$4002 是 -9!

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

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

    • 支持解码和回答措辞不当的问题。 ; - )
    【解决方案4】:

    while 声明的真正含义是:

    1. 测试条件
    2. 如果条件不成立,转5
    3. 做点什么
    4. 回到 1(简单的 JMP 或分支)
    5. 程序的其余部分

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

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

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

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

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

    实际上,这取决于您要处理的数据类型,但 6502 中 while 的任何实现都应遵循上述规定。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-02
      • 2013-08-28
      • 1970-01-01
      相关资源
      最近更新 更多