6.43.5.1 Объявление глобальных регистровых переменных
Вы можете объявить глобальную регистровую переменную в GNU C так:
register int *foo asm ("a5");
Здесь a5 — имя регистра, который следует использовать. Выберите регистр, который обычно сохраняется и восстанавливается вызовами функций на вашей машине, чтобы библиотечные функции не перезаписывали его.
Естественно, имя регистра зависит от процессора, поэтому вам нужно условным образом разбить вашу программу по типу процессора. Регистр a5 — хороший выбор для переменной типа указатель на 68000. На машинах с оконными регистрами убедитесь, что вы выбрали «глобальный» регистр, который не затрагивается механизмом вызова функций.
Кроме того, разные операционные системы на одном и том же процессоре могут по-разному называть регистры; тогда вам понадобятся дополнительные условные выражения. Например, некоторые операционные системы для 68000 называют этот регистр %a5.
В конечном итоге может появиться способ попросить компилятор выбрать регистр автоматически, но сначала нам нужно выяснить, как он должен выбирать и как позволить вам направить выбор. Явного решения нет.
Объявление глобальной регистровой переменной в определённом регистре полностью резервирует этот регистр для этого использования, по крайней мере, в рамках текущей компиляции. Регистр не выделяется для каких-либо других целей в функциях текущей компиляции и не сохраняется и не восстанавливается этими функциями. Записи в этот регистр никогда не удаляются, даже если они кажутся мёртвыми, но ссылки могут быть удалены, перемещены или упрощены.
Доступ к глобальным регистровым переменным из обработчиков сигналов или из более чем одной потоковой нити не безопасен, поскольку библиотечные функции системы могут временно использовать регистр для других целей (если вы не перекомпилируете их специально для конкретной задачи).
Небезопасно для одной функции, использующей глобальную регистровую переменную, вызывать другую такую функцию foo через третью функцию lose, которая скомпилирована без знания этой переменной (т. е. в другом файле исходного кода, в котором переменная не объявлена). Это потому, что lose может сохранить регистр и поместить туда другое значение. Например, вы не можете ожидать, что глобальная регистровая переменная будет доступна в функции сравнения, которую вы передаёте qsort, так как qsort могла поместить что-то другое в этот регистр. (Если вы готовы перекомпилировать qsort с той же глобальной регистровой переменной, вы можете решить эту проблему.)
Если вы хотите перекомпилировать qsort или другие файлы исходного кода, которые фактически не используют вашу глобальную регистровую переменную, чтобы они не использовали этот регистр для каких-либо других целей, то достаточно указать опцию компилятора -ffixed-reg. Вам не нужно фактически добавлять объявление глобального регистра в их исходный код.
Функция, которая может изменить значение глобальной регистровой переменной, не может безопасно вызываться из функции, скомпилированной без этой переменной, поскольку она может перезаписать значение, которое вызывающий ожидает найти при возврате. Поэтому функция, являющаяся точкой входа в часть программы, использующей глобальную регистровую переменную, должна явно сохранить и восстановить значение, принадлежащее её вызывающей функции.
На большинстве машин longjmp восстанавливает для каждой глобальной регистровой переменной значение, которое она имела в момент setjmp. Однако на некоторых машинах longjmp не изменяет значение глобальных регистровых переменных. Чтобы быть переносимым, функция, вызвавшая setjmp, должна принять другие меры для сохранения значений глобальных регистровых переменных и для их восстановления в longjmp. Таким образом, происходит то же самое независимо от того, что делает longjmp.
Все объявления глобальных регистровых переменных должны предшествовать всем определениям функций. Если такое объявление могло бы появиться после определений функций, объявление было бы слишком поздним, чтобы предотвратить использование регистра для других целей в предыдущих функциях.
Глобальные регистровые переменные не могут иметь начальных значений, так как исполняемый файл не имеет средств для предоставления начального содержимого для регистра.
На SPARC есть сообщения о том, что регистры g3...g7 подходят, но некоторые библиотечные функции, такие как getwd, а также подпрограммы для деления и остатка, изменяют g3 и g4. g1 и g2 являются локальными временными переменными.
На 68000 регистры a2...a5 и d2...d7 должны подходить. Конечно, не стоит использовать более нескольких из них.
Далее: Локальные переменные регистров, Наверх: Явные переменные регистров [Содержание][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-5.5.0/gcc/Global-Reg-Vars.html