Иерархии сборки x86

Я пытаюсь хорошо разбираться в ассемблере x86 и задавался вопросом, был ли быстрый и короткий эквивалент movl $1, %eax. Это, когда я думал, что список идиом, часто используемых на этом языке, может быть хорошей идеей.

Это может включать в себя предпочтительное использование xorl %eax, %eax в отличие от movl $0, %eax или testl %eax, %eax от cmpl $0, %eax.

О, и любезно отправьте один пример за сообщение!

Ответы

Ответ 1

Вот еще одна интересная "идиома". Надеюсь, все знают, что разделение - это большая потеря времени даже по сравнению с умножением. Используя небольшую математику, можно умножить на инверсию константы, а не на ее деление. Это выходит за рамки трюков. Например, чтобы разделить на 5:

mov eax, some_number
mov ebx, 3435973837    // 32-bit inverse of 5
mul ebx

Теперь eax был разделен на 5 без использования медленного кода операции div. Вот список полезных констант для раздела бесстыдных украденных из http://blogs.msdn.com/devdev/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).

Ответ 2

Использование LEA для, например, умножение, например:

lea eax, [ecx+ecx*4]   

для EAX = 5 * ECX

Ответ 3

на x64:

xor eax, eax 

для

xor rax, rax

(первый также неявно очищает верхнюю половину rax, но имеет меньший код операции)

Ответ 4

Вы можете как и как оптимизировать сборку. Тогда вы должны спросить, для чего вы оптимизируете: размер или скорость? Во всяком случае, здесь моя "идиома", замена для xchg:

xor eax, ebx
xor ebx, eax
xor eax, ebx

Ответ 5

Расширение моего комментария:

Для нескромного процессора, такого как Pentium Pro, xorl %eax, %eax, похоже, имеет зависимость от %eax и, следовательно, должен дождаться, когда будет доступно значение этого регистра. Более поздние процессоры фактически имеют дополнительную логику, чтобы распознать эту инструкцию как не имеющую зависимости.

В инструкциях incl и decl устанавливаются некоторые флаги, но остальные остаются неизменными. Это худшая ситуация, если флаги моделируются как один регистр для переупорядочения команд: любая инструкция, которая считывает флаг после incl или decl, должна рассматриваться как зависящая от incl или decl ( в случае, если он читает один из флагов, который устанавливает эта инструкция), а также в предыдущей инструкции, устанавливающей флаги (в случае, если он читает один из флагов, который эта инструкция не устанавливает). Решение состояло бы в том, чтобы разделить регистр флагов на два и рассмотреть зависимости с этим более тонким зерном... но у AMD была лучшая идея и полностью удалены эти инструкции из 64-битного расширения, которое они предложили несколько лет назад.

Что касается ссылок, я нашел это либо в руководствах Intel, для которых бесполезно предоставлять ссылку, потому что они находятся на корпоративном веб-сайте, который реорганизован каждые шесть месяцев, или на сайте Agner Fog: http://www.agner.org/optimize/#manuals

Ответ 6

В цикле...

  dec     ecx 
  cmp     ecx, -1       
  jnz     Loop              

является

  dec     ecx  
  jns     Loop 

Быстрее и короче.

Ответ 7

Используя SHL и SHR для умножения/деления на мощность 2

Ответ 8

Другой (помимо xor) для

mov eax, 0   ; B800000000h

есть

sub eax, eax ; 29C0h

Обоснование: меньший код операции

Ответ 9

Не знаю, считается ли это как идиома, но на большинстве процессоров до i7

movq xmm0, [eax]
movhps xmm0, [eax+8]

или, если SSE3 доступен,

lddqu xmm0, [eax]

быстрее считываются из неизолированной ячейки памяти, чем

movdqu xmm0, [eax]