6.45.5.2 Указание регистров для локальных переменных
Вы можете определить локальную переменную-регистр и связать её со специфическим регистром следующим образом:
register int *foo asm ("r12");
Здесь r12 — имя регистра, которое следует использовать. Обратите внимание, что это тот же синтаксис, что и для определения глобальных переменных-регистров, но для локальной переменной объявление находится внутри функции. Ключевое слово register обязательно и не может быть комбинировано с static. Имя регистра должно быть допустимым именем регистра для целевой платформы.
Как и в случае с глобальными переменными-регистрами, рекомендуется выбирать регистр, который обычно сохраняется и восстанавливается вызовами функций на вашей машине, чтобы вызовы библиотечных процедур не перезаписывали его.
Единственное поддерживаемое использование этой функции — указание регистров для операндов ввода и вывода при вызове Расширенной asm (см. Расширенное Ассемблерное Язык). Это может потребоваться, если ограничения для конкретной машины не обеспечивают достаточного управления для выбора нужного регистра. Для принудительного помещения операнда в регистр создайте локальную переменную и укажите имя регистра после объявления переменной. Затем используйте локальную переменную в качестве операнда asm и укажите любую букву ограничения, соответствующую регистру:
register int *p1 asm ("r0") = …;
register int *p2 asm ("r1") = …;
register int *result asm ("r0");
asm ("sysint" : "=r" (result) : "0" (p1), "r" (p2));
Предупреждение: В приведенном выше примере учтите, что регистр (например, r0) может быть перезаписан вызывающей процедурой последующим кодом, включая вызовы функций и библиотечные вызовы для арифметических операций над другими переменными (например, инициализация p2). В этом случае используйте временные переменные для выражений между присваиваниями регистров:
int t1 = …;
register int *p1 asm ("r0") = …;
register int *p2 asm ("r1") = t1;
register int *result asm ("r0");
asm ("sysint" : "=r" (result) : "0" (p1), "r" (p2));
Определение переменной-регистра не резервирует регистр. Помимо вызова Расширенной asm, содержимое указанного регистра не гарантируется. По этой причине следующие использования явным образом не поддерживаются. Если они кажутся работающими, это просто случайность, и они могут перестать работать должным образом из-за (кажущихся) несвязанных изменений в окружающем коде или даже незначительных изменений в оптимизации будущей версии gcc:
- Передача параметров в или из Базового
asm - Передача параметров в или из Расширенного
asmбез использования операндов ввода или вывода. - Передача параметров в или из процедур, написанных на ассемблере (или других языках), использующих нестандартные соглашения о вызовах.
Некоторые разработчики используют локальные переменные-регистры в попытке улучшить распределение регистров gcc, особенно в крупных функциях. В этом случае имя регистра фактически является подсказкой для распределителя регистров. Хотя в некоторых случаях это может генерировать более эффективный код, улучшения зависят от прихотей распределителя/оптимизаторов. Поскольку нет гарантии, что ваши улучшения не будут потеряны, это использование локальных переменных-регистров не рекомендуется.
На платформе MIPS есть связанное использование локальных переменных-регистров с немного другими характеристиками (см. Определение специфики сопроцессоров для целей MIPS в GNU Compiler Collection (GCC) Internals).
Предыдущее: Глобальные переменные-регистры, Далее: Явные переменные-регистры [Оглавление][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-8.5.0/gcc/Local-Register-Variables.html