Нет, встроенный шаблон asm должен быть постоянным времени компиляции , поэтому ассемблер может собрать его в машинный код.
Если вам нужен гибкий шаблон, который вы изменяете при запускевремя, это называется JIT-компиляцией или генерацией кода.Обычно вы генерируете машинный код напрямую, а не исходный текст на ассемблере, который вы передаете ассемблеру.
Например, посмотрите этот полный пример, который генерирует функцию, состоящую из переменного числа dec eax
инструкций изатем выполняет его. Код гольфа: повторяющийся счетчик байтов
Кстати, dec eax
работает на 1 за такт на всех современных процессорах x86, в отличие от NOP, который работает на 4 за такт или, возможно, 5 на Райзене.См. http://agner.org/optimize/.
Лучшим выбором для небольшой задержки может быть инструкция pause
или цепочка зависимостей некоторого переменного числа imul
инструкций, или, возможно, sqrtps
, заканчивающаяся lfence
блокировать выполнение не по порядку (по крайней мере, на процессорах Intel).Я не проверял руководства AMD, чтобы убедиться, что lfence
задокументирован как препятствие для выполнения, но Agner Fog сообщает, что он может работать со скоростью 4 в час на Райзене.
Но на самом деле, вы, вероятно,не нужно JIT-код вообще.Для одноразового эксперимента, который должен работать только на одной или нескольких системах, взломайте цикл задержки с помощью чего-то вроде
for (int i=0 ; i<delay_count ; i++) {
asm volatile("" : "r" (i)); // defeat optimization
}
Это заставит компилятор иметь счетчик цикла в регистре на каждой итерации, поэтому он не может оптимизировать цикл или превратить его в умножение.Вы должны получить сгенерированный компилятором asm как delayloop: dec eax; jnz delayloop
.Возможно, вы захотите поставить _mm_lfence()
после цикла.