ЛР13. Исправление скрипта компоновщика

This commit is contained in:
Andrei Solodovnikov
2023-12-11 16:45:48 +03:00
parent 7626efc394
commit 26b0f592f5
2 changed files with 100 additions and 25 deletions

View File

@@ -95,25 +95,48 @@ ENTRY(_start) /* мы сообщаем компоно
находится у метки "start" находится у метки "start"
*/ */
/* _text_size = 0x4000; /* Размер памяти инстр.: 16KiB */
Объявляем вспомогательные глобальные переменные _data_base_addr = 0x4000; /* Стартовый адрес секции данных */
*/ _data_size = 0x4000; /* Размер памяти данных: 16KiB */
_text_size = 0x4000; /* Размер памяти инстр.: 16KiB */
_data_base_addr = 0x8000; /* Стартовый адрес секции данных */
_data_size = 0x4000; /* Размер памяти данных: 16KiB */
_data_end = _data_base_addr + _data_size; _data_end = _data_base_addr + _data_size;
_trap_stack_size = 2560; /* Размер стека обработчика перехватов. _trap_stack_size = 2560; /* Размер стека обработчика перехватов.
Данный размер позволяет выполнить Данный размер позволяет выполнить
до 32 вложенных вызовов при обработке до 32 вложенных вызовов при обработке
перехватов. перехватов.
*/ */
_stack_size = 1280; /* Размер программного стека. _stack_size = 1280; /* Размер программного стека.
Данный размер позволяет выполнить Данный размер позволяет выполнить
до 16 вложенных вызовов. до 16 вложенных вызовов.
*/ */
/*
В данном разделе указывается структура памяти:
Сперва идет регион "rom", являющийся read-only памятью с исполняемым кодом
(об этом говорят атрибуты 'r' и 'x' соответственно). Этот регион начинается
с адреса 0x00000000 и занимает _text_size байт.
Далее идет регион "ram", начинающийся с адреса _data_base_addr и занимающий
_data_size байт. Этот регион является памятью, противоположной региону "ram"
(в том смысле, что это не read-only память с исполняемым кодом).
*/
MEMORY
{
rom (rx) : ORIGIN = 0x00000000, LENGTH = _text_size
ram (!rx) : ORIGIN = _data_base_addr, LENGTH = _data_size
}
/*
В данном разделе описывается размещение программы в памяти.
Программа разделяется на различные секции:
- секции исполняемого кода программа;
- секции статических переменных и массивов, значение которых должно быть
"вшито" в программу;
и т.п.
*/
SECTIONS SECTIONS
{ {
PROVIDE( _start = 0x00000000 ); /* Позиция start в памяти PROVIDE( _start = 0x00000000 ); /* Позиция start в памяти
@@ -137,23 +160,31 @@ SECTIONS
секция .text итогового файла, которая состоит из секций .boot, а также всех секция .text итогового файла, которая состоит из секций .boot, а также всех
секций, начинающихся на .text во всех переданных компоновщику двоичных секций, начинающихся на .text во всех переданных компоновщику двоичных
файлах. файлах.
Дополнительно мы указываем, что данная секция должна быть размещена в
регионе "rom".
*/ */
.text : {*(.boot) *(.text*)} .text : {*(.boot) *(.text*)} >rom
/* /*
Поскольку мы не знаем суммарного размера получившейся секции, мы проверяем Поскольку мы не знаем суммарного размера получившейся секции, мы проверяем
что не вышли за границы памяти инструкций и переносим счетчик адресов за пределы. Памяти инструкций в область памяти данных что не вышли за границы памяти инструкций и переносим счетчик адресов за
пределы памяти инструкций в область памяти данных.
Дополнительно мы указываем, что данная секция должна быть размещена в
регионе "ram".
*/ */
ASSERT(. < _text_size, ".text section exceeds instruction memory size") ASSERT(. < _text_size, ".text section exceeds instruction memory size")
. = _data_base_addr; . = _data_base_addr;
/* /*
Следующая команда сообщает, что начиная с адреса, которому в данных момент Следующая команда сообщает, что начиная с адреса, которому в данных момент
равен счетчик адресов (_data_base_addr) будет находиться секция .data итогового файла, которая состоит из секций всех секций, начинающихся равен счетчик адресов (_data_base_addr) будет находиться секция .data
итогового файла, которая состоит из секций всех секций, начинающихся
на .data во всех переданных компоновщику двоичных файлах. на .data во всех переданных компоновщику двоичных файлах.
Дополнительно мы указываем, что данная секция должна быть размещена в
регионе "ram".
*/ */
.data : {*(.data*)} .data : {*(.data*)} >ram
/* /*
Общепринято присваивать GP значение равное началу секции данных, смещенное Общепринято присваивать GP значение равное началу секции данных, смещенное
@@ -171,7 +202,8 @@ SECTIONS
/* /*
Поскольку мы не знаем суммарный размер всех используемых секций данных, Поскольку мы не знаем суммарный размер всех используемых секций данных,
перед размещением других секций, необходимо выравнять счетчик адресов по 4х-байтной границе. перед размещением других секций, необходимо выравнять счетчик адресов по
4х-байтной границе.
*/ */
. = ALIGN(4); . = ALIGN(4);
@@ -197,9 +229,12 @@ SECTIONS
указывающие на начало и конец bss-секции посредством счетчика адресов. указывающие на начало и конец bss-секции посредством счетчика адресов.
Подробнее: Подробнее:
https://en.wikipedia.org/wiki/.bss https://en.wikipedia.org/wiki/.bss
Дополнительно мы указываем, что данная секция должна быть размещена в
регионе "ram".
*/ */
_bss_start = .; _bss_start = .;
.bss : {*(.bss*)} .bss : {*(.bss*)} >ram
_bss_end = .; _bss_end = .;
@@ -213,7 +248,8 @@ SECTIONS
стека от наложения на него стека прерываний. стека от наложения на него стека прерываний.
Однако перед этим, мы должны убедиться, что под программный стек останется Однако перед этим, мы должны убедиться, что под программный стек останется
хотя бы 1280 байт (ничем не обоснованное число, взятое с потолка). хотя бы 1280 байт (ничем не обоснованное число, взятое с потолка).
Такое значение обеспечивает до 16 вложенных вызовов (если сохранять только необерегаемые регистры). Такое значение обеспечивает до 16 вложенных вызовов (если сохранять только
необерегаемые регистры).
================================= =================================
*/ */

View File

@@ -6,7 +6,7 @@ ENTRY(_start) /* мы сообщаем компоно
*/ */
_text_size = 0x4000; /* Размер памяти инстр.: 16KiB */ _text_size = 0x4000; /* Размер памяти инстр.: 16KiB */
_data_base_addr = 0x8000; /* Стартовый адрес секции данных */ _data_base_addr = 0x4000; /* Стартовый адрес секции данных */
_data_size = 0x4000; /* Размер памяти данных: 16KiB */ _data_size = 0x4000; /* Размер памяти данных: 16KiB */
_data_end = _data_base_addr + _data_size; _data_end = _data_base_addr + _data_size;
@@ -21,6 +21,32 @@ _stack_size = 1280; /* Размер программного
Данный размер позволяет выполнить Данный размер позволяет выполнить
до 16 вложенных вызовов. до 16 вложенных вызовов.
*/ */
/*
В данном разделе указывается структура памяти:
Сперва идет регион "rom", являющийся read-only памятью с исполняемым кодом
(об этом говорят атрибуты 'r' и 'x' соответственно). Этот регион начинается
с адреса 0x00000000 и занимает _text_size байт.
Далее идет регион "ram", начинающийся с адреса _data_base_addr и занимающий
_data_size байт. Этот регион является памятью, противоположной региону "ram"
(в том смысле, что это не read-only память с исполняемым кодом).
*/
MEMORY
{
rom (rx) : ORIGIN = 0x00000000, LENGTH = _text_size
ram (!rx) : ORIGIN = _data_base_addr, LENGTH = _data_size
}
/*
В данном разделе описывается размещение программы в памяти.
Программа разделяется на различные секции:
- секции исполняемого кода программа;
- секции статических переменных и массивов, значение которых должно быть
"вшито" в программу;
и т.п.
*/
SECTIONS SECTIONS
{ {
PROVIDE( _start = 0x00000000 ); /* Позиция start в памяти PROVIDE( _start = 0x00000000 ); /* Позиция start в памяти
@@ -44,23 +70,31 @@ SECTIONS
секция .text итогового файла, которая состоит из секций .boot, а также всех секция .text итогового файла, которая состоит из секций .boot, а также всех
секций, начинающихся на .text во всех переданных компоновщику двоичных секций, начинающихся на .text во всех переданных компоновщику двоичных
файлах. файлах.
Дополнительно мы указываем, что данная секция должна быть размещена в
регионе "rom".
*/ */
.text : {*(.boot) *(.text*)} .text : {*(.boot) *(.text*)} >rom
/* /*
Поскольку мы не знаем суммарного размера получившейся секции, мы проверяем Поскольку мы не знаем суммарного размера получившейся секции, мы проверяем
что не вышли за границы памяти инструкций и переносим счетчик адресов за пределы. Памяти инструкций в область памяти данных что не вышли за границы памяти инструкций и переносим счетчик адресов за
пределы памяти инструкций в область памяти данных.
Дополнительно мы указываем, что данная секция должна быть размещена в
регионе "ram".
*/ */
ASSERT(. < _text_size, ".text section exceeds instruction memory size") ASSERT(. < _text_size, ".text section exceeds instruction memory size")
. = _data_base_addr; . = _data_base_addr;
/* /*
Следующая команда сообщает, что начиная с адреса, которому в данных момент Следующая команда сообщает, что начиная с адреса, которому в данных момент
равен счетчик адресов (_data_base_addr) будет находиться секция .data итогового файла, которая состоит из секций всех секций, начинающихся равен счетчик адресов (_data_base_addr) будет находиться секция .data
итогового файла, которая состоит из секций всех секций, начинающихся
на .data во всех переданных компоновщику двоичных файлах. на .data во всех переданных компоновщику двоичных файлах.
Дополнительно мы указываем, что данная секция должна быть размещена в
регионе "ram".
*/ */
.data : {*(.data*)} .data : {*(.data*)} >ram
/* /*
Общепринято присваивать GP значение равное началу секции данных, смещенное Общепринято присваивать GP значение равное началу секции данных, смещенное
@@ -78,7 +112,8 @@ SECTIONS
/* /*
Поскольку мы не знаем суммарный размер всех используемых секций данных, Поскольку мы не знаем суммарный размер всех используемых секций данных,
перед размещением других секций, необходимо выравнять счетчик адресов по 4х-байтной границе. перед размещением других секций, необходимо выравнять счетчик адресов по
4х-байтной границе.
*/ */
. = ALIGN(4); . = ALIGN(4);
@@ -104,9 +139,12 @@ SECTIONS
указывающие на начало и конец bss-секции посредством счетчика адресов. указывающие на начало и конец bss-секции посредством счетчика адресов.
Подробнее: Подробнее:
https://en.wikipedia.org/wiki/.bss https://en.wikipedia.org/wiki/.bss
Дополнительно мы указываем, что данная секция должна быть размещена в
регионе "ram".
*/ */
_bss_start = .; _bss_start = .;
.bss : {*(.bss*)} .bss : {*(.bss*)} >ram
_bss_end = .; _bss_end = .;
@@ -120,7 +158,8 @@ SECTIONS
стека от наложения на него стека прерываний. стека от наложения на него стека прерываний.
Однако перед этим, мы должны убедиться, что под программный стек останется Однако перед этим, мы должны убедиться, что под программный стек останется
хотя бы 1280 байт (ничем не обоснованное число, взятое с потолка). хотя бы 1280 байт (ничем не обоснованное число, взятое с потолка).
Такое значение обеспечивает до 16 вложенных вызовов (если сохранять только необерегаемые регистры). Такое значение обеспечивает до 16 вложенных вызовов (если сохранять только
необерегаемые регистры).
================================= =================================
*/ */