Добавлена библиотека команд ассемблера для языков программирования
This commit is contained in:
@@ -0,0 +1,326 @@
|
||||
### Содержание
|
||||
- [[#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.
|
||||
#### Примечания
|
||||
Оба операнда не могут одновременно быть ячейками памяти. Часто данную команду используют для обнуления указанного дважды регистра.
|
||||
Reference in New Issue
Block a user