#ассемблер
В листинге дизассемблированного файла имею: .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 случаем?) Видимо, просто запутался очень + не хватает знаний и нормально изложенного материала. Направьте, камрады.
Ответы
Ответ 1
Команда целиком состоит из трех байт: 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, т.к. операция не между регистром/памятью и значением, а между регистром и регистром/памятью.Ответ 2
Сравнение содержимого регистра с числов равноценно вычитанию из регистра этого числа. Т.е. по сути SUB eax 0 и CMP eax 0 равноценны по результату. При совпаднеии числе в результате получается ноль и срабатывает переход JZ В данном случае я думаю, что программист реализовавывл сравнение вычитанием, а CMP поставил слишком "умный" дизассемблер.
Комментариев нет:
Отправить комментарий