Так как компилятор GCC категорически не может работать с 16-битными регистрами и инструкциями, минимально что он понимает это 32-бит. Поэтому настройка будет именно под эту платформу. Тем более, 386 процессор был минимум 32-битным.
-ffreestanding и -nostdlib Указание компилятору не использовать стандартную либу C/C++
-fno-pie Отключить позиционно-независимое создание программы, мы жестко фиксируем адреса
-mno-sse Не использовать SSE/MMX расширения
-static Указание что компилируем без привязки к каким-то либам .so или .dll
-ffunction-sections, -fdata-sections Размещает каждую функцию отдельно для того чтобы при указании опции -Wl,--gc-sections компилятор удалял из кода ненужные функции и данные
-flto Глубокая оптимизация кода
-T main.ld Указание схемы памяти и опции сборки
-Wl,--build-id=none Не генерировать в начале файла BIN заголовок-сигнатуру
-Wl,-z,notext Указать линковщику, что можно вставлять символы прямо в text-секцию
§ Файл линковщика
Размер кода 32К, начинается с адреса 0x8000
Данные располагаются с адреса 0x100000, допустимое место для них 1М
ENTRY(_start)
MEMORY
{
ROM (rx) : ORIGIN = 0x008000, LENGTH = 32K
RAM (rwx) : ORIGIN = 0x100000, LENGTH = 1M
}
SECTIONS
{
/* Код программы и константы (в ROM) */
.text :
{
KEEP(*(.text._start)) /* Гарантируем, что _start будет первым */
*(.text*) /* Все остальные функции */
*(.rodata*) /* Константы */
} > ROM
/* Инициализированные данные */
.data :
{
_sdata = .; /* Начало секции в RAM */
*(.data*)
_edata = .; /* Конец секции в RAM */
} > RAMAT > ROM
/* Физический адрес начала данных в ROM */
_sidata = LOADADDR(.data);
/* Неинициализированные данные */
.bss :
{
_sbss = .;
*(COMMON)
*(.bss*)
_ebss = .;
} > RAM
/DISCARD/ :
{
*(.note.gnu.build-id)
*(.note.ABI-tag)
*(.comment)
}
/* Определяем вершину стека (в конце RAM) */
_stack_top = ORIGIN(RAM) + LENGTH(RAM);
}
В файле линкера есть переменные, к примеру _sdata, _edata, _sidata – они указывают на начало данных в ROM (_sidata), а также на начало данных в RAM (с _sdata по _edata). Это глобальные данные, которые должны быть обязательно скопированы в ОЗУ перед использованием самой программой.
Тоже касается и BSS: это секция, которая должна быть пустой в памяти и очищена в нули.