У меня 32-битный код операции: FF 35 0E 20 40 00
. Кто-нибудь знает хорошую таблицу OpCode, которая дает ответ на этот вопрос? (Я знаю, что могу использовать дизассемблер, но я хотел бы знать, как определить это с помощью таблицы кодов операций). Я нашел эту веб-страницу, но есть 7 различных решений для FF
. Я не понимаю.
что делает код операции FF350E204000?
Ответы (2)
Вы ищете не в том месте. Вам следует поискать это в официальной документации Intel или AMD.
Appendix A Opcode Map
из Vol 2B
из Intel® 64 and IA-32 Architectures Software Developer’s Manual Combined Volumes: 1, 2A, 2B, 3A and 3B
говорит, что FF
это INC/DEC Grp5
1A
.
Table A-6 Opcode Extensions for One- and Two-byte Opcodes by Group Number
из Vol 2B
говорит _9 _ / _ 10_ либо INC
, DEC
, CALLN
, CALLF
, JMPN
, JMPF
, PUSH
, в зависимости от битов с 5 по 3 байта ModR/M
, следующего за ним. (0x35 >> 3) & 7 = 6 или 110 в двоичном формате. Итак, это PUSH Ev
.
Chapter 2 Instruction Format
из Vol 2A
объясняет, из каких частей состоит инструкция, включая те ModR/M
байта, а какие нет.
Appendix A Using Opcode Tables
из Vol 2B
сообщает вам для E
:
Байт ModR / M следует за кодом операции и определяет операнд. Операнд - это регистр общего назначения или адрес памяти. Если это адрес памяти, адрес вычисляется из сегментного регистра и любого из следующих значений: базовый регистр, индексный регистр, коэффициент масштабирования, смещение.
Это также говорит вам для v
:
Слово, двойное слово или четверное слово (в 64-битном режиме), в зависимости от атрибута размера операнда.
Итак, вы знаете, что Ev
означает регистр или операнд памяти, и поскольку это для 32-битного кода и нет префиксов команд, размер операнда составляет 32 бита. Итак, Ev
32-битный регистр или 32-битная переменная в памяти.
Теперь нужно до конца вычислить оставшиеся байты от ModR / M.
Посмотрите на Figure 2-1. Intel 64 and IA-32 Architectures Instruction Format
из Vol 2A
. Он сообщает вам, что в ModR/M
= 0x35:
Mod
= 00 (двоичный) Reg
= 110 (двоичный; мы извлекали эти 3 бита раньше) R/M
= 101 (двоичный)
Table 2-2. 32-Bit Addressing Forms with the ModR/M Byte
из Vol 2A
говорит вам, что Mod
= 00 и R/M
= 101 означает disp32
, IOW, в инструкции есть операнд памяти, состоящий из 32-битного смещения.
Поле Reg
байта ModR/M
уже использовалось для выбора одной из семи инструкций, и поэтому это поле не кодирует регистровый операнд.
Итак, ваша инструкция PUSH DWORD [0x0040200E]
.
И это согласуется с моими выводами дизассемблера.
Давайте попробуем просмотреть эту последовательность байтов по одному байту за раз.
- Первый байт -
FF
. Если посмотреть на карту кодов операций в Справочнике по набору инструкций Intel, то мы узнаем, что это инструкцияINC
илиDEC
вместе с загадочной «Grp 5 - 1A». 1A означает, что «биты 5, 4 и 3 байта ModR / M используются в качестве расширения кода операции». Байт ModR / M - это байт, который кодирует источник и адрес операндов, которые используются для этой инструкции. В этом случае три бита используются для расширения кода операции. - Следующий байт -
35
. Это байт ModR / M, который обычно появляется сразу после самого кода операции в инструкциях, которые его используют.35
(в шестнадцатеричном формате) - это00110101
в двоичном формате, поэтому биты 5, 4 и 3 равны110
. Глядя на это в таблице расширений кода операции (Таблица A-6), мы видим, что это означает, что это инструкцияPUSH d64 Ev
. Сноскаd64
означает, что «В 64-битном режиме инструкция по умолчанию использует 64-битный размер операнда и не может кодировать 32-битный размер операнда.». Это ожидается для инструкцииPUSH
.Ev
- это символ, который определяет кодировку операнда - что наиболее важно, он указывает, что байт ModR / M следует за самим кодом операции.v
, с другой стороны, сигнализирует, что размер операнда зависит от атрибута размера операнда. У нас уже есть байт ModR / M, поэтому давайте его расшифруем (таблица 2-2, предполагая, что этот код работает в 32-битном режиме): эффективный адрес указывается какdisp32
, что означает, что 32-битное смещение должно следовать за байтом ModR / M. Часть, определяющая регистр, говорит, что следует использоватьESI
, но в этом случае это поле используется для расширения кода операции, поэтому оно не используется для обозначения операнда источника регистра. - Следующие четыре байта - это 32-битное смещение.
0E 20 40 00
при декодировании с прямым порядком байтов означает0x40200e
. Это адрес операнда, который будет использоваться для этой инструкции.
Подводя итог, мы получили, что FF 35 0E 20 40 00
равно PUSH DWORD [0x40200e]
, то есть он будет помещать 32-битное значение, считанное с адреса 0x40200e
в стек.