【问题标题】:What does the byte directive do in 6502 assembler?字节指令在 6502 汇编器中的作用是什么?
【发布时间】:2015-03-02 05:20:30
【问题描述】:

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

n00bish 问题在这里!

我试图了解.byte 指令的作用。不同的来源说不同的东西,其要点如下:

.db、DB、.byte 等列出您指定的确切字节,作为数据而不是指令 (http://forum.6502.org/viewtopic.php?f=2&t=2374)

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

.byte:定义字节大小的数据。后面必须有一个序列 (字节范围)表达式或字符串。

例子:

        .byte   "Hello "
        .byt    "world", $0D, $00

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

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

; Number of PRG-ROM blocks
.byte $01
; Number of CHR-ROM blocks
.byte $01
; ROM control bytes: Horizontal mirroring, no SRAM
; or trainer, Mapper #0
.byte $00, $00

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

LDA #$01
STA $00
LDA #$01
STA $01
LDA #$00
STA $02
LDA #$00
STA $03

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

【问题讨论】:

  • 指令将字节直接放在输出中。没有内存访问。例如,LDA #1.byte $A9, $01 相同。
  • 什么是“输出”?
  • 情况正好相反。所有操作码都可以翻译成.byte 指令。这就是汇编程序所做的。它需要操作码并将它们转换为字节。
  • 就像您引用的文章中所说的那样:“作为数据而不是说明。”如果您需要将数据放入程序中,您只需要将字节放入内存映像中。
  • 哈哈这有点拖沓……“输出”是程序文件的内容。现在这一切都说得通了。 @RaymondChen 感谢您帮助理解这一点

标签: assembly 6502 nintendo


【解决方案1】:

这里有两件不同的事情需要考虑。您正在混合 ROM 内存位置,值总是在这里(它们不能也不应该被“加载”)和 RAM,当系统开机时内容未定义,以及任何您想要使用的数据必须在某个时候有效地“加载”。

例如:

.byte $00, $01, $02, $03

将在 ROM 中的某处添加这 4 个字节。它们没有“加载”,它们总是在这里。

相对于:

ldx #$00
stx somewhere
inx
stx somewhere+1
inx
stx somewhere+2
inx
stx somewhere+3

如果 somewhere 指向 RAM,那么这将在此位置加载字节 $00、$01、$02、$03。这些字节只有在您加载这些值后才会出现在 RAM 位置,直到您用其他值覆盖 RAM。

现在,就您的示例而言,这实际上是一个令人困惑的示例,因为它定义了 iNES 标头格式的字节,该格式始终为 16 个字节长。 这些字节既不是 ROM 也不是 RAM 的一部分,而只是在 PC 上存储 NES ROM 的标头约定。

您看到的示例只是诱使汇编程序认为标头是 ROM 的一部分,而实际上并非如此。这只是其中一种方法。另一种方法是使用汇编程序生成一个干净的“原始”ROM 映像,并在构建时单独添加 iNES 头文件,这就是我个人的做法。

我希望这会有所帮助。

【讨论】:

  • 所以,就像您将这些字节写入文件一样。这就是@Martin 所说的“输出”。并且还解释了 .ascii "NES" 的意义,因为其目的实际上是在文件的标题中出现短语 "NES"。解决了这个问题,谢谢!
  • 是的,在这种情况下,“输出”将直接是一个 iNES 文件,包括 iNES 头文件、PRG-ROM 以及可能存在的 CHR-ROM。但是,在其他情况下,输出可能是其他内容,例如,如果您在汇编中为 PC 编程,您还可以使用 .byte 将常量数据放在程序部分中。使用 .byte 生成 iNES 标头只是一个肮脏的把戏。
  • 我对 asm 不够熟悉,无法理解为什么这是“脏”。设置 iNes 标头的“干净”方式是什么?
  • 好吧,我个人将标题放在一个单独的文件中,并使用(windows)命令行copy /b header.bin + prgrom.bin + chrrom.bin game.nes 来创建iNES ROM。这并不意味着它是唯一的选择(也不是最好的选择)。
  • 是的,,incbin 的工作方式与 .byte 完全相同,只是它会自动将整个二进制文件粘贴到您的 ROM 中。祝你好运:)
【解决方案2】:

读完cmets后,我试着给出一个答案:

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

这意味着汇编程序最后必须将所有指令转换为字节。

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

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

想象一下作为操作系统一部分的以下代码:

LDX $2000
STA 0,X
...
JSR $2001

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

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

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

我希望这会有所帮助。

--- 编辑---

关于您使用“.ascii "iNES"' 行的示例:

这些行只存在于 NES 模拟器的程序中,而不存在于真正的 NES 设备的程序中。

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

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

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

.advance $FFFA
.word vblank, reset, irq

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

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

【讨论】:

  • 我仍然对这里的示例感到困惑:forum.6502.org/viewtopic.php?f=2&t=2374 其中.bytes 似乎用于将值列表加载到内存中
  • 一个更好的例子是:; iNES identifier .ascii "NES" .byte $1a ; Number of PRG-ROM blocks .byte $01 ; Number of CHR-ROM blocks .byte $01 ; ROM control bytes: Horizontal mirroring, no SRAM ; or trainer, Mapper #0 .byte $00, $00 ; Filler .byte $00,$00,$00,$00,$00,$00,$00,$00 ; PRG-ROM .include "tutorprg.p65" ; CHR-ROM .include "tutorchr.p65"“填充物”到底在做什么? (hackipedia.org/Platform/Nintendo/NES/…)
  • 嗯,是填充物。什么都不做的字节。
  • 不,任何操作系统都不需要 iNES,第一条指令根本不在 iNES 标头之后。顺便说一句,NES 中没有操作系统。对不起,但你的评论只是一派胡言。您似乎对 C64 或任何其他机器感到困惑。
猜你喜欢
  • 1970-01-01
  • 2021-08-30
  • 1970-01-01
  • 2011-11-09
  • 1970-01-01
  • 1970-01-01
  • 2023-01-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多