6.43.5.2 Определение регистров для локальных переменных
Вы можете определить локальную переменную регистра с указанным регистром следующим образом:
register int *foo asm ("a5");
Здесь a5 — имя регистра, которое следует использовать. Обратите внимание, что это тот же синтаксис, что и для определения глобальных переменных регистров, но для локальной переменной он находится внутри функции.
Естественно, имя регистра зависит от процессора, но это не проблема, так как конкретные регистры чаще всего полезны с явными инструкциями ассемблера (см. Расширенный ассемблер). Оба эти момента обычно требуют условного кода для разных типов процессоров.
Кроме того, операционные системы на одном типе процессора могут по-разному называть регистры; в таком случае вам потребуются дополнительные условные операторы. Например, некоторые операционные системы для процессоров 68000 называют этот регистр %a5.
Определение такой переменной-регистра не резервирует регистр; он остается доступным для других применений в местах, где управление потоком определяет, что значение переменной не активно.
Этот вариант не гарантирует, что GCC сгенерирует код, в котором эта переменная постоянно находится в указанном вами регистре. Вы не можете написать явную ссылку на этот регистр в части шаблона инструкции ассемблера в инструкции asm и предполагать, что она всегда относится к этой переменной. Однако использование переменной в качестве операнда входных или выходных данных для asm гарантирует, что указанный регистр используется для этого операнда. Подробнее см. Расширенный ассемблер.
Присваивания локальным переменным регистров могут быть удалены, если они, согласно анализу потока данных, становятся мёртвыми. Ссылки на локальные переменные регистров могут быть удалены, перемещены или упрощены.
Как и в случае с глобальными переменными регистров, рекомендуется выбирать регистр, который обычно сохраняется и восстанавливается при вызовах функций на вашей машине, чтобы библиотечные функции не перезаписывали его.
Иногда при написании встроенного кода 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));
Предыдущая: Глобальные переменные регистров, Вверх: Явные переменные регистров [Оглавление][Индекс]
© Free Software Foundation
Licensed under the GNU Free Documentation License, Version 1.3.
https://gcc.gnu.org/onlinedocs/gcc-5.5.0/gcc/Local-Reg-Vars.html