在汇编中编写 while 循环

发布于 2024-11-07 17:37:22 字数 246 浏览 5 评论 0原文

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

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

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

I'm trying to write a while loop in assembly with a 6502 processor and I cannot figure out how to write the hexadecimal code. I've seen examples written using the shorthand where there is a label for where the loop should begin and end but I do not see anything for the actual hex code.

The two codes I see being useful are:

  1. Comparing a byte in memory to the X reg (shorthand: CPX, hex: EC). This sets the Z flag to zero if equal and
  2. Branch X bytes if Z flag = 0 (shorthand: BNE, hex: D0)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

茶花眉 2024-11-14 17:37:22

这里是您开始的地方。该页面具有一个可以在您的 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 执行机器代码所包含的操作。

Here's a place for you to start. The page features a cross-assembler that you can run on your PC. That could be a good dev platform for you.

Before doing anything, you have to understand the theory of operation of the 6502. Then you have to understand the software-development process that includes:

-- preparing a "source file," so called,
of symbolic instructions that you
call "shorthand"
-- using an
assembler, translating that source
file into machine instructions that
the 6502 understands
-- loading the
translation into the 6502
-- telling
the 6502 to execute the translated
machine instructions

Your example program tries to copy LEN memory bytes from SRC to DST.

You format it like this:

      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

After you have added more statement lines (like END, for example); and after you have defined SRC, DST, and LEN, you save the whole thing in a file called, let's say, cploop.txt.

Then you tell the assembler to translate it. The assembler comes out with a file of binary 6502 machine code that cam be represented as the hex bytes you're talking about.

You feed that file of machine code to the simulated 6502. Then you somehow tell the 6502 to execute the operations that the machine code embodies.

甜中书 2024-11-14 17:37:22

下面的示例显示了程序集(您所说的“速记”)和机器代码之间的对应关系。首先,这是该算法的汇编代码,其中抽象出了一些参数:

* = 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

关于循环需要了解的事情名字是,就像src被赋予值$1234一样,loop将被赋予其后面指令的地址。因此,在本例中,由于 LDX #len 占用 2 个字节(我很快就会向您展示),因此 loop 设置为 $4000 + 2 = $4002< /代码>。这是由汇编器自动完成的,但当然您也可以在纸上完成所有这些工作。

那么上述汇编程序的6502机器码是什么呢?

A2 0A
BD 34 12
9D 78 56
CA
D0 F7

我怎么知道这个?好吧,我刚刚将上述程序粘贴到在线 6502 汇编器中,网址为 http://www.masswerk .at/6502/assembler.html。它甚至向您展示了汇编代码和机器代码之间的详细映射:

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!

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

Here's an example showing the correspondence between assembly (what you call "shorthand") and machine code. First, here's the assembly code for the algorithm, with some parameters abstracted away:

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

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

Of course, you can't turn that directly into machine code. You also need to fill in the values of len, src and dest:

src = $1234
dest = $5678
len = 10

The thing to understand about the loop name is that just like src is assigned the value $1234, loop will be assigned the address of the instruction after it. So in this case, since LDX #len takes up 2 bytes (as I'll show you shortly), loop is set to $4000 + 2 = $4002. This is done automatically by the assembler, but of course you could do all this on paper as well.

So what is the 6502 machine code for the above assembly program?

A2 0A
BD 34 12
9D 78 56
CA
D0 F7

How do I know this? Well, I've just pasted the above program into the online 6502 assembler at http://www.masswerk.at/6502/assembler.html. It even shows you the detailed mapping between assembly and machine code:

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

Note how the actual value of LOOP is not even used to compute the machine code for BNE LOOP, only its relative address compared to the BNE instruction itself: F7 is -9, and the difference between $400B and $4002 is -9!

So if you were to do this by hand, you'd just translate everything else into machine code, then when you get to a jump, you compute the difference between the next instruction's starting address and the jump destination's address. It should be negative for backwards jumps and positive for forward jumps.

我不在是我 2024-11-14 17:37:22

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

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

The branch instructions take a single-byte signed relative address operand, which is added to the address of the next instruction to yield the branch target. Since the branch instruction always occupies 2 bytes, the target address is the address of the branch instruction plus the (sign-extended) operand minus 2.

Examples:
$D0 $00: no-op: the branch goes to the next instruction regardless of the condition
$D0 $FE: branch points back to itself, creating an infinite loop if Z=0.

梦魇绽荼蘼 2024-11-14 17:37:22

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 指令的范围限制),则您在问题中确定的具体情况是可以的。

A while statement really means:

  1. test a condition
  2. if the condition is false, go to 5
  3. do something
  4. go back to 1 (a simple JMP or branch)
  5. rest of program

With 6502, none of this is going to be extremely simple unless you can make a lot of assumptions. If the condition you are testing is always going to be a register, the compare instructions (cmp, cpx, cpy) and branch instructions are obviously what you need for 1.

If it's going to be a single byte stored in memory, then you need to load that byte, and then compare it.

If it's a 16-bit value stored in two bytes, you need to load and test each value of the byte.

Dealing with floats? If you have written or have available to you a floating point package (such as the Commodore 64 ROM BASIC floating-point routines) you'll need to use them.

You can see why high-level languages have data types.

So really, it depends on the type of data you are dealing with, but any implementation of while in 6502 should pretty much follow the above.

The specific case you identify in your question is OK if you know the data you will compare will always be in X and that your destination will always be +127/-128 bytes away (range limit of Bxx instructions).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文