Бөлісу құралы:


x86 Instructions

В списках в этом разделе инструкции, помеченные звездочкой (*) особенно важны. Инструкции не так помечены не являются критическими.

На процессоре x86 инструкции имеют переменный размер, поэтому дизассемблирование назад является упражнением в сопоставлении шаблонов. Чтобы дизассемблировать назад от адреса, следует начать дизассемблирование в точке дальше назад, чем вы действительно хотите пойти, а затем с нетерпением ждите, пока инструкции не начнут иметь смысл. Первые несколько инструкций могут не иметь смысла, так как возможно, вы начали дизассемблирование в середине инструкции. Существует возможность, к сожалению, что дизассембли никогда не будет синхронизироваться с потоком инструкций, и вам придется попробовать дизассемблинг в другой начальной точке, пока не найдете начальную точку, которая работает.

For well-packed switch statements, the compiler emits data directly into the code stream, so disassembling through a switch statement will usually stumble across instructions that make no sense (because they are really data). Найдите конец данных и продолжайте дизассемблинг там.

Нотация инструкций

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

Арифметические инструкции обычно двухрегистрируются с помощью регистров источника и назначения. Результат хранится в месте назначения.

Некоторые инструкции имеют 16-разрядные и 32-разрядные версии, но здесь перечислены только 32-разрядные версии. Здесь не указаны инструкции с плавающей запятой, привилегированные инструкции и инструкции, которые используются только в сегментированных моделях (которые Microsoft Win32 не использует).

Чтобы сэкономить место, многие инструкции выражаются в объединенной форме, как показано в следующем примере.

*

MOV

r1, r/m/#n

r1 = r/m/#n

означает, что первый параметр должен быть регистром, но второй может быть регистром, ссылкой на память или непосредственным значением.

Чтобы сэкономить еще больше места, инструкции также можно выразить, как показано в следующем примере.

*

MOV

r1/m, r/m/#n

r1/m = r/m/#n

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

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

Кроме того, битовый суффикс (8, 16, 32) можно добавить в источник или назначение, чтобы указать, что параметр должен иметь такой размер. Например, r8 означает 8-разрядный регистр.

Преобразование памяти, передачи данных и преобразования данных

Инструкции по передаче памяти и данных не влияют на флаги.

Эффективный адрес

*

LEA

r, m

Загрузка эффективного адреса.

(r = адрес m)

Например , LEA eax, [esi+4] означает eax = esi + 4. Эта инструкция часто используется для арифметики.

Передача данных

MOV

r1/m, r2/m/#n

r1/m = r/m/#n

MOVSX

r1, r/m

Перемещение с расширением знака.

*

MOVZX

r1, r/m

Перемещение с нулевым расширением.

