I've recently come across a minor issue when linking multiple object files for a Motorola 68000 based system (SEGA Mega Drive). The problem is, when an input section for one object file ends and the next one begins, the linker fills memory addresses with zeros so that the next object file begins aligned on a four byte boundary. The text below is a memory map output by the linker. As you can see, the .text output section contains three object files. The first two (main.o, swap.o), were written in C compiled and assembled using m68k-elf-gcc. The third one (swap_asm.o) was hand written in 68000 assembly and assembled using the vasm. The function at the beginning of swap.o would normally start at address 0x0000001E. But, the linker is *fill*ing the beginning of the swap.o file with two bytes, specifically 0x0000. So, swap.o starts at 0x00000020. But, swap_asm.o is not getting aligned and begins at a non-four-byte-aligned address, 0x00000036. Is there a way to make the linker not add any padding and just start the swap.o right away? I understand there are a few work arounds like filling the space with a NOP, but I was wondering if there is a way to just not do a *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
So I found my answer. When the assembler detects long (32-bits) data is being dealt with in an assembly file, it automatically aligns the input section along a 4 byte boundary. You can actually override this using SUBALIGN in a linker script. Here's my linker script aligning input sections along a 2 byte boundary.
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
}
New linker map:
.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