По умолчанию 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
Комментариев нет:
Отправить комментарий