**Машинный язык** - это комбинация строго организованных последовательностей 0 и 1. Компьютер понимает только свой машинный язык. В 50-е годы XX века программисты стали использовать символический аналог машинного языка, который назвали **языком ассемблера**. Этот язык точно отображает особенности машинного языка, поэтому для каждого типа компьютера он свой.  
**Алфавит ассемблера:**
- Все латинские буквы: A-Z, a-z (прописные и строчные эквивалентны)
- Цифры: 0-9
- Специальные знаки: \_, \?, \@, \$, \&
- Разделители: ,, ., \[, \], (, ), <, >, {, }, +, /, \*, %, !, "", \\, =, #, ^
  
**Идентификатор** - это последовательность допустимых символов для обозначения имен переменных и методов. Длина может составлять 256 символов, а транслятор воспринимает первые 32 символа. Идентификатор не может начинаться с цифры. Точка может быть только первым символом.  
**Ключевые слова** - это служебные символы языка ассемблер, к которым относятся названия регистров и операторы. Целые числа могут записываться в десятичной, двоичной, 16-ричной, реже в восьмеричной системе счисления.  
Символы и строки заключаются либо в одинарные, либо в двойные кавычки. В качестве символов можно использовать русские буквы. В строках прописные и строчные символы не эквивалентны.  
**Программа на языке ассемблер** - это последовательность предложений, каждый из которых записывается в отельной строке. Переносить на другую строку **нельзя**.  
По смыслу все предложения делятся на 3 группы:  
- Комментарии
- Команды
- Директивы
## Комментарии
**Комментарием** считается любая строка, начинающаяся со знака ;, либо пустая строка. Также допустим многострочный комментарий, который начинается со слова `COMMENT <маркер><текст>`, где `COMMENT` - директива языка ассемблер. Маркер - это любой символ, кроме пробела. Концом комментария считается конец строки, в которой снова в любой позиции встретился этот же маркер.
```asm
COMMENT * это все
является комментарием
к примеру * и это тоже
```
Многострочный комментарий обычно используется для временного исключения фрагмента программы.  
## Команды
**Предложения-команды** - это символьная форма записи машинных команд.  
Синтаксис команд: `[<метка>:] <мнемокод> [<операнды>] [;<комментарий>]`  
**Мнемокод** - это служебное слово, указывающее в символьной форме операцию, которую должна выполнить команда.  
## Директивы
**Директивы** - это приказы ассемблеру со следующим синтаксисом: `[<имя>] <название директивы> [<операнды>] [;<комментарий>]`. Например: 
```asm
X DB 1, -2, OFFh; массив X, состоящий из трех элементов
```
#### Директивы определения данных размером в байт, слово и двойное слово
**DB** - директива определения данных размером в байт.  
Синтаксис: `[<имя>] DB <операнд>{, <операнд>}`.  
Встречая такую директиву, ассемблер вычисляет операнды и записывает их значения в последовательные байты памяти. Первому из этих байтов даётся указанное имя, по которому на этот байт можно ссылаться из других мест программы.  
Существует два основных  способа задания операндов: 
1) **?** - знак неопределенного значения:
```asm
X DB ?
```
Для переменной X отводится 1 байт памяти, в который ничего не записывается. Выделив байт под переменную, ассемблер запоминает его адрес. Когда в тексте программы встретится данное имя, ассемблер заменит его на адрес, который принято называть значением имени X. Размер переменной в памяти называется **типом имени переменной**. Тогда значение и тип имени переменной однозначно определяют ячейку, обозначаемую этим именем. В ассемблере есть оператор типа `TYPE <имя>`. Значением этого оператора является размер ячейки, выделенной под переменную в байтах:
```asm
TYPE X ; = BYTE = 1
```
2) Константное выражение от -128 до 255:
```asm
A DB 254 ; 0FEh
B DB 17h ; 17h
C DB "*" ; 2Ah
```
При описании переменной-массива имя даётся его первому элементу, остальные остаются безымянными:
```asm
M DB 2
DB -2
DB ?
DB "*"
```
или:
```asm
N DB 2, -2, ?, "*"
```
![Хранение массива в памяти](../Pictures/03_01.%20Хранение%20массива%20в%20памяти.png)  
Таким образом, в памяти будет выделено 4 ячейки памяти размером в байт:
```asm
TYPE M ; = 1
```
Для ссылок на другие байты массива используют ссылки вида `M+k`, где `k` - целое число. Т. е., `M+1` - адрес байта со значением `FE`:
```asm
M + 1 ; адрес байта со значением FE
M + 3 ; адрес байта со значением '*' (2A)
```
Если несколько соседних операндов - символы, их можно объединить в строку:
```asm
S DB 'a'
DB 'b'
DB 'c'
```
также возможны другие варианты написания:
```asm
S DB 'abc'
S DB 'a', 'b', 'c'
S DB 'ab', 'c'
S DB 'a', 'bc'
; TYPE S = 1
```
Если необходимо описать байтовый массив, состоящий из нескольких байтовых элементов, можно использовать конструкцию повторения - `DUP()`:
```asm
R DB 0,0,0,0,0,0,0,0
R DB 8 DUP(0)
```
где 8 - коэффициент повторения, `DUP` - служебное слово, в круглых скобках - повторяемая величина.  
Точно также можно описать двумерный массив:
```asm
G DB 10 DUP(20 DUP(?))
```
**DW** - директива определения данных размером в слово.
```asm
A DW ? ; TYPE A = 1
B DW 1234h ; TYPE B = 2
C DW -2 ; TYPE C = 2
S1 DW `01` ; TYPE S1 = 2
E DW 40000, 3 DUP(?) ; TYPE E = 2
```
В качестве операнда директивы `DW` может быть указано адресное выражение, то есть выражение, значение которого является адрес:
```asm
C DB ?
D DW C
```
Ассемблер записывает в слово, выделенное под переменную `D`, адрес переменной `C`, который становится начальным значением переменной `D`.  
**DD** - директива определения данных размером в двойное слово.
Диапазон значений:
- Целые числа: от $−2^{31}$ до $2^{32}−1$
- Константные выражения от $−2^{15}$ до $2^{16}−1$, т.к. все выражения вычисляются в области 16-битовых чисел
```asm
A DD ? ; TYPE A = 4
B DD 123456h ; TYPE B = 4
C DD 33 DUP(?) ; TYPE C = 4
C DB ?
D DD C
```
Ассемблер заменяет имя переменной `C` на адресную пару? состоящую из сегмента и смещения имени внутри сегмента.
#### Директива эквивалентности
```asm
<имя> EQU <операнд>
```
Операнд может быть:
1. **Операнд-имя**. Если в правой части директивы указанно имя регистра, переменной или константы, тогда имя слева объявляется синонимом данного имени, и все последующие вхождения в текст программы этого имени-синонима ассемблер будет заменять на имя, указанное справа:
```asm
A DW ?
B EQU A
C DW B ; эквивалентно C DW A
```
2. **Операнд - константное выражение**:
```asm
N EQU 100 ; N - константа со значением 100
K EQU 2*N-1 ; K - константа со значением 199
```
Все последующие вхождения в текст программы имени константы ассемблер будет заменять на значение этой константы.  
3. **Операнд - любой текст**:
```asm
S EQU "Привет"
```
#### Директива присваивания
Эта директива определяет константу с именем, указанным слева и числовым значением, равным значению выражения справа. Однако, данная константа может менять свое значение.
```asm
K = 10
A DW K ; эквивалентно A DW 10
K = K + 4
B DB k ; эквивалентно B DB 14
```
**Пример 1:** чему равны переменные `A`, `B`?
```asm
K = 1
N EQU K
A DW N 
K = 2
B DB N
; N = 1
; A = 1
; B = 2
```
**Пример 2:** чему равны переменные `C`, `D`?
```asm
K = 1
N EQU K + 10
C DW N
K = 2
D DW N
; N = 11
; C = 11
; D = 11
```
Выражения ассемблера вычисляются не во время выполнения программы, а во время ее трансляции, в отличие от языков программирования высокого уровня. Встретив в тексте программы выражение, ассемблер вычисляет его и полученное значение записывает в программу. Поэтому в выражениях нельзя использовать величины, которые станут известны во время выполнения программы.  
**Приоритет операций:**
1. (), \[\], LENGHT, SIZE, WIDTH, MASK
2. .
3. :
4. PTR, OFFSET, SEG, TYPE, THIS
5. HIGH, LOW
6. Одноместные +, -
7. \[\] \*, /, MOD, SHL, SHR
8. Двуместные +, -
9. EQ, NE, LT, GT, GE
10. NOT
11. AND
12. OR, XOR
13. SHORT, TYPE 
