diff --git a/2 курс/2 курс.md b/2 курс/2 курс.md index 3d31e0c..bf9e70b 100644 --- a/2 курс/2 курс.md +++ b/2 курс/2 курс.md @@ -2,8 +2,8 @@ - **[Архитектура компьютера](Архитектура%20компьютера/Архитектура%20компьютера.md)** - **[Веб-программирование](Веб-программирование/Веб-программирование.md)** -- **[Языки программирования](Языки%20программирования/Языки%20программирования.md)** - **[Теория вероятностей](Теория%20вероятностей/Теория%20вероятностей.md)** +- **[Языки программирования](Языки%20программирования/Языки%20программирования.md)** ### Журналы - [Архитектура компьютера](https://docs.google.com/spreadsheets/d/1WvS1ad9J6jXNwSxTRnQs4yGgUBlwFzopUXUiYbGCZMw/edit?usp=sharing) - [Веб-программирование](https://docs.google.com/spreadsheets/d/1A2XNYpN1Q1rr5-mpkAk5g0BP4NDY-cwRWtBudLz6Xis/edit?gid=696774553#gid=696774553) diff --git a/2 курс/Языки программирования/Библиотека команд ассемблера.md b/2 курс/Языки программирования/Библиотека команд ассемблера.md new file mode 100644 index 0000000..27c34f0 --- /dev/null +++ b/2 курс/Языки программирования/Библиотека команд ассемблера.md @@ -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 , ` добавляет значение операнда `` к значению операнда `` и записывает результат в операнд ``. +#### Комбинации операндов +`` - `` +- регистр - регистр или ячейка памяти +- регистр или ячейка памяти - регистр +- регистр - явно заданный операнд +- `al/ax/eax/rax` - явно заданный операнд +#### Флаги +Ставит OF, SF, ZF, AF, CF и PF. +#### Примечания +Как видно, нельзя сложить две ячейки памяти. Когда вторым операндом является явно заданное число, его знак расширяется до размера первого операнда. + +### CALL + +`call
` сохраняет информацию (регистр `rip`) о текущем процессе и передает управление процессу, расположенному по адресу `
` (заменят значение регистра `rip` на `address`). +#### Комбинации операндов +В зависимости от типа адресации, `
` может быть как регистром или ячейкой памяти (абсолютная адресация), так и меткой (относительная адресация). +#### Флаги +Не меняются. +#### Примечания +При использовании в качестве абсолютного адреса значения вершины стека `[rsp]` (с использованием косвенной адресации), команда сначала сохранит необходимый адрес перехода, и только потом сохранит адрес возврата в стек. + +### CMP + +`cmp , ` выполняет операцию вычитания (`sub , `) без сохранения результата. +#### Комбинации операндов +Те же, что и у [[#SUB|инструкции]] `sub`. +#### Флаги +Ставит CF, OF, SF, ZF, AF и PF. +#### Примечания +В основном используется перед командами, исполнение которых зависит от флагов состояния. При необходимости, знак второго операнда расширяется до размера первого. + +### DEC + +`dec ` уменьшает значение операнда на единицу. +#### Комбинации операндов +Регистр или ячейка памяти. +#### Флаги +Не меняет CF. +Ставит OF, SF, ZF, AF и PF. +#### Примечания +Может использоваться для изменения счетчика цикла без изменения флага CF. Для того, чтобы также изменить значение флага CF, можно использовать [[#SUB|инструкцию]] `sub`. + +### DIV + +`div ` производит беззнаковое деление значения регистра `ax` (или `dx:ax`, `edx:eax`, `rdx:rax`, в зависимости от размера) на операнд ``, сохраняя целую часть деления в регистр `al` (или `ax`, `eax`, `rax`), а остаток - в регистр `ah` (или `dx`, `edx`, `rdx`). +#### Комбинации операндов +Регистр или ячейка памяти. +В зависимости от размера операнда, меняются регистры для изначального значения и результата. +- ` = byte` (1 байт) - `ax -> al:ah` +- ` = word` (2 байта) - `dx:ax -> dx:ax` +- ` = dword` (4 байта) - `edx:eax -> edx:eax` +- ` = qword` (8 байт) - `rdx:rax -> rdx:rax` +#### Флаги +Не определены CF, OF, SF, ZF, AF и PF. +#### Примечания +Все значения округляются в сторону нуля. Чтобы не запутаться, в какой регистр какая часть результата записывается, можно регистры `rdx:rax` читать как дробь, где сверху будет `rdx` - остаток, а снизу - `rax` - целая часть. + +### ENTER + +`enter , ` создает фрейм стека для подпрограммы с указанным размером `` и уровнем вложенности ``. При нулевом уровне вложенности сохраняет `rbp` в стеке, новое значение `rbp` ставит равным текущему `rsp`, а после сдвигает `rsp` на указанное количество байт ``. Если же вложенность больше 0, то помимо `rbp`, на стек будут также записаны значения, указывающие на фреймы всех предыдущих уровней вложенности, а также указатель текущего фрейма, и только после этого выделится нужное количество памяти. +#### Комбинации операндов +`` - явно заданное 16-битное число +`` - явно заданное 8-битное число +#### Флаги +Не меняет. +#### Примечания +Уровни вложенности применяются только в блочных структурах, где нужен доступ к памяти функции предыдущих уровней вложенности. На практике же можно применять только нулевой уровень вложенности. В таком случае команду `enter , 0` можно расписать как `push rbp; mov rbp, rsp; sub rsp, `. Чаще всего используется в паре с [[#LEAVE|инструкцией]] `leave`. + +### IDIV + +`idiv ` производит знаковое деление значения регистра `ax` (или `dx:ax`, `edx:eax`, `rdx:rax`, в зависимости от размера) на операнд ``, сохраняя целую часть деления в регистр `al` (или `ax`, `eax`, `rax`), а остаток - в регистр `ah` (или `dx`, `edx`, `rdx`). +#### Примечания +В основном, данная команда схожа с [[#DIV|инструкцией]] `div`, только используется для знаковых чисел, а не для беззнаковых. + +### IMUL + +`imul , , ` производит знаковое умножение двух операндов. При этом операнды `` и `` необязательны, но от их наличия изменяется поведение команды. +#### Комбинации операндов +- При наличии только одного операнда `` команда аналогична [[#MUL|инструкции]] `mul`. В данном случае `` это регистр или ячейка памяти. +- Если операнда два - `` и ``, тогда производится умножение значения операнда `` на значение операнда ``, а результат обрезается и записывается как значение операнда ``. В данном случае `` - регистр, а `` - регистр или ячейка памяти. +- Если операнда три - ``, `` и ``, тогда производится умножение значения операнда `` на значение операнда ``, а результат обрезается и записывается как значение операнда ``. В данном случае `` - регистр, `` - регистр или ячейка памяти, а `` - явно заданное 8/16/32/64-битное число. +#### Флаги +Ставит CF и OF, если +- для одного операнда: верхняя половина не ноль; +- для двух или трех операндов: результат должен быть обрезан, чтобы поместится в ячейку; +иначе CF и OF устанавливаются в ноль. +Не определены SF, ZF, AF и PF. + +### INC + +`inc ` увеличивает значение операнда `` на единицу. +#### Комбинации операндов +Регистр или ячейка памяти. +#### Флаги +Ставит OF, SF, ZF, AF и PF. +Не меняет CF. +#### Примечания +Может использоваться для изменения счетчика цикла без изменения флага CF. Для того, чтобы также изменить значение флага CF, можно использовать [[#ADD|инструкцию]] `add`. + +### JMP + +`jmp
` производит безусловный переход на другую часть программы, указанную адресом `
`, и передает ей управление программой. +Помимо этого также существуют условные переходы, работающие по похожему принципу. Они производят переход только в определенном случае, в зависимости от значений установленных флагов. +#### Условные переходы +- `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 ,
` сохраняет адрес до значения по адресу `
` в качестве значения операнда ``. +В зависимости от размера операндов, действие команды слегка меняется. Если они одного размера, ничего необычного не происходит. Если размер регистра превышает размер адреса, то адрес расширяется нулями до нужного значения и записывается в регистр. Если размер адреса больше размера регистра, то в регистр записывается только нижняя часть адреса. +#### Комбинации операндов +`` - регистр. +`
` - ячейка памяти. +#### Флаги +Не меняет. + +### LEAVE + +`leave` очищает стек от фрейма, который ранее был выделен с помощью [[#ENTER|инструкции]] `enter`. +#### Флаги +Не меняет. +#### Примечания +Данную команду можно заменить последовательностью команд `mov rsp, rbp; pop rbp`. Чаще всего эта команда сопровождается [[#RET|инструкцией]] `ret`, что возвращает управление предыдущей программе. + +### MOV + +`mov , ` копирует значение операнда `` и записывает его как значение операнда ``. +#### Комбинации операндов +`` - `` +- регистр или ячейка памяти - регистр +- регистр - регистр или ячейка памяти +- регистр или ячейка памяти - явно заданное значение +#### Флаги +Не меняет. +#### Примечания +Оба операнда должны быть одинакового размера. Как видно, оба операнда не могут быть ячейкой памяти. + +### MUL + +`mul ` производит беззнаковое умножение значения операнда `` со значением регистра `al` (или `ax`, `eax`, `rax`, в зависимости от размера операнда ``) и записывает результат в регистр `ax` (или `dx:ax`, `edx:eax`, `rdx:rax`). +#### Комбинации операндов +Регистр или ячейка памяти. +В зависимости от размера операнда, меняются регистры для изначального значения и результата. +- ` = byte` (1 байт) - `al -> ax` +- ` = word` (2 байта) - `ax -> dx:ax` +- ` = dword` (4 байта) - `eax -> edx:eax` +- ` = qword` (8 байт) - `rax -> rdx:rax` +#### Флаги +Ставит CF и OF в ноль, если верхняя половина результата пуста и равна нулю, иначе CF и OF ставятся в 1. +Не определены SF, ZF, AF и PF. +#### Примечания +При записи результата два регистра можно рассматривать как соединенные вместе: меньшая часть записывается в регистр `rax`, а большая, если не вмещается, в регистр `rdx`. + +### NEG + +`neg ` заменяет значение операнда на значение, полученное вычитанием изначального значения из нуля. +#### Комбинации операндов +Регистр или ячейка памяти. +#### Флаги +Ставит CF в 0, если значение операнда ` = 0`, иначе ставит CF в 1. +Ставит OF, SF, ZF, AF и PF. + +### POP + +`pop ` загружает значение, находящееся на вершине стека, в указанный операнд `` и увеличивает указатель вершины стека. В зависимости от размера читаемого операнда `` изменится и увеличение стека (сколько загружено, на столько стек и увеличится). +#### Комбинации операндов +Регистр или ячейка памяти. +#### Флаги +Не меняет. +#### Примечания +При исполнении команды `pop rsp` увеличивает указатель стека до того, как значение старой вершины стека будет записано в регистр. + +### PUSH + +`push ` уменьшает указатель вершины стека и загружает значение операнда `` на вершину стека. В зависимости от размера операнда `` изменится и уменьшение стека (сколько будет загружено, на столько стек и уменьшится). +#### Комбинации операндов +Регистр, ячейка памяти или явно заданное значение. +#### Флаги +Не меняет. +#### Примечания +Если операнд - явно заданное число, занимающее меньше места, чем полное значение операнда, то недостающие биты будут заполнены в соответствии со знаком числа. Команда `push rsp` запишет значение регистра `rsp` такое, какое было до его уменьшения. То же самое происходит, если адрес операнда `` вычисляется на ходу и зависит от значения регистра `rsp`. + +### RET + +`ret ` берет с вершины стека значение адреса и передает ему управление программой, уменьшая указатель стека на размер взятого адреса. Опционально может быть указан операнд ``, по значению которого будет освобождено соответствующее количество байт из стека (то есть указатель стека увеличится на соответствующее количество байт). +#### Флаги +Не меняет. +#### Примечания +Чаще всего используется после [[#CALL|инструкции]] `call` для возврата из подпрограммы. + +### SAL/SAR/SHL/SHR + +`shift , ` (где `shift` - семейство команд сдвигов) сдвигает биты значения операнда `` на соответствующее значение операнда ``. Существует несколько разновидностей сдвигов: +- `sal` - арифметический сдвиг влево; +- `sar` - арифметический сдвиг вправо; +- `shl` - логический сдвиг влево; +- `shr` - логический сдвиг вправо. +Арифметический и логический сдвиг влево производят одну и ту же операцию: сдвигают биты значения влево (в сторону наиболее значимых битов). Логический сдвиг вправо заменяет все освобожденные сдвигом биты на ноль. Арифметический сдвиг вправо устанавливает все освобожденные сдвигом биты в зависимости от знака изначального числа. +#### Комбинации операндов +`` - регистр или ячейка памяти. +`` - явно заданное 8-битное значение или значение регистра `cl`. При этом данное значение урезается до 6 бит. +#### Флаги +Если значение операнда ` = 0`, не меняет. +Ставит CF по последнему сдвинутому за пределы числа биту; CF не определен для логических сдвигов, если значение операнда `` больше или равно битовой длине значения операнда ``. +Ставит OF в 0 только для сдвигов на один бит только в том случае, если +- при сдвиге влево два крайних левых бита равны; +- при арифметическом сдвиге вправо; +иначе ставит в 1. В случае логических сдвигов вправо ставит OF по значению старшего бита изначального числа. Иначе, OF не определен. +Ставит SF, ZF и PF. +Не определен AF. +#### Примечания +Сдвиги также можно представить как умножение на два `` количество раз (в случае сдвига влево) или как деление на два `` количество раз (знаковое (с округлением в сторону отрицательной бесконечности) или беззнаковое, в зависимости от соответственно арифметического или логического сдвига вправо). + +### SUB + +`sub , ` вычитает значение операнда `` из операнда ``, и записывает результат в операнд ``. +#### Комбинации операндов +`` - `` +- регистр - регистр или ячейка памяти +- регистр или ячейка памяти - регистр +- регистр - явно заданный операнд +- `al/ax/eax/rax` - явно заданный операнд +#### Флаги +Ставит OF, SF, ZF, AF, PF и CF. +#### Примечания +Оба операнда не могут быть одновременно ячейками памяти. Когда используется явно заданное значение, его знак расширяется до размера операнда ``. + +### SYSCALL + +`syscall` вызывает системный вызов на основе переданных через аргументы функции значений. +#### Флаги +Ставит все флаги. +#### Примечания +Подробнее об этой команде можно почитать в конспекте [семинара 1](Среда%20выполнения.%20Основы%20языка%20ассемблера.md#Команды). + +### TEST + +`test , ` выполняет операцию логического "или" между значениями операндов `` и `` без сохранения результата. +#### Комбинации операндов +`` - `` +- регистр или ячейка памяти - регистр +- регистр или ячейка памяти - явно заданное число +- `al/ax/eax/rax` - явно заданное число +#### Флаги +Ставит OF и CF в 0. +Ставит SF, ZF и PF. +Не определен AF. +#### Примечания +Часто эту команду используют для сравнения операнда с нулем, дублируя этот операнд. + +### XOR + +`xor , ` выполняет операцию исключающего "или" между значениями операндов `` и `` и записывает значение результата как значение операнда ``. +#### Комбинации операндов +`` - `` +- регистр - регистр или ячейка памяти +- регистр или ячейка памяти - регистр +- регистр - явно заданный операнд +- `al/ax/eax/rax` - явно заданный операнд +#### Флаги +Ставит AF и CF в 0. +Ставит SF, ZF и PF. +Не определен AF. +#### Примечания +Оба операнда не могут одновременно быть ячейками памяти. Часто данную команду используют для обнуления указанного дважды регистра. \ No newline at end of file diff --git a/2 курс/Языки программирования/Вызов функций. Использование стека. Конечные автоматы.md b/2 курс/Языки программирования/Вызов функций. Использование стека. Конечные автоматы.md index b25bbad..8959185 100644 --- a/2 курс/Языки программирования/Вызов функций. Использование стека. Конечные автоматы.md +++ b/2 курс/Языки программирования/Вызов функций. Использование стека. Конечные автоматы.md @@ -34,11 +34,11 @@ >**Переходы** - инструкции, которые явно меняют порядок выполнения программы. -Безусловный переход к необходимой инструкции по адресу выполняется с помощбю инструкции `jmp`. Инструкцию `jmp addr` можно интерпретировать как команду `mov rip, addr` (сама такая команда, к слову, исполнена быть [[#Регистры|не может]]. +Безусловный переход к необходимой инструкции по адресу выполняется с помощбю [инструкции](Библиотека%20команд%20ассемблера.md#JMP) `jmp`. Команду `jmp addr` можно интерпретировать как команду `mov rip, addr` (сама такая команда, к слову, исполнена быть [[#Регистры|не может]]. -Но переходы также бывают и условными, то есть исполняются только при определенном условии. Чаще всего такие условия устанавливаются по [[#Регистры|регистру]] `eflags/rflags` во время исполнения программы. Почти для каждого флага (коих всего шесть - CF (Carry Flag), PF (Parity Flag), AF (Auxiliary Carry Flag), ZF (Zero Flag), SF (Sign Flag) и OF (Overflow Flag), но AF при условных переходах не используется) существует как минимум по две инструкции перехода: если флаг установлен в ноль или в единицу. Помимо этого, существуют другие полезные инструкции, такие как `ja`, `jb` (для беззнаковых числе), `jg`, `jl` (для знаковых чисел), `jae`, `jle` и подобные. +Но переходы также бывают и условными, то есть исполняются только при определенном условии. Чаще всего такие условия устанавливаются по [[#Регистры|регистру]] `eflags/rflags` во время исполнения программы. Почти для каждого флага (коих всего шесть - CF (Carry Flag), PF (Parity Flag), AF (Auxiliary Carry Flag), ZF (Zero Flag), SF (Sign Flag) и OF (Overflow Flag), но AF при условных переходах не используется) существует как минимум по две инструкции перехода: если флаг установлен в ноль или в единицу. Помимо этого, существуют другие полезные [инструкции](Библиотека%20команд%20ассемблера.md#JMP), такие как `ja`, `jb` (для беззнаковых числе), `jg`, `jl` (для знаковых чисел), `jae`, `jle` и подобные. -Для того, чтобы поставить необходимые для перехода флаги, в основном используются инструкция `test` или инструкция `cmp`, которые эти флаги ставят. Для проверки какого-либо регистра `reg` на ноль чаще всего используют команду `test reg, reg`. +Для того, чтобы поставить необходимые для перехода флаги, в основном используются [инструкция](Библиотека%20команд%20ассемблера.md#TEST) `test` или [инструкция](Библиотека%20команд%20ассемблера.md#CMP) `cmp`, которые эти флаги ставят. Для проверки какого-либо регистра `reg` на ноль чаще всего используют команду `test reg, reg`. ### Локальные метки Для того, чтобы выделять различные участки подпрограммы, используются локальные метки. @@ -72,12 +72,12 @@ 1. создать для нее [метку](Среда%20выполнения.%20Основы%20языка%20ассемблера.md#Секции,%20метки%20и%20комментарии); 2. выделить код функции отдельно по [метке](Среда%20выполнения.%20Основы%20языка%20ассемблера.md#Секции,%20метки%20и%20комментарии). -По факту, функции работают как [[#Переходы|переход]] с возвратом в место вызова. При вызове функции адрес возврата сохраняется в [[#Стек|стек]]. Для вызова функции используется инструкция `call` (буквально `call addr` можно разложить как `push rip` и `jmp addr`, хотя вручную такие команды выполнить [[#Регистры|не получится]]). +По факту, функции работают как [[#Переходы|переход]] с возвратом в место вызова. При вызове функции адрес возврата сохраняется в [[#Стек|стек]]. Для вызова функции используется [инструкция](Библиотека%20команд%20ассемблера.md#CALL) `call` (буквально `call addr` можно разложить как `push rip` и `jmp addr`, хотя вручную такие команды выполнить [[#Регистры|не получится]]). Можно расписать вызов функции по шагам: 1. Сохранить все важные значения [[#Соглашение%20вызова|caller-saved]] регистров (их можно сохранить в стеке). 2. Выставить необходимые [[#Функции%20с%20аргументами|аргументы]] в нужные регистры. -3. Вызвать функцию инструкцией `call`. +3. Вызвать функцию [инструкцией](Библиотека%20команд%20ассемблера.md#CALL) `call`. 4. Сохранить [[#Возврат значений из функции|результат работы]] функции из `rax`. 5. Вернуть [[#Соглашение%20вызова|caller-saved]] регистры в исходное положение. @@ -86,7 +86,7 @@ В качестве примера выделения функции можно рассмотреть [простейший пример](Среда%20выполнения.%20Основы%20языка%20ассемблера.md#Простейшая%20программа) программы на ассемблере. Есть смысл выделить в этой программе функцию выхода: тогда можно будет обращаться к ней из любого места программы. -Для определения функции необходимо использовать [метку](Среда%20выполнения.%20Основы%20языка%20ассемблера.md#Секции,%20метки%20и%20комментарии), которая на эту функцию будет указывать: в данном случае, очевидно, метка будет называться `exit`. После [метки](Среда%20выполнения.%20Основы%20языка%20ассемблера.md#Секции,%20метки%20и%20комментарии) идет выделенный для этой функции код. Для вызова функции в программе будет использоваться инструкция `call`. +Для определения функции необходимо использовать [метку](Среда%20выполнения.%20Основы%20языка%20ассемблера.md#Секции,%20метки%20и%20комментарии), которая на эту функцию будет указывать: в данном случае, очевидно, метка будет называться `exit`. После [метки](Среда%20выполнения.%20Основы%20языка%20ассемблера.md#Секции,%20метки%20и%20комментарии) идет выделенный для этой функции код. Для вызова функции в программе будет использоваться [инструкция](Библиотека%20команд%20ассемблера.md#CALL) `call`. Таким образом получим новую программу. ``` @@ -111,13 +111,13 @@ _start: ``` ### Возврат из функций -Вообще, подпрограмма обязана иметь возможность быть вызвана отовсюду и вернутся в место вызова. Для того, чтобы завершить функцию и вернутся к месту ее вызова, используется инструкция `ret` (буквально команду `ret` можно интерпретировать как `pop rip`). +Вообще, подпрограмма обязана иметь возможность быть вызвана отовсюду и вернутся в место вызова. Для того, чтобы завершить функцию и вернутся к месту ее вызова, используется [инструкция](Библиотека%20команд%20ассемблера.md#RET) `ret` (буквально команду `ret` можно интерпретировать как `pop rip`). Не стоит завершать функцию, если [[#Стек|стек]] не находится в том же положении, в котором был в начале инструкции. Иначе программа в качестве адреса возврата из [[#Стек|стека]] возьмет первую попавшуюся переменную, которая в этот момент будет на вершине стека, и скорее всего переход не удастся. При выполнении подпрограммы для завершения программы с системным выходом `exit` можно не писать возврат из подпрограммы, так как программа все равно уже не будет работать. -При этом инструкцию `call` можно заменить на инструкцию `jmp` в случае, если возврат из подпрограммы не подразумевается (к примеру, в подпрограмме выполняется системный вызов `exit`). +При этом [инструкцию](Библиотека%20команд%20ассемблера.md#CALL) `call` можно заменить на [инструкцию](Библиотека%20команд%20ассемблера.md#JMP) `jmp` в случае, если возврат из подпрограммы не подразумевается (к примеру, в подпрограмме выполняется системный вызов `exit`). ### Функции с аргументами >**Аргумент** - кусок данных, который нужен функции для работы. @@ -172,7 +172,7 @@ sub rsp, 24 Из-за того, что регистр `rbp` является callee-saved, его необходимо отдельно сохранять в начале вызываемой подпрограммы. Это показано в третьем способе выделения памяти в стеке. -Выделение памяти под стек также иногда называется прологом, а в ассемблере существует инструкция `enter`, которая реализует третий способ пролога. В то же время освобождение памяти в стеке также иногда называется эпилогом, и в ассемблере для него существует функция `leave`. +Выделение памяти под стек также иногда называется прологом, а в ассемблере существует [инструкция](Библиотека%20команд%20ассемблера.md#ENTER) `enter`, которая реализует третий способ пролога. В то же время освобождение памяти в стеке также иногда называется эпилогом, и в ассемблере для него существует [инструкция](Библиотека%20команд%20ассемблера.md#LEAVE) `leave`. ### Выравнивание стека При работе со стеком принято выравнивать значение стека по 16 байтам. Это значит, что при выравнивании стека под каждое значение внутри отводится по 16 байт. В самом начале стек изначально выравнен по 16, так как в начале программы у функции `_start` нет адреса возврата. diff --git a/2 курс/Языки программирования/Языки программирования.md b/2 курс/Языки программирования/Языки программирования.md index 942bb3b..87a6bcc 100644 --- a/2 курс/Языки программирования/Языки программирования.md +++ b/2 курс/Языки программирования/Языки программирования.md @@ -12,6 +12,7 @@ - [Гитлаб](https://gitlab.se.ifmo.ru/programming-languages/cse-programming-languages-fall-2026/main) ## Доп. материалы +- Заметки - [Библиотека команд ассемблера](Библиотека%20команд%20ассемблера.md) - Книга - [Engineering a Compiler](http://www.r-5.org/files/books/computers/compilers/writing/Keith_Cooper_Linda_Torczon-Engineering_a_Compiler-EN.pdf) - Keith D. Cooper - Книга - [Введение в теорию автоматов, языков и вычислений](https://djvu.online/file/iPQzGw3Q4wPsJ) - Хопкрофт, Мотвани, Ульман - Книга - [Introduction to the Theory of Computation](https://broman.dev/download/Introduction%20to%20the%20Theory%20of%20Computation%203rd%20Edition.pdf) - Sipser