Компилятор помещает весь код и некоторые данные только для чтения в раздел .text
.Также может быть раздел .rodata
.Вы можете сделать так, чтобы ваш скрипт компоновщика поместил в адрес ПЗУ что-то вроде этого:
. = <rom-base-address>;
.rodata : { *(.rodata) }
<other read-only sections go here>
.text : { *(.text) }
Компилятор помещает все начальные значения доступных для записи данных в раздел .data
и все символы, которые не имеютначальное значение в .bss
..bss
просто, вы просто помещаете это в оперативную память..data
хочет быть в ОЗУ во время выполнения, но в ПЗУ во время загрузки, и скрипт компоновщика позволяет сделать это с ключевым словом AT
:
. = <ram-base-address>;
.bss : { *(.bss) }
.data : AT ( ADDR (.text) + SIZEOF (.text) )
{ *(.data) }
Это означает, что данныераздел теперь имеет разные LMA и VMA (адрес загрузки памяти / адрес виртуальной памяти).Ваша программа будет ожидать найти данные в VMA (во время выполнения), но эти данные действительно будут существовать в LMA (вам, возможно, придется научить ваш флешер это делать), что сразу после раздела .text
.
Если вам нужно выяснить, куда копировать и откуда, вы можете создать указатели в скрипте компоновщика.Итак, измените приведенный выше пример следующим образом:
.data : AT ( ADDR (.text) + SIZEOF (.text) )
{ _data_lma = LOADADDR(.data); _data_vma = .;
*(.data);
_data_size = SIZEOF (.data);}
Затем вы можете сделать memcpy (_data_vma, _data_lma, _data_size)
в своем коде запуска (хотя вам, возможно, придется кодировать это вручную в ассемблере?)ваша программа как постоянные глобальные переменные, которые разрешаются во время соединения.Итак, в вашем ассемблерном коде у вас может быть что-то вроде:
_data_lma_k:
.long _data_lma
Тогда число будет жестко запрограммировано в разделе .text
.Конечно, синтаксис ассемблера может отличаться на вашей платформе.
Для получения дополнительной информации см. Руководство по компоновщику здесь