在汇编中编写 while 循环
我正在尝试使用 6502 处理器在汇编中编写 while 循环,但我不知道如何编写十六进制代码。我见过使用速记编写的示例,其中有一个循环应该开始和结束的标签,但我没有看到任何实际的十六进制代码。
我认为有用的两个代码是:
- 将内存中的字节与 X reg 进行比较(简写:CPX,十六进制:EC)。如果相等则将 Z 标志设置为零,
- 如果 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:
- Comparing a byte in memory to the X reg (shorthand: CPX, hex: EC). This sets the Z flag to zero if equal and
- Branch X bytes if Z flag = 0 (shorthand: BNE, hex: D0)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这里是您开始的地方。该页面具有一个可以在您的 PC 上运行的交叉汇编程序。这可能对您来说是一个很好的开发平台。
在做任何事情之前,您必须了解 6502 的操作原理。然后您必须了解软件开发过程,包括:
-- 准备所谓的“源文件”,
您的符号指令
调用“简写”
-- 使用一个
汇编器,翻译该源代码
文件写入机器指令
6502 理解
-- 加载
翻译成6502
——讲述
6502执行翻译
机器指令
您的示例程序尝试将
LEN
内存字节从SRC
复制到DST
。您可以这样格式化它:
添加更多语句行(例如
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 fromSRC
toDST
.You format it like this:
After you have added more statement lines (like
END
, for example); and after you have definedSRC
,DST
, andLEN
, 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.
下面的示例显示了程序集(您所说的“速记”)和机器代码之间的对应关系。首先,这是该算法的汇编代码,其中抽象出了一些参数:
当然,您不能将其直接转换为机器代码。您还需要填写
len
、src
和dest
的值:关于
循环
需要了解的事情名字是,就像src
被赋予值$1234
一样,loop
将被赋予其后面指令的地址。因此,在本例中,由于LDX #len
占用 2 个字节(我很快就会向您展示),因此loop
设置为$4000 + 2 = $4002< /代码>。这是由汇编器自动完成的,但当然您也可以在纸上完成所有这些工作。
那么上述汇编程序的6502机器码是什么呢?
我怎么知道这个?好吧,我刚刚将上述程序粘贴到在线 6502 汇编器中,网址为 http://www.masswerk .at/6502/assembler.html。它甚至向您展示了汇编代码和机器代码之间的详细映射:
请注意,
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:
Of course, you can't turn that directly into machine code. You also need to fill in the values of
len
,src
anddest
:The thing to understand about the
loop
name is that just likesrc
is assigned the value$1234
,loop
will be assigned the address of the instruction after it. So in this case, sinceLDX #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?
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:
Note how the actual value of
LOOP
is not even used to compute the machine code forBNE LOOP
, only its relative address compared to theBNE
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.
分支指令采用单字节有符号相对地址操作数,该操作数被添加到下一条指令的地址以产生分支目标。由于分支指令始终占用 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 ifZ=0
.while 语句的真正含义是:
对于 6502,这些都不会除非你可以做出很多假设,否则要非常简单。如果您测试的条件始终是寄存器,则比较指令(cmp、cpx、cpy)和分支指令显然是您所需要的 1。
如果它将是存储在内存中的单个字节,那么您需要加载该字节,然后进行比较。
如果它是存储在两个字节中的 16 位值,则需要加载并测试该字节的每个值。
处理浮动?如果您已经编写或有可用的浮点包(例如 Commodore 64 ROM BASIC 浮点例程),您将需要使用它们。
您可以明白为什么高级语言有数据类型。
所以实际上,这取决于您正在处理的数据类型,但 6502 中
while
的任何实现都应该遵循上述内容。如果您知道要比较的数据始终位于 X 中并且您的目的地始终位于 +127/-128 字节之外(Bxx 指令的范围限制),则您在问题中确定的具体情况是可以的。
A
while
statement really means: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).