2009-09-08 2 views
87

xor eax, eax всегда будет устанавливать eax в ноль, не так ли? Итак, почему MSVC++ иногда помещает его в код моего исполняемого файла? Является ли более эффективным то, что mov eax, 0?Какова цель XORing регистрации с собой?

012B1002 in   al,dx 
012B1003 push  ecx 
    int i = 5; 
012B1004 mov   dword ptr [i],5 
    return 0; 
012B100B xor   eax,eax 

Также, что делать in al, dx?

+13

это очень маловероятно, что MSVC++ компилятор действительно испускает команду «in». Вероятно, вы разобрались с неправильным адресом/неправильным выравниванием. – newgre

+1

Я просто использую дизассемблер в режиме отладки. –

+4

Да, настоящие инструкции начинаются на несколько байт раньше. Не существует С-эквивалента инструкции «in» и чтения из 16-битного порта ввода-вывода и перезаписывания результата несколько инструкций позже является очень маловероятной сгенерированной последовательностью команд. – hirschhornsalz

ответ

120

Да, это более эффективно.

Опкода короче mov eax, 0, только 2 байта, а процессор распознает специальный случай, и рассматривает его как mov eax, 0 без ложного зависимости чтения на eax, поэтому время выполнения такого же.

+4

Бинго. Это одна из нескольких идиом, которые говорят процессору обходить обычную логику зависимостей. –

+32

«Процессор регонизирует специальный случай и рассматривает его как« mov eax, 0 »без ложной зависимости чтения от eax, поэтому время выполнения такое же». Процессор на самом деле еще лучше: он просто выполняет переименование реестра внутри, и даже не делает ничего с 'eax'. – kquinn

+1

Собственно, на большой картинке это быстрее. Есть меньше байтов, которые нужно извлечь из ОЗУ. –

12

xor eax, eax - это более быстрый способ установить eax на ноль. Это происходит потому, что вы возвращаете ноль.

Инструкция in делает вещи с портами ввода/вывода. В основном считывание слова данных из порта указано dx и его хранение в al. Непонятно, почему это происходит здесь. Вот reference, который, кажется, объясняет это подробно.

+8

«Инструкция в инструкции работает с портами I \ O». Но в этом случае это, вероятно, «артефакт», вызванный отладчиком, начинающим разборку в середине инструкции. –

+5

Согласен. Но все-таки, вот что он делает. –

+1

@Abel Почему вы переименовали все мнемоники и зарегистрировали имена? Это, по меньшей мере, нетрадиционно. Как вы можете видеть в коде OP, большинство современных ассемблеров и дизассемблеров используют все-строчную орфографию. –

0

Операция XOR действительно очень быстро. Если результатом является установка регистра на ноль, компилятор будет делать это быстрее всего, как он знает. Операция бит, такая как XOR, может принимать только один цикл ЦП, тогда как копия (из одного регистра в другой) может принимать небольшую часть.

Часто авторы компилятора даже имеют разные типы поведения, учитывая разные целевые архитектуры процессора.

24

Также следует избегать 0s при компиляции в качестве кода оболочки для использования переполнения буфера и т. Д. Почему бы избежать 0? Ну, 0 представляет конец строки в c/C++, и код оболочки будет усечен, если среднее значение для использования является функцией обработки строк или тому подобное.

Btw im ссылаясь на исходный вопрос: «Любая причина для« xor eax, eax »?» не то, что делает компилятор MSVC++.

Поскольку есть некоторые дебаты в комментариях о том, как это уместно в реальном мире, см this article и this section on Wikipedia.

+9

Для меня это звучит глупо. В вашем коде обязательно будут нулевые байты, поэтому я не вижу, как еще один будет иметь большое значение. В любом случае, кто заботится, можете ли вы обмануть программу в чтение кода в качестве данных. Реальная проблема заключается в выполнении данных в виде кода. –

+21

