2010-01-25 4 views
25

Я просматривал disassmbly моей программы (так как он упал), и заметил многоПочему использование Visual Studio XCHG топор, топор

xchg ax, ax 

Я гугл его и узнал, что это по существу NOP, но почему визуальная студия делает xchg вместо noop?

Приложение 64-битное приложение C# .NET3.5, составленный визуальной студии

+1

следующие байты, связанные с этими инструкциями: nop должен быть hex 90. is xchg ax, ax 2-байтная инструкция? –

+0

Это оказалось вопросом с немного более нюансом, чем я изначально думал (или помнил в любом случае). –

+0

эй ты можешь рассказать мне, как смотреть на ассемблерный код, подобный твоему. я хотел бы видеть, как простой prgoram преобразуется в сборку. спасибо – masfenix

ответ

33

На x86 NOP инструкция являетсяXCHG AX, AX

В 2 мнемонические инструкции по сборке в том же двоичном op- код. (На самом деле, я полагаю, что ассемблер мог использовать любой регистр xchg с самим собой, но AX или EAX - это то, что обычно используется для nop, насколько я знаю).

xchg ax, ax имеет свойства изменения значений регистра и изменения флагов (эй - это не операция!).


Редактировать (в ответ на замечание Anon.):

О порядке - теперь я помню, есть несколько кодировок для xchg инструкции. Некоторые берут набор мод/г/м бит (как и многие инструкции архитектуры Intel x86), которые указывают источник и назначение. Эти кодировки занимают более одного байта. Существует также специальная кодировка, которая использует один байт и обменивает регистр общего назначения с (E)AX. Если указанный регистр также равен (E)AX, то вы имеете однобайтную инструкцию NOP. вы также можете указать, что (E)AX обмениваться с самим собой, используя более крупный вариант инструкции xchg.

Я предполагаю, что MSVC использует несколько версии байтов xchg с (E)AX в качестве источника и назначения, когда он хочет, чтобы жевать более чем один байт без всякой операции - она ​​занимает такое же число циклов как один байт xchg , но использует больше места. При разборке вы не увидите многократный байт xchg, декодированный как NOP, даже если результат тот же.

В частности xchg eax, eax или nop может быть закодирован как опкодами 0x90 или 0x87 0xc0 в зависимости от того, хотите ли вы его использовать 1 или 2 байта. Разборщик Visual Studio (и, возможно, другие) будет декодировать код операции 0x90 в качестве инструкции NOP и будет декодировать код операции 0x87 0xc0 как xchg eax, eax.

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

+0

Тогда почему я тоже вижу nop? – Malfist

+0

Это был бы дизассемблер, умный (или немой, в зависимости от того, что вы хотели этого сделать). Вы видите оба декодера, используя один и тот же дизассемблер? Это может быть интересно посмотреть. –

+0

Это дизассемблер визуальной студии ... – Malfist

8

xchg ax,ax и nop фактически та же команда, они отображаются на тот же код операции (0x90 iirc). Это нормально, xchg ax,axis a No-Op. Почему следует тратить лишние кодировки кода операции с инструкциями, которые ничего не делают?

Вопрос: почему вы видите как мнемоническую печать.Я думаю, это просто недостаток в вашей разборке, нет двоичной разницы.

+1

0x90 не 90 ... .. – Earlz

+0

Вопрос о том, следует ли обрабатывать коды кодов операций с инструкциями do-nothing, вызывает некоторые интересные проблемы, особенно в архитектурах, которые указаны для улавливания недействительных инструкций. С одной стороны, если значительная часть пространства операций opcode используется функционально-идентичными инструкциями, запрещение использования всего, кроме одного такого кодирования, сделает остальные доступными для будущих операций. С другой стороны, это может сделать некоторые сценарии генерации динамического кода более сложными, и если предполагается, что недействительные коды операций оказались в ловушке, для их ловушки требуется дополнительное оборудование. – supercat

+0

@supercat: Это немного отличается от того, что просто отклоняется, чтобы определить * еще один * код операции, который ничего не делает, не так ли? – SamB

4

MSVC помещает NOP в скомпилированный код для отладочных сборников, как правило. Это позволяет редактировать & Продолжить работу.

5

Фактически, xchg ax,ax - это то, как MS разбирает «66 90». 66 - это переопределение размера операнда, поэтому он предположительно работает на ax вместо eax. Тем не менее, CPU все еще выполняет его как nop. Префикс 66 используется здесь, чтобы сделать команду двумя байтами в размере, обычно для целей выравнивания.

+0

есть также много других NOP с разными размерами, и компилятор может выбрать тот, который подходит лучше всего http://stackoverflow.com/ а/12564044/995714 –

2

Я не знаю, связано ли это с вопросом, но многие функции Windows начинаются с MOV EDI, EDI. Это также 2 байта NOP. Два байта NOP полезны для кода hotpatch, потому что вы можете спокойно заменить его коротким JMP.

Ссылка: http://blogs.msdn.com/b/oldnewthing/archive/2011/09/21/10214405.aspx

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