MOVSX and MOVZX are special versions of the mov instruction that perform sign extension or zero extension from the source to the destination. Это единственная инструкция, которая позволяет источнику и назначению иметь разные размеры. (И на самом деле они должны быть разными размерами.

Обработка стека

The stack is pointed to by the esp register. The value at esp is the top of the stack (most recently pushed, first to be popped); older stack elements reside at higher addresses.

PUSH

r/m/#n

Отправка значения в стек.

POP

r/m

Всплывающее значение из стека.

PUSHFD

Отправка флагов в стек.

POPFD

Всплывающие флаги из стека.

PUSHAD

Отправка всех целых регистров.

POPAD

Появляется все целые регистры.

ENTER

#n, #n

Кадр стека сборки.

*

LEAVE

Разрыв кадра стека

The C/C++ compiler does not use the enter instruction. (The enter instruction is used to implement nested procedures in languages like Algol or Pascal.)

The leave instruction is equivalent to:

mov esp, ebp
pop ebp

Преобразование данных

CBW

Convert byte (al) to word (ax).

CWD

Convert word (ax) to dword (dx:ax).

CWDE

Convert word (ax) to dword (eax).

CDQ

convert dword (eax) to qword (edx:eax).

Все преобразования выполняют расширение знака.

Арифметические и битовые манипуляции

Все арифметические и битовые инструкции по манипуляции изменяют флаги.

Арифметика

ADD

r1/m, r2/m/#n

r1/m += r2/m/#n

ADC

r1/m, r2/m/#n

r1/m += r2/m/#n + carry

SUB

r1/m, r2/m/#n

r1/m -= r2/m/#n

SBB

r1/m, r2/m/#n

r1/m -= r2/m/#n + carry

NEG

r1/m

r1/m = -r1/m

INC

r/m

r/m += 1

DEC

r/m

r/m -= 1

CMP

r1/m, r2/m/#n

Compute r1/m - r2/m/#n

The cmp instruction computes the subtraction and sets flags according to the result, but throws the result away. It is typically followed by a conditional jump instruction that tests the result of the subtraction.

MUL

r/m8

ax = al * r/m8

MUL

r/m16

dx:ax = ax * r/m16

MUL

r/m32

edx:eax = eax * r/m32

IMUL

r/m8

ax = al * r/m8

IMUL

r/m16

dx:ax = ax * r/m16

IMUL

r/m32

edx:eax = eax * r/m32

IMUL

r1, r2/m

r1 *= r2/m

IMUL

r1, r2/m, #n

r1 = r2/m * #n

Незначенный и подписанный умножение. Состояние флагов после умножения не определено.

DIV

r/m8

(ah, al) = (ax % r/m8, ax / r/m8)

DIV

r/m16

(dx, ax) = dx:ax / r/m16

DIV

r/m32

(edx, eax) = edx:eax / r/m32

IDIV

r/m8

(ah, al) = ax / r/m8

IDIV

r/m16

(dx, ax) = dx:ax / r/m16

IDIV

r/m32

(edx, eax) = edx:eax / r/m32

Незаписанный и подписанный раздел. Первый регистр в объяснении псевдокода получает оставшуюся часть, а второй получает кворот. Если результат переполняет место назначения, создается исключение переполнения деления.

Состояние флагов после разделения не определено.

*

SETcc

r/m8

Set r/m8 to 0 or 1

If the condition cc is true, then the 8-bit value is set to 1. В противном случае 8-разрядное значение равно нулю.

Двоичный закодированный десятичный знак

Эти инструкции не будут отображаться, если вы не отладите код, написанный в COBOL.

DAA

Десятичная корректировка после добавления.

DAS

Десятичная корректировка после вычитания.

These instructions adjust the al register after performing a packed binary-coded decimal operation.

AAA

ASCII корректируется после добавления.

AAS

ASCII корректируется после вычитания.

These instructions adjust the al register after performing an unpacked binary-coded decimal operation.

AAM

ASCII корректируется после умножения.

AAD

ASCII корректируется после деления.

These instructions adjust the al and ah registers after performing an unpacked binary-coded decimal operation.

Биты

AND

r1/m, r2/m/#n

r1/m = r1/m and r2/m/#n

OR

r1/m, r2/m/#n

r1/m = r1/m or r2/m/#n

XOR

r1/m, r2/m/#n

r1/m = r1/m xor r2/m/#n

NOT

r1/m

r1/m = bitwise not r1/m

*

TEST

r1/m, r2/m/#n

Compute r1/m and r2/m/#n

The test instruction computes the logical AND operator and sets flags according to the result, but throws the result away. Обычно за ним следует инструкция условного перехода, которая проверяет результат логического И.

SHL

r1/m, cl/#n

r1/m <<= cl/#n

SHR

r1/m, cl/#n

r1/m >>= cl/#n zero-fill

*

SAR

r1/m, cl/#n

r1/m >>= cl/#n sign-fill

Последний бит смещен на выноску.

SHLD

r1, r2/m, cl/#n

Сдвиг влево.

Shift r1 left by cl/#n, filling with the top bits of r2/m. Последний бит смещен на выноску.

SHRD

r1, r2/m, cl/#n

Сдвиг вправо вправо.

Shift r1 right by cl/#n, filling with the bottom bits of r2/m. Последний бит смещен на выноску.

ROL

r1, cl/#n

Rotate r1 left by cl/#n.

ROR

r1, cl/#n

Rotate r1 right by cl/#n.

RCL

r1, cl/#n

Rotate r1/C left by cl/#n.

RCR

r1, cl/#n

Rotate r1/C right by cl/#n.

Поворот похож на сдвиг, за исключением того, что биты, которые смещены повторно, появляются как входящие биты заливки. Версия инструкций поворота на языке C включает бит переноса в поворот.

BT

r1, r2/#n

Copy bit r2/#n of r1 into carry.

BTS

r1, r2/#n

Set bit r2/#n of r1, copy previous value into carry.

BTC

r1, r2/#n

Clear bit r2/#n of r1, copy previous value into carry.

Поток управления

Jcc

dest

Branch conditional.

JMP

dest

Jump direct.

JMP

r/m

Jump indirect.

CALL

dest

Call direct.

*

CALL

r/m

Call indirect.

The call instruction pushes the return address onto the stack then jumps to the destination.

*

RET

#n

Return

The ret instruction pops and jumps to the return address on the stack. A nonzero #n in the RET instruction indicates that after popping the return address, the value #n should be added to the stack pointer.

LOOP

Decrement ecx and jump if result is nonzero.

LOOPZ

Decrement ecx and jump if result is nonzero and zr was set.

LOOPNZ

Decrement ecx and jump if result is nonzero and zr was clear.

JECXZ

Jump if ecx is zero.

Эти инструкции являются остатками наследия CISC x86, и в последних процессорах на самом деле медленнее, чем эквивалентные инструкции, написанные долгий путь.

Обработка строк

MOVST

Move T from esi to edi.

CMPST

Compare T from esi with edi.

SCAST

Scan T from edi for accT.

LODST

Load T from esi into accT.

STOST

Store T to edi from accT.

After performing the operation, the source and destination register are incremented or decremented by sizeof(T), according to the setting of the direction flag (up or down).

The instruction can be prefixed by REP to repeat the operation the number of times specified by the ecx register.

The rep mov instruction is used to copy blocks of memory.

The rep stos instruction is used to fill a block of memory with accT.

Флаги

LAHF

Load ah from flags.

SAHF

Store ah to flags.

STC

Set carry.

CLC

Clear carry.

CMC

Complement carry.

STD

Set direction to down.

CLD

Set direction to up.

STI

Enable interrupts.

CLI

Disable interrupts.

Переблокированные инструкции

XCHG

r1, r/m

Swap r1 and r/m.

XADD

r1, r/m

Add r1 to r/m, put original value in r1.

CMPXCHG

r1, r/m

Сравнение и обмен условными данными.

The cmpxchg instruction is the atomic version of the following:

   cmp     accT, r/m
   jz      match
   mov     accT, r/m
   jmp     done
match:
   mov     r/m, r1
done:

Смешанный

INT

#n

Ловушка к ядру.

BOUND

r, m

Trap if r not in range.

*

NOP

No operation.

XLATB

al = [ebx + al]

BSWAP

r

Переключение порядка байтов в регистре.

Here is a special case of the int instruction.

INT

3

Ловушка точек останова отладчика.

The opcode for INT 3 is 0xCC. The opcode for NOP is 0x90.

При отладке кода может потребоваться исправить некоторый код. Это можно сделать, заменив обижающие байты 0x90.

Идиомы

XOR

r, r

r = 0

TEST

r, r

Check if r = 0.

*

ADD

r, r

Shift r left by 1.