Я не забываю видеть способ использовать расширенный gcc встроенный ассемблерный код, чтобы считать значение регистра и сохранить его в переменную C.
Я не могу, хотя ни за что в жизни помнят, как сформировать asm оператор.
Вот способ получить EBX:
int main()
{
int i;
asm("\t movl %%ebx,%0" : "=r"(i));
return i + 1;
}
Результат:
main:
subl $4, %esp
#APP
movl %ebx,%eax
#NO_APP
incl %eax
addl $4, %esp
ret
«= R» (I) - это выходное ограничение, сообщая компилятору о том, что первый вывод (% 0) является реестром, который должен быть помещен в переменной «I». На этом уровне оптимизации (-O5) переменная я никогда не хранятся в памяти, но удерживается в регистре EAX, который также происходит для регистрации реестра возврата.
Я не знаю, о НКУ , но в против, это то, как:
int data = 0;
__asm
{
mov ebx, 30
mov data, ebx
}
cout<<data;
по сути, я переместил данные в EBX
к вашей переменной данные
.
Это будет перемещать указатель стека в переменную SP.
intptr_t sp;
asm ("movl %%esp, %0" : "=r" (sp) );
Просто замените «ESP» с фактическим регистрам, который вы заинтересованы в (но убедитесь, что не потерять %%) и «SP» с вашей переменной.
Примечание редактора: Этот способ использования локальной переменной регистров-асм теперь документирован GCC как «не поддерживается» . Это все еще обычно происходит для работы на GCC, но разрывается с Clang. (Эта формулировка в документации была добавлена после того, как этот ответ был опубликован, я думаю.)
Глобальная версия переменных фиксированной регистрации имеет большую стоимость производительности для 32-битного X86, которая имеет только 7 GP-целочисленных регистров (не подсчитание указатель стека). Это уменьшит, что к 6. Учтитесь только если у вас есть глобальная переменная, что весь ваш код использует в значительной степени.
Идет в другое направление, чем другие ответы, так как я не уверен, что вы хотите.
Руководство GCC § 5.40 Переменные в указанных регистрах
Регистрация Int * Foo ASM («A5»);
Здесь
A5
a5
- это имя реестра, которое следует использовать ...Естественно, что имя регистра - зависит от процессора, но это не проблема, поскольку определенные регистры чаще всего полезны с явными Инструкции ассемблера (см. расширенные ASM ). Обе эти вещи, как правило, требуют, чтобы вы окружали свою программу в соответствии с типом ЦП.
Определение такой переменной регистров не оставляет регистр; Он остается доступным для других применений в местах, где контроль потока определяет значение переменной не вживую.
Руководство GCC § 3.18 Опции для конвенций генерации кода
-FIXED-
REGОбратите внимание на регистр с именем Reg как фиксированный регистр; Сгенерированный код никогда не должен ссылаться на него (за исключением, возможно, как указатель стека, указатель кадра или в какой-либо другой фиксированной роли).
Это может реплицировать ответ Ричарда более проще,
int main() {
register int i asm("ebx");
return i + 1;
}
, хотя это довольно бессмысленно, так как вы не имеете представления, что в EBX
регистр.
Если вы объединили эти два, составление этого с помощью GCC -FIFICED-EBX
,
#include <stdio.h>
register int counter asm("ebx");
void check(int n) {
if (!(n % 2 && n % 3 && n % 5)) counter++;
}
int main() {
int i;
counter = 0;
for (i = 1; i <= 100; i++) check(i);
printf("%d Hamming numbers between 1 and 100\n", counter);
return 0;
}
Вы можете убедиться, что переменная C всегда использует в реестре для быстрого доступа, а также не будет нагруженными другой генерированный код. (Устранено, EBX
- это Callee-Sake под обычными призывами X86, поэтому, даже если он будет нагруженными звонками на другие функции, скомпилированные без -FFIXED - *
, он должен быть восстановлен тоже. )
С другой стороны, это определенно не портативно, и обычно не является преимуществом производительности, так как вы ограничиваете свободу компилятора.
Из самого GCC документов: http://gcc.gnu.org/onlinedocs/gnu.org/onlinedocs/gccc/extended-asm.html