我如何为这个墨盒头生成校验和?
How can I generate a checksum for this cartridge header?
我正在尝试为 Game Boy 购物车生成 cartridge header 校验和。磁带头校验和定义为类似 C 的伪代码:
unsigned char checksum = 0;
for(unsigned char *p = 0x0134; p < 0x014D; p++)
x += ~*p;
或者:
unsigned char checksum = 0;
for(unsigned char *p = 0x0134; p < 0x014D; p++)
x = x - *p - 1;
此数据从地址 0x0104
开始。地址0x0134
对应title
的开头。地址0x014D
对应header_checksum
的开头。
请注意,出于演示目的,我在 .ascii
字符串中使用了十六进制转义序列。这 实际上 不起作用,因为 GNU as
.
无法识别 \x
nintendo_logo:
# Nintendo logo. Must be present and unmodified.
.ascii "\xce\xed\x66\x66\xcc\x0d\x00\x0b\x03\x73\x00\x83\x00\x0c\x00\x0d"
.ascii "\x00\x08\x11\x1f\x88\x89\x00\x0e\xdc\xcc\x6e\xe6\xdd\xdd\xd9\x99"
.ascii "\xbb\xbb\x67\x63\x6e\x0e\xec\xcc\xdd\xdc\x99\x9f\xbb\xb9\x33\x3e"
title:
# Title. At most 11 characters and zero-padded if smaller.
# GameBoys use 16 characters.
TITLE_SIZE = 11
.ascii "ABCDEF"
.fill TITLE_SIZE-(.-title)
manufacturer:
.ascii "ABCD"
cgb_f:
# Color Game Boy flag. 0x80 means that the game supports
# Color Game Boy functions, but still works on the original Game Boy.
.byte 0x80
new_licensee:
# Company or publisher ASCII code. 00 is none.
.ascii "00"
sgb_f:
# Super Game Boy flag. 3 means it has support for the SGB, 0 means no.
# I might implement color for the SGB
.byte 0x03
cart_type:
# Memory bank controller used and any additional hardware.
# 0x00 is rom-only.
.byte 0x00
rom_size:
# ROM size in terms of 32KB << B
.byte 0x00
ram_size:
# The amount of externam RAM in the catridge
.byte 0x00
is_japan:
# If the byte is 0x00 it's for Japan, if 0x01 anywhere else
.byte 0x01
old_licensee:
# hex value of company/publisher
# Super Game Boy needs 0x33 to work
.byte 0x33
version:
# version of the game
.byte 0x00
header_checksum:
# TODO: How to calculate this?
sum = add(title, version)
.byte sum
如何计算这个校验和?如果可能的话,有没有办法使用汇编程序指令来做到这一点?
GAS 指令无法读取已发送到输出文件中的字节。
如果你想要assemble-time 计算 的东西,我想你可以用 a GAS .macro
来完成,它在assemble-time 表达式更新汇编程序变量, 和 作为 .byte
.
的操作数
但是您需要在用作数字的表达式中执行此操作,这可能会排除方便的 .ascii
字符串文字。
在这种情况下,转换为使用像
这样的宏可能比值得更麻烦
byte_cksum_accum 0xce,0xed,0x66,0x66,0xcc,0x0d,0x00, ...
.
这样的宏可以使用 .set cksum, cksum + ~
或类似的东西,以及 .byte
。循环多个 GAS 宏参数是通过编写递归 .macro
来完成的。所以我认为这是可能的。 GAS 还具有允许 i = i + 1
的 .altmacro
语法。我自己没怎么用过 GAS 宏。
更好的选择:使用 C 程序 + 构建规则 + .incbin
- 让您的来源使用
.incbin "checksum_file.bin
directive
- ... C 程序在阅读您的
.o
后编写的
- 在 Makefile 中,此
.o
的构建规则在外部组装/生成校验和 / re-assembles 以包含 正确的 校验和。 (在第一次组装之前触摸或截断或删除 checksum_file.bin
,以最方便的方式确保它仍然可以组装,并且如有必要 不 包含陈旧的校验和字节.)
更好的选择?
- 让你的 C 程序输出一个带有 数据 和校验和的平面二进制文件。 所以 header 字节仍然是在您的源代码中恰好出现在一个地方,在您的 C 程序的
uint8_t header[] = {...}
初始值设定项中。
- 在
.S
中使用 .incbin
来包含它。
- 使用构建规则确保 cksummed-header.bin 是构建
.S
的输入依赖项
或者写一个 C 程序修改一个二进制文件
- 读取 header,更新二进制文件中的占位符
.byte 0
。
- 将 header 数据与 asm 源的其余部分保持在一起
- C 程序不需要为不同的购物车重新编译。
我正在尝试为 Game Boy 购物车生成 cartridge header 校验和。磁带头校验和定义为类似 C 的伪代码:
unsigned char checksum = 0;
for(unsigned char *p = 0x0134; p < 0x014D; p++)
x += ~*p;
或者:
unsigned char checksum = 0;
for(unsigned char *p = 0x0134; p < 0x014D; p++)
x = x - *p - 1;
此数据从地址 0x0104
开始。地址0x0134
对应title
的开头。地址0x014D
对应header_checksum
的开头。
请注意,出于演示目的,我在 .ascii
字符串中使用了十六进制转义序列。这 实际上 不起作用,因为 GNU as
.
\x
nintendo_logo:
# Nintendo logo. Must be present and unmodified.
.ascii "\xce\xed\x66\x66\xcc\x0d\x00\x0b\x03\x73\x00\x83\x00\x0c\x00\x0d"
.ascii "\x00\x08\x11\x1f\x88\x89\x00\x0e\xdc\xcc\x6e\xe6\xdd\xdd\xd9\x99"
.ascii "\xbb\xbb\x67\x63\x6e\x0e\xec\xcc\xdd\xdc\x99\x9f\xbb\xb9\x33\x3e"
title:
# Title. At most 11 characters and zero-padded if smaller.
# GameBoys use 16 characters.
TITLE_SIZE = 11
.ascii "ABCDEF"
.fill TITLE_SIZE-(.-title)
manufacturer:
.ascii "ABCD"
cgb_f:
# Color Game Boy flag. 0x80 means that the game supports
# Color Game Boy functions, but still works on the original Game Boy.
.byte 0x80
new_licensee:
# Company or publisher ASCII code. 00 is none.
.ascii "00"
sgb_f:
# Super Game Boy flag. 3 means it has support for the SGB, 0 means no.
# I might implement color for the SGB
.byte 0x03
cart_type:
# Memory bank controller used and any additional hardware.
# 0x00 is rom-only.
.byte 0x00
rom_size:
# ROM size in terms of 32KB << B
.byte 0x00
ram_size:
# The amount of externam RAM in the catridge
.byte 0x00
is_japan:
# If the byte is 0x00 it's for Japan, if 0x01 anywhere else
.byte 0x01
old_licensee:
# hex value of company/publisher
# Super Game Boy needs 0x33 to work
.byte 0x33
version:
# version of the game
.byte 0x00
header_checksum:
# TODO: How to calculate this?
sum = add(title, version)
.byte sum
如何计算这个校验和?如果可能的话,有没有办法使用汇编程序指令来做到这一点?
GAS 指令无法读取已发送到输出文件中的字节。
如果你想要assemble-time 计算 的东西,我想你可以用 a GAS .macro
来完成,它在assemble-time 表达式更新汇编程序变量, 和 作为 .byte
.
但是您需要在用作数字的表达式中执行此操作,这可能会排除方便的 .ascii
字符串文字。
在这种情况下,转换为使用像
这样的宏可能比值得更麻烦
byte_cksum_accum 0xce,0xed,0x66,0x66,0xcc,0x0d,0x00, ...
.
这样的宏可以使用 .set cksum, cksum + ~
或类似的东西,以及 .byte
。循环多个 GAS 宏参数是通过编写递归 .macro
来完成的。所以我认为这是可能的。 GAS 还具有允许 i = i + 1
的 .altmacro
语法。我自己没怎么用过 GAS 宏。
更好的选择:使用 C 程序 + 构建规则 + .incbin
- 让您的来源使用
.incbin "checksum_file.bin
directive - ... C 程序在阅读您的
.o
后编写的
- 在 Makefile 中,此
.o
的构建规则在外部组装/生成校验和 / re-assembles 以包含 正确的 校验和。 (在第一次组装之前触摸或截断或删除checksum_file.bin
,以最方便的方式确保它仍然可以组装,并且如有必要 不 包含陈旧的校验和字节.)
更好的选择?
- 让你的 C 程序输出一个带有 数据 和校验和的平面二进制文件。 所以 header 字节仍然是在您的源代码中恰好出现在一个地方,在您的 C 程序的
uint8_t header[] = {...}
初始值设定项中。 - 在
.S
中使用.incbin
来包含它。 - 使用构建规则确保 cksummed-header.bin 是构建
.S
的输入依赖项
或者写一个 C 程序修改一个二进制文件
- 读取 header,更新二进制文件中的占位符
.byte 0
。 - 将 header 数据与 asm 源的其余部分保持在一起
- C 程序不需要为不同的购物车重新编译。