CL65 在使用 .align 时不调整地址
CL65 doesn't adjust addresses when using .align
我正在尝试编写一个使用 .align 指令来确保数据不跨越页面边界的 asm 程序。
然而,虽然数据位于内存中的正确位置,但编译后的代码并没有使用正确的地址。
根据文档 (https://www.cc65.org/doc/ld65-5.html)
If an alignment is requested, the linker will add enough space to the
output file, so that the new segment starts at an address that is
dividable by the given number without a remainder. All addresses are
adjusted accordingly. To fill the unused space, bytes of zero are
used, or, if the memory area has a "fillval" attribute, that value.
似乎没有发生这种调整。
为了重现,我有以下配置文件:(注意 'align' 在 DATA256 段上)
# Assembly configuration for R38
FEATURES {
STARTADDRESS: default = 01;
}
SYMBOLS {
__LOADADDR__: type = import;
# Putting "-u __EXEHDR__" on cl65's command line will add a BASIC RUN stub to your program.
# __EXEHDR__: type = import;
__HIMEM__: type = weak, value = F00;
}
MEMORY {
ZP: file = "", start = [=10=]22, size = [=10=]80 - [=10=]22, define = yes;
ZP2: file = "", start = [=10=]A9, size = 00 - [=10=]A9;
LOADADDR: file = %O, start = %S - 2, size = [=10=]02;
MAIN: file = %O, start = %S, size = __HIMEM__ - %S;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP2, type = zp, optional = yes; # OK if BASIC functions not used
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro;
LOWCODE: load = MAIN, type = ro, optional = yes;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;
DATA256: load = MAIN, type = rw, align = 0;
DATA4k: load = MAIN, type = rw, align = 00;
BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
segment = RODATA;
CONDES: type = interruptor,
label = __INTERRUPTOR_TABLE__,
count = __INTERRUPTOR_COUNT__,
segment = RODATA,
import = __CALLIRQ__;
}
用asm作为
.org 01 ; Assembled code should start at 01
; (where BASIC programs start)
; The real program starts at 10 = 2064
; 10 SYS 2064
.byte [=11=]C, ; 0C - pointer to next line of BASIC code
.byte [=11=]A, [=11=] ; 2-byte line number ([=11=]0A = 10)
.byte E ; SYS BASIC token
.byte ; [space]
.byte , , , ; ="2",="0",="6",="4"
.byte [=11=] ; End of Line
.byte [=11=], [=11=] ; This is address 0C containing
; 2-byte pointer to next line of BASIC code
; ([=11=]00 = end of program)
.byte [=11=], [=11=] ; Padding so code starts at 10
cld
stp
lda testdata
rts
.segment "DATA256"
testdata:
.byte , , ,
使用以下命令行构建:
cl65 --verbose -o build.prg --cpu 65c02 -t cx16 -C asm.cfg -Ln labels.txt -m map.txt -T main.asm
这是编译后的.prg。您可以看到 'lda testdata' 从 $0816 读取,这不是对齐地址。 $01、$02、$03 的填充显示数据对齐。
这在调试器中得到确认。
我做错了什么?或者这是链接器中的错误?
不要使用 .org
指令。配置文件设置该地址:STARTADDRESS: default = 01
.
此外,该指令告诉汇编器告诉链接器“不要重定位以下代码”。这会阻止 .segment
指令执行我们期望的操作。
我正在尝试编写一个使用 .align 指令来确保数据不跨越页面边界的 asm 程序。
然而,虽然数据位于内存中的正确位置,但编译后的代码并没有使用正确的地址。
根据文档 (https://www.cc65.org/doc/ld65-5.html)
If an alignment is requested, the linker will add enough space to the output file, so that the new segment starts at an address that is dividable by the given number without a remainder. All addresses are adjusted accordingly. To fill the unused space, bytes of zero are used, or, if the memory area has a "fillval" attribute, that value.
似乎没有发生这种调整。
为了重现,我有以下配置文件:(注意 'align' 在 DATA256 段上)
# Assembly configuration for R38
FEATURES {
STARTADDRESS: default = 01;
}
SYMBOLS {
__LOADADDR__: type = import;
# Putting "-u __EXEHDR__" on cl65's command line will add a BASIC RUN stub to your program.
# __EXEHDR__: type = import;
__HIMEM__: type = weak, value = F00;
}
MEMORY {
ZP: file = "", start = [=10=]22, size = [=10=]80 - [=10=]22, define = yes;
ZP2: file = "", start = [=10=]A9, size = 00 - [=10=]A9;
LOADADDR: file = %O, start = %S - 2, size = [=10=]02;
MAIN: file = %O, start = %S, size = __HIMEM__ - %S;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
EXTZP: load = ZP2, type = zp, optional = yes; # OK if BASIC functions not used
LOADADDR: load = LOADADDR, type = ro;
EXEHDR: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro;
LOWCODE: load = MAIN, type = ro, optional = yes;
RODATA: load = MAIN, type = ro;
DATA: load = MAIN, type = rw;
DATA256: load = MAIN, type = rw, align = 0;
DATA4k: load = MAIN, type = rw, align = 00;
BSS: load = MAIN, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
segment = RODATA;
CONDES: type = interruptor,
label = __INTERRUPTOR_TABLE__,
count = __INTERRUPTOR_COUNT__,
segment = RODATA,
import = __CALLIRQ__;
}
用asm作为
.org 01 ; Assembled code should start at 01
; (where BASIC programs start)
; The real program starts at 10 = 2064
; 10 SYS 2064
.byte [=11=]C, ; 0C - pointer to next line of BASIC code
.byte [=11=]A, [=11=] ; 2-byte line number ([=11=]0A = 10)
.byte E ; SYS BASIC token
.byte ; [space]
.byte , , , ; ="2",="0",="6",="4"
.byte [=11=] ; End of Line
.byte [=11=], [=11=] ; This is address 0C containing
; 2-byte pointer to next line of BASIC code
; ([=11=]00 = end of program)
.byte [=11=], [=11=] ; Padding so code starts at 10
cld
stp
lda testdata
rts
.segment "DATA256"
testdata:
.byte , , ,
使用以下命令行构建:
cl65 --verbose -o build.prg --cpu 65c02 -t cx16 -C asm.cfg -Ln labels.txt -m map.txt -T main.asm
这是编译后的.prg。您可以看到 'lda testdata' 从 $0816 读取,这不是对齐地址。 $01、$02、$03 的填充显示数据对齐。
这在调试器中得到确认。
我做错了什么?或者这是链接器中的错误?
不要使用 .org
指令。配置文件设置该地址:STARTADDRESS: default = 01
.
此外,该指令告诉汇编器告诉链接器“不要重定位以下代码”。这会阻止 .segment
指令执行我们期望的操作。