Война миров - ассемблер против си

             

IDA Pro за работой


Причем, цикл выровнен по адресам, кратным 10h (команды "LEA ESI,[ESI+0]" и "LEA EDI,[EDI+0]" используются для выравнивания), что с одной стороны хорошо, а с другой — не очень. Начиная с процессоров поколения P6 (к которым, в частности, принадлежит Pentium Pro, Penium-II) и AMD K5, выравнивание циклов требуется только тогда, когда целевой переход попадает на команду, расщепленную двумя линейками кэш-памяти первого уровня, длина которых в зависимости от процессора составляет 32, 64 или даже 256 байт. В противном случае наблюдается существенное снижение быстродействия.

Компилятор MS VC вообще не выравнивает циклы, поэтому их быстродействие зависит от воли случая — попадет ли первая инструкция цикла на "расщепляющий" адрес или… не попадет. Компилятор GCC выравнивает циклы, но по слишком ретивой стратегии, всегда подтягивая их к адресам, кратным 10h. Это хорошо работает на первопнях, но вот на более современных процессорах команды, расходующиеся на выравнивание, занимают лишнее место и впустую съедают производительность (особенно на вложенных циклах, где они выполняются многократно).

Зато, в отличии от своего конкурента, GCC "догадался" использовать команду "MOVZX EAX, AL", только вот _зачем_ она ему понадобилась — не понятно. Команда "MOVZX" пересылает значение из источника в приемник, дополняя его нулями до 16- или 32-бит (в зависимости от разрядности). Но ведь в нашем случае старшие биты регистра EAX _уже_ равны нулю, поскольку компилятор _сам_ обнулил их инструкцией "XOR EAX,EAX". Следовательно, команда "MOVZX EAX,AL" совершенно не нужна и со всей своей очевидностью избыточна.

Интересно, изменилось ли что-нибудь в новых версиях? Компилируем программу с помощью GCC 3.4.2 и смотрим полученный результат:

.text:080484C0             CRC    proc near

.text:080484C0

.text:080484C0             arg_0  = dword ptr  8

.text:080484C0             arg_4  = dword ptr  0Ch

.text:080484C0

.text:080484C0 55          push   ebp

.text:080484C1 89 E5       mov    ebp, esp

.text:080484C3 8B 4D 0C    mov    ecx, [ebp + arg_4]

.text:080484C6 53          push   ebx



.text:080484C7 31 C0       xor    eax, eax

.text:080484C9 8B 5D 08    mov    ebx, [ebp+arg_0]

.text:080484CC 31 D2       xor    edx, edx

.text:080484CE EB 04       jmp    loc_80484D4

.text:080484D0

.text:080484D0       loc_80484D0:

.text:080484D0 02 04 13    add    al, [ebx+edx]

.text:080484D3 42          inc    edx

.text:080484D4

.text:080484D4       loc_80484D4:

.text:080484D4 39 CA       cmp    edx, ecx

.text:080484D6 7C F8       jl     short loc_80484D0

.text:080484D8 0F B6 C0    movzx  eax, al

.text:080484DB F7 D8       neg    eax

.text:080484DD 5B          pop    ebx

.text:080484DE C9          leave

.text:080484DF C3          retn



Содержание раздела