На x86 инструкция NOP
равна XCHG AX, AX
2 мнемонические инструкции собираются в один и тот же двоичный код операции. (На самом деле, я полагаю, что ассемблер мог бы использовать любой xchg
регистра с самим собой, но, насколько я знаю, AX
или EAX
- это то, что обычно используется для nop
.
xchg ax, ax
обладает свойствами изменения значений без регистров и без флагов (эй, это не операция!).
Редактировать (в ответ на комментарий Анона.):
Ах да, теперь я помню, что есть несколько кодировок для инструкции xchg
. Некоторые принимают набор битов mod / r / m (как и многие инструкции по архитектуре 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
.
Прошло много времени с тех пор, как я провел детальную работу на ассемблере, поэтому есть вероятность, что я ошибаюсь хотя бы в одном подсчете здесь ...