При описании команд, необходимо указывать какие операнды в ней допустимы, а какие нет. | Местонахождение операнда | Обозначение | Запись на ассемблере | | ---------------------------- | ------------ | --------------------- | | В команде | i8, i16, i32 | Константное выражение | | В регистре общего назначения | r8, r16 | Имя регистра | | В сегментном регистре | sr | CS, DS, SS, ES | | В памяти | m8, m16, m32 | Адресное выражение | ## Команды пересылки 1. `MOV op1,op2` - по этой команде на место первого операнда пересылается значение второго операнда. Флаги команда не меняет. ```asm MOV AX, 500 ; AX := 500 MOV BL, DH ; BL := DH ``` ```asm MOV AX, 100 MOV DS, AX ``` Запрещено пересылать из одной ячейки памяти в другую, из одного сегментного регистра в другой, и записывать непосредственный операнд в сегментный регистр. | op1 | op2 | | ------------- | ---------------------------------- | | r8 | i8, r8, m8 (пересылка байтов) | | m8 | i8, r8 | | r16 | i16, r16, m16, sr (пересылка слов) | | sr (кроме CS) | m16, r16 | | m16 | i16, r16, sr | Размер пересылаемой величины определяется по типу операндов, указанных в команде. Если известны размеры обоих операндов, то эти размеры должны совпадать, иначе ассемблер зафиксирует ошибку. **Пример:** ```asm X DB ? ; TYPE X = BYTE Y DW ? ; TYPE Y = WORD MOV X, 0 ; (X - байт) MOV SI, 0 ; (SI - регистр размером в слово) MOV CH, X ; пересылка байта MOV DX, AL ; (ошибка: DX - слово, AL - байт) ``` 2. Оператор указания типа `PTR`: `<тип> PTR <выражение>`, где `<тип>` - это служебные слова BYTE, WORD, DWORD. Выражение может быть либо константным, либо адресным. Оператор `PTR` используется в двух случаях: 1) Когда типы операндов неизвестны, и поэтому необходимо явно указать тип одного из них. **Пример:** В регистре SI находится адрес некоторой ячейки памяти, и требуется записать 0 в эту ячейку. ```asm MOV BYTE PTR [SI], 0 MOV WORD PTR [SI], 0 MOV [SI] BYTE PTR 0 MOV [SI] WORD PTR 0 ``` 2) Когда необходимо изменить тип, указанный при описании переменной **Пример:** ```asm Z DW 1234h ; Z: 34h, Z+1: 12h MOV BYTE PTR Z, 0 ; Z: 00h, Z+1: 12h ``` 3. Команда перестановки двух операндов `XCHG`: ```asm XCHG XCHG op1, op2 ``` Флаги команда не меняет, операнды должны быть одного размера. | op1 | op2 | | --- | ---------------------------- | | r8 | r8, m8 (перестановка байтов) | | m8 | r8 | | r16 | r16, m16 (перестановка слов) | | m16 | r16 | **Пример:** ```asm MOV AX, 62 ; AX = 62 MOV SI, 135 ; SI = 135 XCHG AX, SI ; AX = 135, SI = 62 ``` ## Арифметические команды 1. **Сложение**: `ADD op1,op2`, **вычитание**:`SUB op1,op2`. | op1 | op2 | | --- | --------------------------------------- | | r8 | i8, r8, m8 (сложение/вычитание байтов) | | m8 | i8, r8 | | r16 | i16, r16, m16 (сложение/вычитание слов) | | m16 | i16, r16 | Меняются флаги переноса CF, переполнение OF, знака SF и нуля ZF. 2. **Увеличение на 1**: `INC op`) **уменьшение на 1**: `DEC op`. Допустимые операнды: `r8`, `m8`, `r16`, `m16`. Команды `INC` и `DEC` не меняют флаг переноса CF и занимают меньше места в памяти. 3. **Изменение знака числа**: `NEG op`. Допустимые операнды: `r8`, `m8`, `r16`, `m16`. Команда рассматривает свой операнд, как число со знаком, и меняет его на противоположный: ```asm MOV AH, 1 NEG AH ; AH = -1 ``` Если операнд равен -128, то операнд не меняется, флаг переполнения OF будет равен 1. Если операнд равен 0, флаг переноса CF будет равен 0, в других случаях - 1. 4. **Сложение с учетом переноса**: `ADC op1, op2`, **вычитание с учетом переноса**: `SBB op1, op2`. `ADC` - к сумме прибавляется значение CF. `SBB` - из разности вычитается CF. 5. **Умножение целых без знака**: `MUL op`, **умножение целых со знаком**: `IMUL op`. Операнд может быть либо в регистре, либо в памяти, но не может быть непосредственным операндом. Местоположение другого операнда фиксировано и явно в команде не участвует. При умножении байтов первый множитель берется из регистра AL, и не из какого другого. При умножении слов берется из регистра AX. Под результат умножения отводится в 2 раза больше места, чем под сомножители. При умножении байтов результат имеет размер слова и записывается в регистр AX (AH - старшие разряды, AL - младшие разряды). При умножении слов результат имеет размер двойного слова и записывается в 2 регистра (DX - старшие разряды, AX - младшие). **Пример:** ```asm N DB 10 MOV AL, 2 MUL N ; AX = 2 * 10 = 20 = 0014h (AH = 00h, AL = 14h) MOV AL, 26 MUL N ; AX = 26 * 10 = 260 = 0104h (AH = 01h, AL = 04h) MOV AX, 8 MOV BX, -1 IMUL BX ; (DX, AX) = -8 = 0FFFFFFF8h (DX = 0FFFFh, AX = 0FFF8h) ``` Чтобы узнать, умещается ли результат в формат сомножителей, необходимо проанализировать флаги CF и OF. Если оба флага равны 1, произведение занимает двойной формат. Если оба флага равны 0, то результат произведения байтов занимает регистр AL, а произведение слов - регистр AX. 6. **Деление целых без знака**: `DIV op`, **деление целых со знаком**: `IDIV op`. Операнд - это делитель, который может находится либо в регистре, либо в ячейке памяти. При делении слова на байт, делимое находится в регистре AX. При делении двойного слова на слово, делимое находится в двух регистрах AX и DX. В области целых чисел настоящее деление невозможно, и под делением понимают получение двух величин - неполного частного (DIV) и остатка от деления (MOD). Оба этих числа помещаются на место делимого. Старшая часть делимого заменяется на остаток от деления, а младшее - на неполное частное. Неполное частное и остаток имеют одинаковый размер, который совпадает с размером делителя. При делении возможно появление ошибки с название "деление на 0" или "переполнение". 2 случай - это когда неполное частное не вмещается в отведенное ему место. **Пример с ошибкой:** ```asm MOV AX, 600 MOV BH, 2 DIV BH ; 600 DIV 2 = 300, но 300 не вмещается в AL ``` ## Изменение размера числа 1. Расширение байта со знаком до слова: `CDW`. `AH := 00h`, если `AL ≥ 0` `AH := 0FFh`, если `AL < 0` **Пример:** ```asm MOV AL, 32 ; AL = 20h CBW ; AX = 0020h (число +32 как слово) MOV AL, -32 ; AL = 0E0H CBW ; AX = 0FFE0h (число -32 как слово) ``` 2. Расширение слова со знаком до двойного слова: `CWD` `DX := 0000h`, если `AX ≥ 0` `DX := 0FFFFh`, если `AX < 0`