Files
Info/2 курс/Языки программирования/Библиотека команд ассемблера.md
T

326 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
### Содержание
- [[#ADD]]
- [[#CALL]]
- [[#CMP]]
- [[#DEC]]
- [[#DIV]]
- [[#ENTER]]
- [[#IDIV]]
- [[#IMUL]]
- [[#INC]]
- [[#JMP]]
- [[#LEA]]
- [[#LEAVE]]
- [[#MOV]]
- [[#MUL]]
- [[#NEG]]
- [[#POP]]
- [[#PUSH]]
- [[#RET]]
- [[#SAL/SAR/SHL/SHR|SHIFT]]
- [[#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>` команда аналогична [[#MUL|инструкции]] `mul`. В данном случае `<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](Среда%20выполнения.%20Основы%20языка%20ассемблера.md#Команды).
### 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.
#### Примечания
Оба операнда не могут одновременно быть ячейками памяти. Часто данную команду используют для обнуления указанного дважды регистра.