Доступ к переменной сценария, заданной в компоновщике, из источникаКод не интуитивно понятен.В частности, символ сценария компоновщика не эквивалентен объявлению переменной на языке высокого уровня, это символ, который не имеет значения.
Прежде чем идти дальше, важно отметить, что компиляторы часто преобразуютимена в исходном коде на разные имена, когда они хранятся в таблице символов.Например, компиляторы Fortran обычно добавляют или добавляют символ подчеркивания, а C ++ выполняет тщательное искажение имен.Поэтому может возникнуть несоответствие между именем переменной, используемой в исходном коде, и именем той же переменной, которая определена в сценарии компоновщика.Например, в C переменная сценария компоновщика может называться:
extern int foo;
Но в сценарии компоновщика она может быть определена следующим образом:
_foo = 1000;
В остальных примерах этоПредполагается, что преобразование имен не выполнялось.
Когда символ объявляется на языке высокого уровня, таком как C, происходят две вещи.Во-первых, компилятор резервирует достаточно места в памяти программы для хранения значения символа.Во-вторых, компилятор создает запись в таблице символов программы, которая содержит символ address .то есть таблица символов содержит адрес блока памяти, содержащего значение символа.Так, например, следующее объявление C в области видимости файла:
int foo = 1000;
создает запись с именем "foo" в таблице символов.Эта запись содержит адрес блока памяти размера int, в котором изначально хранится число 1000.
Когда программа ссылается на символ, компилятор генерирует код, который сначала обращается к таблице символов, чтобы найти адрес памяти символаблок, а затем код для чтения значения из этого блока памяти.Итак:
foo = 1;
ищет символ foo в таблице символов, получает адрес, связанный с этим символом, а затем записывает значение 1 в этот адрес.Принимая во внимание, что:
int * a = & foo;
ищет символ foo в таблице символов, получает его адрес и затем копирует этот адрес в блок памяти, связанный с переменной «a».
Сценарии компоновщикаОбъявления символов, напротив, создают запись в таблице символов, но не назначают им память.Таким образом, они являются адресом без значения.Так, например, определение сценария компоновщика:
foo = 1000;
создает запись в таблице символов с именем @samp {foo}, которая содержит адрес ячейки памяти 1000, но по адресу 1000 ничего особенного не сохраняется. Это означает, чточто вы не можете получить доступ к значению символа, определенного сценарием компоновщика - он не имеет значения - все, что вы можете сделать, это использовать адрес символа, определенного сценарием компоновщика.
Следовательно, когда вы используете определенный в скрипте символ компоновщика в исходном коде, вы всегда должны брать адрес символа и никогда не пытаться использовать его значение.Например, предположим, что вы хотите скопировать содержимое раздела памяти с именем .ROM в раздел с именем .FLASH, а скрипт компоновщика содержит следующие объявления:
start_of_ROM = .ROM;
end_of_ROM = .ROM + sizeof (.ROM);
start_of_FLASH = .FLASH;
Тогда исходный код C для выполнения копирования будетbe:
extern char start_of_ROM, end_of_ROM, start_of_FLASH;
memcpy (& start_of_FLASH, & start_of_ROM, & end_of_ROM - & start_of_ROM);
Обратите внимание на использование операторов "&".Они правильные.