0

我最近在为基于 Motorola 68000 的系统(SEGA Mega Drive)链接多个目标文件时遇到了一个小问题。问题是,当一个目标文件的输入段结束而下一个开始时,链接器用零填充内存地址,以便下一个目标文件开始在四字节边界上对齐。下面的文本是链接器输出的内存映射。如您所见,.text 输出部分包含三个目标文件。前两个(main.o、swap.o)是用 C 语言编写的,使用m68k-elf-gcc编译和组装。第三个(swap_asm.o)是用68000汇编手写的,使用vasm组装. swap.o 开头的函数通常从地址 0x0000001E 开始。但是,链接器用两个字节*填充*swap.o文件的开头,特别是0x0000。所以,swap.o 从 0x00000020 开始。但是,swap_asm.o 没有对齐,而是从一个非四字节对齐的地址 0x00000036 开始。有没有办法让链接器不添加任何填充并立即启动 swap.o?我知道有一些解决方法,比如用 NOP 填充空间,但我想知道是否有办法不做 *fill*?

.text           0x00000000       0x4c
 main.o(.text)
 .text          0x00000000       0x1e main.o
                0x00000000                main
 swap.o(.text)
 *fill*         0x0000001e        0x2 
 .text          0x00000020       0x16 swap.o
                0x00000020                swap
 swap_asm.o(.text)
 .text          0x00000036       0x16 swap_asm.o
                0x00000036                swap_asm
4

2 回答 2

0

所以我找到了我的答案。当汇编器检测到汇编文件中正在处理长(32 位)数据时,它会自动将输入部分沿 4 字节边界对齐。您实际上可以在链接描述文件中使用 SUBALIGN 覆盖它。这是我的链接器脚本,将输入部分沿 2 字节边界对齐。


MEMORY
{
    rom : ORIGIN = 0x00000000, LENGTH = 0x00400000
}

SECTIONS
{
  .text  : SUBALIGN(0x2) {
        *(.header)
        *(.boot)
        obj/main.o(.text)
        *(.text)
        *(.isr)
        *(.vdp)
  } > rom
  .data : { *(.data) } > rom
  .bss : { *(.bss) } > rom
}

新的链接器映射:

.text           0x00000000       0x4a
 main.o(.text)
 .text          0x00000000       0x1e main.o
                0x00000000                main
 swap.o(.text) 
 .text          0x0000001e       0x14 swap.o
                0x0000001e                swap
 swap_asm.o(.text)
 .text          0x00000034       0x16 swap_asm.o
                0x00000034                swap_asm
于 2022-01-19T01:25:09.603 回答
0

68000 处理器需要对齐指令(这个要求也适用于数据)。尽管有 CPU 要求(不可跳过),链接器还使用一个脚本,其中段需要有一些对齐(通常是为了满足这个 cpu 要求)

虽然链接器脚本可以调整,但更改对齐方式可能会使链接器产生不正确的代码(因为上一段中所说的),但无论如何,这是您可以尝试和测试的东西。

摩托罗拉 68000(以及更多的 16 位版本的 MegaDrive)在奇数地址上请求 16 位传输时触发总线错误陷阱。如果是 32 位,也会发生同样的情况(但这也发生在 68030 之前,我认为 68040 已经处理了这个问题,例如英特尔处理器)

于 2022-01-17T07:18:35.487 回答