24 KiB
Содержание
- #ADD
- #CALL
- #CMP
- #DEC
- #DIV
- #ENTER
- #IDIV
- #IMUL
- #INC
- #JMP
- #LEA
- #LEAVE
- #MOV
- #MUL
- #NEG
- #POP
- #PUSH
- #RET
- #SAL/SAR/SHL/SHR
- #SUB
- #SYSCALL
- #TEST
- #XOR
ADD
add <op1>, <op2> добавляет значение операнда <op1> к значению операнда <op2> и записывает результат в операнд <op1>.
Комбинации операндов
<op1> - <op2>
- регистр - регистр или ячейка памяти
- регистр или ячейка памяти - регистр
- регистр - явно заданный операнд
al/ax/eax/rax- явно заданный операнд
Флаги
Ставит OF, SF, ZF, AF, CF и PF.
Примечания
Как видно, нельзя сложить две ячейки памяти. Когда вторым операндом является явно заданное число, его знак расширяется до размера первого операнда.
CALL
call <address> сохраняет информацию (регистр rip) о текущем процессе и передает управление процессу, расположенному по адресу <address> (заменят значение регистра rip на address).
Комбинации операндов
В зависимости от типа адресации, <address> может быть как регистром или ячейкой памяти (абсолютная адресация), так и меткой (относительная адресация).
Флаги
Не меняются.
Примечания
При использовании в качестве абсолютного адреса значения вершины стека [rsp] (с использованием косвенной адресации), команда сначала сохранит необходимый адрес перехода, и только потом сохранит адрес возврата в стек.
CMP
cmp <op1>, <op2> выполняет операцию вычитания (sub <op1>, <op2>) без сохранения результата.
Комбинации операндов
Те же, что и у #SUB sub.
Флаги
Ставит CF, OF, SF, ZF, AF и PF.
Примечания
В основном используется перед командами, исполнение которых зависит от флагов состояния. При необходимости, знак второго операнда расширяется до размера первого.
DEC
dec <op> уменьшает значение операнда на единицу.
Комбинации операндов
Регистр или ячейка памяти.
Флаги
Не меняет CF. Ставит OF, SF, ZF, AF и PF.
Примечания
Может использоваться для изменения счетчика цикла без изменения флага CF. Для того, чтобы также изменить значение флага CF, можно использовать #SUB sub.
DIV
div <op> производит беззнаковое деление значения регистра ax (или dx:ax, edx:eax, rdx:rax, в зависимости от размера) на операнд <op>, сохраняя целую часть деления в регистр al (или ax, eax, rax), а остаток - в регистр ah (или dx, edx, rdx).
Комбинации операндов
Регистр или ячейка памяти. В зависимости от размера операнда, меняются регистры для изначального значения и результата.
<op> = byte(1 байт) -ax -> al:ah<op> = word(2 байта) -dx:ax -> dx:ax<op> = dword(4 байта) -edx:eax -> edx:eax<op> = qword(8 байт) -rdx:rax -> rdx:rax
Флаги
Не определены CF, OF, SF, ZF, AF и PF.
Примечания
Все значения округляются в сторону нуля. Чтобы не запутаться, в какой регистр какая часть результата записывается, можно регистры rdx:rax читать как дробь, где сверху будет rdx - остаток, а снизу - rax - целая часть.
ENTER
enter <op1>, <op2> создает фрейм стека для подпрограммы с указанным размером <op1> и уровнем вложенности <op2>. При нулевом уровне вложенности сохраняет rbp в стеке, новое значение rbp ставит равным текущему rsp, а после сдвигает rsp на указанное количество байт <op1>. Если же вложенность больше 0, то помимо rbp, на стек будут также записаны значения, указывающие на фреймы всех предыдущих уровней вложенности, а также указатель текущего фрейма, и только после этого выделится нужное количество памяти.
Комбинации операндов
<op1> - явно заданное 16-битное число
<op2> - явно заданное 8-битное число
Флаги
Не меняет.
Примечания
Уровни вложенности применяются только в блочных структурах, где нужен доступ к памяти функции предыдущих уровней вложенности. На практике же можно применять только нулевой уровень вложенности. В таком случае команду enter <op1>, 0 можно расписать как push rbp; mov rbp, rsp; sub rsp, <op1>. Чаще всего используется в паре с #LEAVE leave.
IDIV
idiv <op> производит знаковое деление значения регистра ax (или dx:ax, edx:eax, rdx:rax, в зависимости от размера) на операнд <op>, сохраняя целую часть деления в регистр al (или ax, eax, rax), а остаток - в регистр ah (или dx, edx, rdx).
Примечания
В основном, данная команда схожа с #DIV div, только используется для знаковых чисел, а не для беззнаковых.
IMUL
imul <op1>, <op2>, <op3> производит знаковое умножение двух операндов. При этом операнды <op2> и <op3> необязательны, но от их наличия изменяется поведение команды.
Комбинации операндов
- При наличии только одного операнда
<op1>команда аналогична #MULmul. В данном случае<op1>это регистр или ячейка памяти. - Если операнда два -
<op1>и<op2>, тогда производится умножение значения операнда<op1>на значение операнда<op2>, а результат обрезается и записывается как значение операнда<op1>. В данном случае<op1>- регистр, а<op2>- регистр или ячейка памяти. - Если операнда три -
<op1>,<op2>и<op3>, тогда производится умножение значения операнда<op2>на значение операнда<op3>, а результат обрезается и записывается как значение операнда<op1>. В данном случае<op1>- регистр,<op2>- регистр или ячейка памяти, а<op3>- явно заданное 8/16/32/64-битное число.
Флаги
Ставит CF и OF, если
- для одного операнда: верхняя половина не ноль;
- для двух или трех операндов: результат должен быть обрезан, чтобы поместится в ячейку; иначе CF и OF устанавливаются в ноль. Не определены SF, ZF, AF и PF.
INC
inc <op> увеличивает значение операнда <op> на единицу.
Комбинации операндов
Регистр или ячейка памяти.
Флаги
Ставит OF, SF, ZF, AF и PF. Не меняет CF.
Примечания
Может использоваться для изменения счетчика цикла без изменения флага CF. Для того, чтобы также изменить значение флага CF, можно использовать #ADD add.
JMP
jmp <address> производит безусловный переход на другую часть программы, указанную адресом <address>, и передает ей управление программой.
Помимо этого также существуют условные переходы, работающие по похожему принципу. Они производят переход только в определенном случае, в зависимости от значений установленных флагов.
Условные переходы
jc-jump if carry set (CF = 1)jnc-jump if carry clear (CF = 0)jo-jump if overflow set (OF = 1)jno-jump if overflow clear (OF = 0)jp-jump if parity set (PF = 1)jnp-jump if parity clear (PF = 0)js-jump if sign set (SF = 1)jns-jump if sign clear (SF = 0)jz-jump if zero set (ZF = 1)jnz-jump if zero clear (ZF = 0)je-jump if equal (ZF = 1)jne-jump if not equal (ZF = 0)ja-jump if above (CF = 0 & ZF = 0)jna-jump if not above (CF = 1 & ZF = 1)jae-jump if above or equal (CF = 0)jnae-jump if not above or equal (CF = 1)jb-jump if below (CF = 1)jnb-jump if not below (CF = 0)jbe-jump if below or equal (CF = 1 & ZF = 1)jnbe-jump if not below or equal (CF = 0 & ZF = 0)jg-jump if greater (ZF = 0 & SF = OF)jng-jump if not greater (ZF = 1 & SF != OF)jge-jump if greater or equal (SF = OF)jnge-jump if not greater or equal (SF != OF)jl-jump if less (SF != OF)jnl-jump if not less (SF = OF)jle-jump if less or equal (ZF = 1 & SF != OF)jnle-jump if not less or equal (ZF = 0 & SF = OF)
Комбинации операндов
Регистр, ячейка памяти или явно заданное число.
Флаги
Не меняет.
Примечания
Не сохраняет информацию о возврате.
LEA
lea <op>, <address> сохраняет адрес до значения по адресу <address> в качестве значения операнда <op>.
В зависимости от размера операндов, действие команды слегка меняется. Если они одного размера, ничего необычного не происходит. Если размер регистра превышает размер адреса, то адрес расширяется нулями до нужного значения и записывается в регистр. Если размер адреса больше размера регистра, то в регистр записывается только нижняя часть адреса.
Комбинации операндов
<op> - регистр.
<address> - ячейка памяти.
Флаги
Не меняет.
LEAVE
leave очищает стек от фрейма, который ранее был выделен с помощью #ENTER enter.
Флаги
Не меняет.
Примечания
Данную команду можно заменить последовательностью команд mov rsp, rbp; pop rbp. Чаще всего эта команда сопровождается #RET ret, что возвращает управление предыдущей программе.
MOV
mov <op1>, <op2> копирует значение операнда <op2> и записывает его как значение операнда <op1>.
Комбинации операндов
<op1> - <op2>
- регистр или ячейка памяти - регистр
- регистр - регистр или ячейка памяти
- регистр или ячейка памяти - явно заданное значение
Флаги
Не меняет.
Примечания
Оба операнда должны быть одинакового размера. Как видно, оба операнда не могут быть ячейкой памяти.
MUL
mul <op> производит беззнаковое умножение значения операнда <op> со значением регистра al (или ax, eax, rax, в зависимости от размера операнда <op>) и записывает результат в регистр ax (или dx:ax, edx:eax, rdx:rax).
Комбинации операндов
Регистр или ячейка памяти. В зависимости от размера операнда, меняются регистры для изначального значения и результата.
<op> = byte(1 байт) -al -> ax<op> = word(2 байта) -ax -> dx:ax<op> = dword(4 байта) -eax -> edx:eax<op> = qword(8 байт) -rax -> rdx:rax
Флаги
Ставит CF и OF в ноль, если верхняя половина результата пуста и равна нулю, иначе CF и OF ставятся в 1. Не определены SF, ZF, AF и PF.
Примечания
При записи результата два регистра можно рассматривать как соединенные вместе: меньшая часть записывается в регистр rax, а большая, если не вмещается, в регистр rdx.
NEG
neg <op> заменяет значение операнда на значение, полученное вычитанием изначального значения из нуля.
Комбинации операндов
Регистр или ячейка памяти.
Флаги
Ставит CF в 0, если значение операнда <op> = 0, иначе ставит CF в 1.
Ставит OF, SF, ZF, AF и PF.
POP
pop <op> загружает значение, находящееся на вершине стека, в указанный операнд <op> и увеличивает указатель вершины стека. В зависимости от размера читаемого операнда <op> изменится и увеличение стека (сколько загружено, на столько стек и увеличится).
Комбинации операндов
Регистр или ячейка памяти.
Флаги
Не меняет.
Примечания
При исполнении команды pop rsp увеличивает указатель стека до того, как значение старой вершины стека будет записано в регистр.
PUSH
push <op> уменьшает указатель вершины стека и загружает значение операнда <op> на вершину стека. В зависимости от размера операнда <op> изменится и уменьшение стека (сколько будет загружено, на столько стек и уменьшится).
Комбинации операндов
Регистр, ячейка памяти или явно заданное значение.
Флаги
Не меняет.
Примечания
Если операнд - явно заданное число, занимающее меньше места, чем полное значение операнда, то недостающие биты будут заполнены в соответствии со знаком числа. Команда push rsp запишет значение регистра rsp такое, какое было до его уменьшения. То же самое происходит, если адрес операнда <op> вычисляется на ходу и зависит от значения регистра rsp.
RET
ret <op> берет с вершины стека значение адреса и передает ему управление программой, уменьшая указатель стека на размер взятого адреса. Опционально может быть указан операнд <op>, по значению которого будет освобождено соответствующее количество байт из стека (то есть указатель стека увеличится на соответствующее количество байт).
Флаги
Не меняет.
Примечания
Чаще всего используется после #CALL call для возврата из подпрограммы.
SAL/SAR/SHL/SHR
shift <op1>, <op2> (где shift - семейство команд сдвигов) сдвигает биты значения операнда <op1> на соответствующее значение операнда <op2>. Существует несколько разновидностей сдвигов:
sal- арифметический сдвиг влево;sar- арифметический сдвиг вправо;shl- логический сдвиг влево;shr- логический сдвиг вправо. Арифметический и логический сдвиг влево производят одну и ту же операцию: сдвигают биты значения влево (в сторону наиболее значимых битов). Логический сдвиг вправо заменяет все освобожденные сдвигом биты на ноль. Арифметический сдвиг вправо устанавливает все освобожденные сдвигом биты в зависимости от знака изначального числа.
Комбинации операндов
<op1> - регистр или ячейка памяти.
<op2> - явно заданное 8-битное значение или значение регистра cl. При этом данное значение урезается до 6 бит.
Флаги
Если значение операнда <op2> = 0, не меняет.
Ставит CF по последнему сдвинутому за пределы числа биту; CF не определен для логических сдвигов, если значение операнда <op2> больше или равно битовой длине значения операнда <op1>.
Ставит OF в 0 только для сдвигов на один бит только в том случае, если
- при сдвиге влево два крайних левых бита равны;
- при арифметическом сдвиге вправо; иначе ставит в 1. В случае логических сдвигов вправо ставит OF по значению старшего бита изначального числа. Иначе, OF не определен. Ставит SF, ZF и PF. Не определен AF.
Примечания
Сдвиги также можно представить как умножение на два <op2> количество раз (в случае сдвига влево) или как деление на два <op2> количество раз (знаковое (с округлением в сторону отрицательной бесконечности) или беззнаковое, в зависимости от соответственно арифметического или логического сдвига вправо).
SUB
sub <op1>, <op2> вычитает значение операнда <op2> из операнда <op1>, и записывает результат в операнд <op1>.
Комбинации операндов
<op1> - <op2>
- регистр - регистр или ячейка памяти
- регистр или ячейка памяти - регистр
- регистр - явно заданный операнд
al/ax/eax/rax- явно заданный операнд
Флаги
Ставит OF, SF, ZF, AF, PF и CF.
Примечания
Оба операнда не могут быть одновременно ячейками памяти. Когда используется явно заданное значение, его знак расширяется до размера операнда <op1>.
SYSCALL
syscall вызывает системный вызов на основе переданных через аргументы функции значений.
Флаги
Ставит все флаги.
Примечания
Подробнее об этой команде можно почитать в конспекте семинара 1.
TEST
test <op1>, <op2> выполняет операцию логического "или" между значениями операндов <op1> и <op2> без сохранения результата.
Комбинации операндов
<op1> - <op2>
- регистр или ячейка памяти - регистр
- регистр или ячейка памяти - явно заданное число
al/ax/eax/rax- явно заданное число
Флаги
Ставит OF и CF в 0. Ставит SF, ZF и PF. Не определен AF.
Примечания
Часто эту команду используют для сравнения операнда с нулем, дублируя этот операнд.
XOR
xor <op1>, <op2> выполняет операцию исключающего "или" между значениями операндов <op1> и <op2> и записывает значение результата как значение операнда <op1>.
Комбинации операндов
<op1> - <op2>
- регистр - регистр или ячейка памяти
- регистр или ячейка памяти - регистр
- регистр - явно заданный операнд
al/ax/eax/rax- явно заданный операнд
Флаги
Ставит AF и CF в 0. Ставит SF, ZF и PF. Не определен AF.
Примечания
Оба операнда не могут одновременно быть ячейками памяти. Часто данную команду используют для обнуления указанного дважды регистра.