С теоретической точки зрение самый "правильный" способ - это динамическая компоновка. То есть, имеется динамический компоновщик, а с каждым модулем предоставляется дополнительная информация (метаинформация) о расположении и связи с именами точек входа в процедуры, переменных, и т. д. Обращение к процедурам и переменным во внешних модулях осуществляется по именам. При загрузке модуля динамический компоновщик использует информацию о именах и пропатчивает код модуля подставляя актуальные адреса, смещения и константы.

Преимущества динамической компоновки:
-- Возможна полностью раздельная компиляция как импортируемого так и импортирующего модуля. Правда, понадобится компилятор, который умеет создавать информацию о символах.
-- После того как компоновка завершена, модули могут напрямую вызывать процедуры и обращаться к данным друг друга - повышение производительности.

Недостатки:
-- Требуется память под код динамического компоновщика.
-- Требуется время для его работы (обычно это несущественно).
-- Требуется память под информацию о символах. Однако, после операции динамической компоновки её можно использовать повторно.

Другой популярный способ - таблица точек входа в процедуры, расположенная по общеизвестному адресу. Идея в том, имеется фиксированый адрес, обозначенный в документации и не меняющийся от одной версии программы к другой. По этому адресу располагается таблица адресов точек входа в процедуры (могут располагаться также адреса переменных), причём для каждой процедуры смещение её адреса в таблице также не меняется от версии к версии, сам записанный адрес может меняться от версии к версии. Подгружаемый модуль знает адрес таблицы, извлекает из него адрес и использует его для вызова процедуры.

Достоинства:
-- Таблицу адресов можно очень просто автоматически формировать пользуясь уже имеющимися трансляторами ассемблера

Недостатки:
-- Замедление исполнения. Каждый вызов требует обращения к таблице.
-- Раздувание модуля. Дополнительный код для обращения к таблице занимает память.
-- Сама таблица тоже занимает память и её нельзя освободить.
-- Потенциально меньшая гибкость. Адрес таблицы не должен меняться от версии к версии.