6.44.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-6.5.0/gcc/Local-Register-Variables.html