字节指令在 6502 汇编程序中的作用是什么?

What does the byte directive do in 6502 assembler?

首先:对不起,如果这是一个骗局!我搜索了一下,但没有找到可以令人满意地解释这一点的资源。

n00bish 问题在这里!

我想了解 .byte 指令的作用。不同的来源说不同的话,其要点是这样的:

.db, DB, .byte, etc. lay down the exact bytes you specify, as data and not as instructions (http://forum.6502.org/viewtopic.php?f=2&t=2374)

cc65手册给出了类似的含糊:

.byte: Define byte sized data. Must be followed by a sequence of (byte ranged) expressions or strings.

Example:

        .byte   "Hello "
        .byt    "world", [=10=]D, [=10=]

(http://www.cc65.org/doc/ca65-11.html)

我不知道那是什么意思。我认为所有与定义数据相关的操作都是读写内存地址的变体。所以像这样(来自 NES 开发的图)

; Number of PRG-ROM blocks
.byte 
; Number of CHR-ROM blocks
.byte 
; ROM control bytes: Horizontal mirroring, no SRAM
; or trainer, Mapper #0
.byte [=11=], [=11=]

它到底在做什么?这一切都可以用操作码来解释吗,还是它在做一些更奇特的事情?对我来说,它看起来像是在写顺序数据,从零页开始,像这样??:

LDA #
STA [=12=]
LDA #
STA 
LDA #[=12=]
STA 
LDA #[=12=]
STA 

我离这儿远吗?我一直在阅读 6502 Software Design by Leo Scanlon,但我没有看到对那个(或任何)指令的引用。我正在学习 6502 用于 NES 开发,所有示例代码都充满了 .byte.ascii 和其他几个指令。在尝试浏览用户提供的 NES 教程的世界之前,我真的很想尝试从像 Scanlon 书这样的学术文本中获得 6502 的坚实基础,但这正在成为我理解 NES 6502 的障碍。

看完评论我试着给出答案:

在大多数计算机的内存中,各种数据(包括代码)都以字节的形式存储。

这意味着汇编程序最后必须将所有指令翻译成字节。

指令"LDA 34"将存储为三个字节:$AD、$12和$34。

使用指令“.byte”、“.word”和“.long”(可能是6502不支持“.long”)你可以直接指示汇编器把一些给定的字节放到一些内存位置代表一些指令的字节。

想象一下下面这段代码是操作系统的一部分:

LDX 00
STA 0,X
...
JSR 01

在这种情况下,地址 $2000 的字节将包含零页中的一个地址,A 寄存器将写入该地址,而地址 $2001 的字节是实际代码的第一个字节。

从地址 $2000 开始的数据的汇编代码现在可能如下所示:

# Zero-page address where the OS will store the A register
.byte 
# Actual code called by the OS
LDA 
...
RTS

希望对您有所帮助。

--- 编辑 ---

关于带有“.ascii "iNES"”行的示例:

这些行仅出现在 NES 模拟器的程序中,而不出现在真正的 NES 设备的程序中。

当使用术语 "operating system" 的非常非常广泛的定义时,您可能会说 NES 模拟器是某种 "operating system"。在这种情况下,示例中“.byte”行的原因与上述相同:

"operating system"(= NES 模拟器)将读取文件的前 16 个字节,检查这些字节,对这些字节执行一些操作,然后实际运行代码。

您可能还在代码中看到了以下几行:

.advance $FFFA
.word vblank, reset, irq

这两行也不是 6502 汇编器指令,而是对汇编器的指令:

它们指示汇编程序将六个特殊字节写入地址 $FFFA。这是必要的,因为 6502 CPU 需要六个字节代表地址 $FFFA-$FFFF 处的三个特殊地址。

这里有两件不同的事情需要考虑。您正在混合 ROM 内存位置,值总是在这里(它们不能也不应该是 "loaded in")和 RAM,系统开机时内容未定义,并且在哪里您要使用的任何数据都必须在某些时候有效 "loaded in"。

例如:

.byte [=10=], , , 

将在 ROM 的某处添加这 4 个字节。他们不是"loaded in",他们总是在这里。

相对于:

ldx #[=11=]
stx somewhere
inx
stx somewhere+1
inx
stx somewhere+2
inx
stx somewhere+3

如果某处 指向RAM,那么这将在此位置加载字节$00、$01、$02、$03。这些字节仅在您加载这些值后位于 RAM 位置,直到您用其他值覆盖 RAM。

现在,对于你的例子,这实际上是一个令人困惑的例子,因为它定义了 iNES header 格式的字节,它总是 16 字节长。 这些字节既不是 ROM 也不是 RAM 的一部分,只是 header 在 PC 上存储 NES ROM 的约定。

您看到的示例只是让汇编程序认为 header 是 ROM 的一部分,而实际上它不是。这只是其中一种方法。另一种方法是用汇编程序生成一个干净的 "raw" ROM 映像,并在构建时单独添加 iNES header,这是我个人的做法。

希望对您有所帮助。