Кому это нужно? Хакеры делают это, и, по-видимому, большую часть индустрии компьютерной безопасности. Пожалуйста, просветите себя, прежде чем голосуете о чем-то. Здесь вы можете найти дополнительные ссылки [Искусство эксплуатации - Глава 0x2a0] [1], а также образец кода оболочки, который не содержит 0s. [1] [http://books.google.es/books?id=P8ijosP6ti4C&lpg=PP1&dq=the%20art%20of%20exploitation&pg=PA84#v=onepage&q=&f=false] –

+2

Это возвращает воспоминания из TRS -80. Некоторые из нас встроят процедуры сборки внутри строк BASIC. Было несколько символов, которые абсолютно не могли появиться в исходном коде, не нарушая его, и поэтому любая такая процедура должна была быть тщательно оптимизирована, чтобы избежать использования этих символов. –

0

Другой причиной использовать XOR reg, reg или XORPS reg, reg является разорвать цепи зависимостей, это позволяет процессору оптимизировать параллельно выполнение команд сборки более эффективно (даже при этом оно добавляет еще несколько инструкций по пропускной способности).

+1

Это дает ему преимущество перед 'AND reg, 0', но не над' MOV reg, 0'. Дефрагментация прерывания - это особый случай для 'xor', но всегда случай для' mov'. Это не упоминается, что приводит к случайным путаницам у людей, которые думают, что «mov» имеет ложную зависимость от старого значения, которое перезаписывается. Но, конечно, нет. –

+0

любая ссылка для этого, я не знаю, как разлом разлома на моей голове. – Quonux

+0

Все, что перезаписывает пункт назначения, в зависимости от этого, прерывает цепочку dep. например каждая инструкция из 3-операндов 'op dest, src1, src2' (например,' VPSHUFB dest, src1, src2' или 'lea eax, [rbx + 2 * rdx]') разбивает цепочку dep на старое значение 'dest'. Это заметно только тогда, когда есть ложная зависимость от старого значения: как «mov ax, bx', который (на AMD/Silvermont/P4, но не P6/SnB) имеет ложное отключение по старому значению' eax', даже если вы никогда не читаете 'eax'. В Intel большое примечание состоит в том, что ['popcnt/lzcnt/tzcnt' имеет ложное отпечаток на их выходе] (http://stackoverflow.com/a/25089720/224132) –

-6

исключающие часто используются для шифрования коды, например

 mov eax,[ecx+ValueHere] 
     xor eax,[ecx+ValueHere] 
     mov [ebx+ValueHere],esi 
     xor esi,[esp+ValueHere] 
     pop edi 
     mov [ebx+ValueHere],esi 

Инструкция XOR соединяет два значения с помощью логического исключающего ИЛИ помните OR используется включительно ИЛИ Чтобы понять XOR лучше, рассмотрят эти два двоичных значения:

 1001010110 
     0101001101 

Если вы ИЛИ им, результат равен 1100011011. Когда два бита друг над другом равны, результирующий бит равен 0. Остается только один бит: 1. Вы можете использовать calc.exe для вычисления XOR.

+7

Уверен, но об этом не говорится, речь идет о «xor с собой» – harold

-1

от OP> любая причина для дела «xor eax, eax» return 0; 012B100B исключающее EAX, EAX RET < - OP не показывает это

XOR EAX, EAX просто 0 'из регистра EAX, она выполняется быстрее, чем MOV EAX, $ 0 и не нужно получить непосредственные данные 0 загрузить в EAX

это совершенно очевидно, что это «возвращение 0», что MSVC оптимизирует EAX это регистр используется для возврата значения из функции в MSVC

+1

Этот ответ не добавляет ничего, чего нет в других ответах. И да, все x86 ABI используют 'eax' /' rax' как регистр для возвращаемых значений. Кроме того, немедленные данные не нужно извлекать, кроме как в качестве предпосылки для декодирования команд. xor короче mov и даже оставляет больше свободного места в строке кэша uop, в которой он находится, но ни один из этих эффектов не описывается как «не требуется». –

Смежные вопросы