как программа узнает, что это за адреса памяти?
Программа (и ее автор) не знает что адрес памяти будет, когда она загруженный в память компьютера, он знает только , где заполнитель, относительно начала его сегмента. Вот почему компилятор сопровождает каждый такой заполнитель записью о перемещении . Перемещение - это часть информации, которая сообщает ОС или компоновщику
- , где находится перемещенный адрес (его смещение в коде или сегменте данных)
- в каком сегменте он находится
- к какому сегменту или символу относится
- какой тип перемещения должен применяться к адресу
Рассмотрим следующий простой фрагмент или исходный код Windows Переносимая исполняемая программа:
[.text]
Main:NOP
LEA ESI,[Mem]
; more instructions
[.data]
DB "Some data"
Mem: DB "Other data"
, которые будут преобразованы в машинные инструкции и данные памяти:
|[.text] |[.text]
|00000000:90 |Main:NOP
|00000001:8D35[09000000] | LEA ESI,[Mem]
|00000007: | ; more instructions
|[.data] |[.data]
|00000000:536F6D6520646174~| DB "Some data"
|00000009:4F74686572206461~|Mem: DB "Other data"
Компилятор не знает виртуальный адрес Mem
, он знает только, что он расположен 0x00000009
байтов от начала .data
сегмента, поэтому он вставит этот временный номер в код операции LEA ESI,[Mem]
и создаст перемещение заполнителя (расположенного в сегменте .text
со смещением 0x00000003
) относительно сегмента .data
.
Во время компоновки компоновщик решает, что сегмент .text
будет загружен по виртуальному адресу 0x00401000
и сегмент .data
по VA 0x00402000
. Затем компоновщик читает запись о перемещении и изменяет местозаполнитель, добавляя 0x00402000
. Тогда инструкция LEA ESI,[Mem]
в связанном исполняемом файле будет 8D3509204000
, что является окончательным фиксированным виртуальным адресом Mem
. Мы сможем увидеть этот адрес в отладчике во время выполнения.
Перемещения присутствуют и в связанных исполняемых файлах (16-битный DOS MZ или Windows PE), в случае, если они не могут быть загружается по виртуальному адресу базы изображений, принятому во время соединения. Со связыванием библиотек SO в Linux это более сложно, см. Главу 2 Dynami c связывание в http://www.skyfree.org/linux/references/ELF_Format.pdf