В листинге дизассемблированного файла имею:
.text:00401296 cmp eax, 0 .text:00401299
jz short loc_4012B0
Пронзив исполняемый файл hex-редактором, лечу на адрес 696 (адрес первой команды cmp) и там смотрю такие байты:
83 F8 00
Пытаюсь разобраться..
Топаю на http://sparksandflames.com/files/x86InstructionChart.html
Там мне подсказывают, что
83 - SUB Ev Ib...
Вычитание? Не сравнение? В самой программе он работает как сравнение.. Привычный мир рушится...
Вопросы:
Почему 83 - вычитание, а не сравнение или опкод "модифицируется" каким-то спец. байтом?
Как вычислить опкод команды mov eax,eax (не 89 F8 00 случаем?).
Как в этом случае будет влиять на ход программы байт mod r/m?
Или xor eax,eax? (не 35 F8 F8 случаем?)
Видимо, просто запутался очень + не хватает знаний и нормально изложенного материала. Направьте, камрады.
Ответ
Команда целиком состоит из трех байт: 83 F8 00
83h - это только часть опкода. Как уже заметил VladD, это может соответствовать командам ADD, OR, ADC, SBB, AND, SUB, XOR и CMP. Чтобы понять, что это за команда фактически, нужно смотреть следующий байт (F8h). Это байт MOD R/M, состоящих из 3 полей (по 2, 3, 3 бита):
F8 == 11 111 000
По второму полю этого байта можно определить конкретную команду (хотя, обычно оно отвечает за один из операндов) - как раз из списка ADD, OR, ADC, SBB, AND, SUB, XOR и CMP. Первое поле показывает, что второй (на самом деле первый) операнд - это регистр (или адрес в памяти, но в данном случае это все же регистр). 000 - это, собственно, код регистра, EAX.
Третий байт является вторым операндом команды - 0.
Больше по этой теме можно почитать, например, здесь: Крис Касперски - Дизассемблирование в уме
А еще лучше - читать руководства от Intel в оригинале
Используемый вами справочник очень не полный.
Как вычислить опкод команды mov eax,eax?
Скомпилировать и посмотреть, это наиболее надежный способ, или смотреть в руководстве от Intel.
Или xor eax,eax? (не 35 F8 F8 случаем?)
Скорее 31 C0. Второй байт - байт mod r/m, там просто указывается, что производится операция производится между регистром и регистром, и коды самих регистров:
11 000 000
(000 в обоих случаях - обозначение регистра eax). А первый байт - не 35h, а 31h, т.к. операция не между регистром/памятью и значением, а между регистром и регистром/памятью.