Assembly Language & Procedure Calls

the linker

A real program is rarely written in one file. You write several source files, plus you use libraries other people wrote. Each piece is compiled or assembled separately into an object file, but an object file is incomplete: it has holes where it refers to functions and data that live in other files. The linker is the tool that combines all these object files into one finished program, filling in the holes so every reference points to the right place. Think of it as the editor who takes a stack of separately written chapters and assembles them into one book with a consistent page numbering.

The linker does three main jobs. First, it lays the pieces out, deciding where in the combined program each function and chunk of data will sit. Second, it resolves symbols: when file A calls a function printf that is defined in a library, the object file for A left a blank marked needs printf; the linker finds printf's actual definition and notes its address. Third, it does relocation: it goes back and patches every blank with the now-known address, so a call that said call ??? becomes call 0x4005a0. If a needed symbol is defined nowhere, you get the classic undefined reference error; if it is defined twice, a duplicate-symbol error.

The linker matters because it is what makes separate compilation practical: you can change one file and re-link without recompiling everything, and you can ship reusable libraries as object code. It works at the orientation level you need to know here, sitting between the assembler/compiler (which produces object files) and the loader (which brings the program into memory to run). A key choice it makes is whether to copy library code directly into your program (static linking) or leave a reference to be resolved later (dynamic linking).

main.o calls a function sum defined in math.o: - In main.o, the call to sum is a blank: 'call <sum, address unknown>'. - math.o defines sum and records 'sum is here, at my offset 0x40'. - The linker places math.o, learns sum's final address (say 0x10240), and patches main.o's call to 'call 0x10240'. The blank is now filled. If no file defined sum, you'd see: undefined reference to `sum'.

Resolve symbols (find where each name is defined), then relocate (patch each reference with the real address).

An 'undefined reference' error is the linker, not the compiler: each file compiled fine on its own, but a name it needs is defined nowhere among them.

Also called
link editorld連結程式