Я пытался добраться, польза держат x86 ассемблер, и задавался вопросом, был ли быстрый-и-короткий эквивалент movl $1, %eax
. Именно тогда я думал, что список идиом, используемых часто на языке, возможно, будет хорошей идеей.
Это могло включать предпочтительное использование xorl %eax, %eax
в противоположность movl $0, %eax
, или testl %eax, %eax
против cmpl $0, %eax
.
О, и любезно отправьте один пример по почте!
на x64:
xor eax, eax
для
xor rax, rax
(первый также неявно очищает верхнюю половину rax
, но имеет меньший код операции)
Можно и как оптимизировать в сборке. Тогда вам нужно будет спросить, для чего вы оптимизируете: размер или скорость? В любом случае, вот моя «идиома», замена xchg
:
xor eax, ebx
xor ebx, eax
xor eax, ebx
Не знаю, считается ли это идиомой, но на большинстве процессоров до i7
movq xmm0, [eax]
movhps xmm0, [eax+8]
или, если SSE3 доступен,
lddqu xmm0, [eax]
быстрее для чтения из невыровненной области памяти, чем
movdqu xmm0, [eax]
Использование SHL
и SHR
для умножения / деление на степень 2
Использование LEA
, например, умножение, например:
lea eax, [ecx+ecx*4]
для EAX = 5 * ECX
Расширение моего комментария:
Для незаметного процессора, такого как Pentium Pro, xorl% eax,% eax
, похоже, зависит от % eax
и, следовательно, должен подождите, пока станет доступным значение этого регистра. У более поздних процессоров фактически есть дополнительная логика для распознавания этой инструкции как не имеющей никаких зависимостей.
Инструкции incl
и decl
устанавливают некоторые флаги, но оставляют другие без изменений. Это наихудшая ситуация, если флаги моделируются как один регистр с целью переупорядочения инструкций: любая инструкция, которая читает флаг после incl
или decl
, должна рассматриваться как зависящая от , включая
или decl
(в случае, если он читает один из флагов, которые устанавливает эта инструкция), а также в предыдущей инструкции, которая устанавливает флаги (в случае, если он читает один из флагов, которые это инструкция не ставит). Решением было бы разделить регистр флагов на два и рассмотреть зависимости с этим более тонким зерном ... но AMD пришла в голову получше и полностью удалила эти инструкции из 64-битного расширения, которое они предложили несколько лет назад.
Что касается ссылок, я нашел их либо в руководствах Intel, для которых бесполезно давать ссылку, потому что они находятся на корпоративном веб-сайте, реорганизуемом каждые шесть месяцев, либо на сайте Агнера Фога: http: // www .agner.org / optimize / # manuals
Еще один (помимо xor
) для
mov eax, 0 ; B800000000h
-
sub eax, eax ; 29C0h
Обоснование: меньший код операции
Вот еще одна интересная «идиома». Надеюсь, все знают, что деление - это большая трата времени даже по сравнению с умножением. Используя небольшую математику, можно умножить на обратную константу вместо деления на нее. Это выходит за рамки хитрых уловок.Например, чтобы разделить на 5:
mov eax, some_number
mov ebx, 3435973837 // 32-bit inverse of 5
mul ebx
Теперь eax был разделен на 5 без использования кода операции медленного div. Вот список полезных констант для бессовестного деления, украденного из http://blogs.msdn.com/dev/archive/2005/12/12/502980.aspx
3 2863311531
5 3435973837
7 3067833783
9 954437177
11 3123612579
13 3303820997
15 4008636143
17 4042322161
Для чисел, не указанных в списке, вы можете нужно сделать сдвиг заранее (разделить на 6, shr 1, затем умножить на обратное 3).
В циклах ...
dec ecx
cmp ecx, -1
jnz Loop
dec ecx
jns Loop
Быстрее и короче.