Не ясно, зачем вам нужно помещать содержимое определенного регистра в переменную, учитывая изменчивый характер большинства из них.
GNU C имеет ограничения специфического регистра только для оригинального 8регистры, как "=S"(rsi)
.Для r8..r15
единственным вариантом (во избежание необходимости инструкции mov
внутри оператора asm
) является переменная register-asm.
register long long my_var __asm__ ("r8");
__asm__ ("" :"=r"(my_var)); // guaranteed that r chooses r8
Возможно, вы захотите использовать дополнительный ввод / выводограничение для управления , где вы выбираете значение r8
.(Например, "+rm"(some_other_var)
сделает этот оператор asm частью цепочки зависимостей данных в вашей функции, но это также предотвратит постоянное распространение и другие оптимизации.) asm volatile
может помочь в управлении упорядочением, но это не гарантируется.
Это иногда работает, чтобы опустить оператор __asm__ ("" :"=r"(my_var));
, используя регистр local в качестве операнда, но он гарантированно сработает, если вы его используете: https://gcc.gnu.org/onlinedocs/gcc/Local-Register-Variables.html#Local-Register-Variables. (И посмотрите обсуждение в комментариях к предыдущей версии этого ответа, в котором предлагалось, что вы можете пропустить эту часть.) Это не делает ваш код медленнее, поэтому не пропускайте эту часть, чтобы убедиться, что ваш код в целом безопасен.
Единственное поддерживаемое использование этой функции - указание регистров для операндов ввода и вывода при вызове Extended asm (см. Extended Asm).Это может быть необходимо, если ограничения для конкретной машины не обеспечивают достаточного контроля для выбора желаемого регистра.Чтобы ввести операнд в регистр, создайте локальную переменную и укажите имя регистра после объявления переменной.Затем используйте локальную переменную для операнда asm и укажите любую букву ограничения, которая соответствует регистру
PS Это расширение GCC, которое может быть не переносимым, но должно быть доступно на всех компиляторах, поддерживающих GNU Cвстроенный синтаксис asm.
gcc вообще не имеет ограничений на конкретные регистры для некоторых архитектур, таких как ARM, так что этот метод является единственным способом для редких случаев, когда вы хотите принудительно использовать определенные регистры для операндов ввода или вывода.
Пример:
int get_r8d(void) {
register long long my_var __asm__ ("r8");
__asm__ ("" :"=r"(my_var)); // guaranteed that r chooses r8
return my_var * 2; // do something interesting with the value
}
, скомпилированный с gcc7.3 -O3 в проводнике компилятора Godbolt
get_r8d():
lea eax, [r8+r8] # gcc can use it directly without a MOV first
ret