Страницы

Поиск по вопросам

среда, 5 декабря 2018 г.

Изменить сегмент в ld

По умолчанию ld, как я понял, считает, что в %ds находится 0 и соответственно компонует программу на языке C с этим значением. Как его изменить в настройках компоновщика, чтобы при изменении %ds на другое значение в программе (например, 0x07c0), она работала корректно?
На всякий случай уточню, что речь идёт о написании программы наподобие загрузчика.


Ответ

Как я понял, напрямую задать %ds нельзя, но зато для секции .data можно указать VMA, что расшифровывается, как Virtual Memory Address. После этого, компоновщик будет загружать секцию по LMA (Load Memory Address), но адреса переменных, находящихся в этой секции, при обращении к этим переменным из программы, будут начинаться с VMA, а не с LMA.
Рассмотрим такой пример: в %ds устанавливается в коде значение 0x07c0, секция .text загружается по адресу 0x7c00, .data находится сразу после .text. Тогда необходимо установить VMA равным размеру секции .text. После этого, например, переменная, находящаяся в самом начале секции .data, при обращении к ней из кода программы, будет иметь адрес %ds*16+Размер секции .text=0x7c00+Размер секции .text. Это соответствует фактическому расположению переменной. Полный код скрипта компоновщика:
ENTRY(main); SECTIONS { . = 0x7C00; /*установлен только LMA, VMA такой же */ .text : AT(0x7C00) { _text = .; *(.text*); _text_end = .; } /*VMA=SIZEOF(.text) LMA=ADDR (.text) + SIZEOF (.text)*/ .data (SIZEOF(.text)) : AT(ADDR (.text) + SIZEOF (.text)) { _data = .; *(.bss); *(.bss*); *(.data); *(.rodata*); *(COMMON) _data_end = .; } .sig : AT(0x7DFE) { SHORT(0xaa55); } /DISCARD/ : { *(.note*); *(.iplt*); *(.igot*); *(.rel*); *(.comment); *(.eh_frame); } }
Подробнее про LMA и VMA можно почитать по этой ссылке https://sourceware.org/binutils/docs/ld/Output-Section-LMA.html

Комментариев нет:

Отправить комментарий