Linker

The linker is responsible for taking a number of object files and turning them into a single executable binary file. To link a program there are a few prerequisites:

  1. produce the object files you wish to link

  2. produce a LINK file to describe the desired layout for the linked program

  3. link the program

Building object files

Object files are nothing more than individually assembled fragments. Anything you assemble (Commodore key + A key) can be stored to disk in the object format. This is done with the :o Ex command. The linker will specifically look for files that end in .o when it goes to link, so be sure to enter a filename with that suffix: e.g. :o hello.o.

Your assembled program may itself specify where it should be loaded (this is what the .org directive does). In these cases, the linker doesn’t have much work. It will, at least, ensure that all the linked files don’t overlap.

Its real value comes when you use the .seg directive instead. The linker’s job is to find all the code and data that was defined in the same segment and to put it together into one contiguous block.

For example, say we have two object files: a.o and b.o

a.s

.seg "CODE"
    lda #$00
    sta $900f
.seg "DATA"
    .db "hello"

b.s

.seg "CODE"
    rol $9000
.seg "DATA"
    .db " world"

The linker will concatenate each segment in b.o to the corresponding ones defined in a.o. Effectively, the linked binary will correspond to something like this:

.seg "CODE"
    lda #$00
    sta $900f
    rol $9000
.seg "DATA"
    .db "hello"
    .db " world"

But what physical address will “CODE” and “DATA” actually correspond to? Enter the LINK file.

Section flags

In the above example, we declared the key “FILL” with the value of “1” for SECTIONA. This is called a section flag. The FILL flag tells the linker how to handle unused memory within a SECTION. The table below describes the available flags and their names.

Note that any nonzero value for these flags will enable them while the zero value disables them.

NAME

DESCRIPTION

FILL

if ‘1’ fills unused memory in the section with 0’s

Zero page sections

A SEGMENT declared with .SEGZP or .BSSZP is an address assignment only: it reserves zero page locations for its symbols and contributes no bytes to the linked binary. The SECTION such a SEGMENT loads into is therefore not part of the program image, and the linker leaves it out when working out the program’s start and end addresses. Without that, a single zero page byte would drag the program’s start address down into the zero page, making the saved .PRG load over the stack and KERNAL workspace on its way to your code.

For the same reason FILL is ignored on a SECTION that any zero page SEGMENT loads into. There is nothing to pad – the SECTION contributes no bytes – and padding it would pull the program’s start address back into the zero page.

Note that this applies to the SEGMENT’s type, not its address. A SEGMENT declared with plain .SEG that you place below $0100 is treated like any other SEGMENT: its bytes are part of the image and the program will start there.