## Безусловный переход. Оператор SHORT Команды перехода не меняют флаги. В ЭВМ используются несколько машинных команд безусловного перехода, но на ассемблере они все обозначаются одинаково: `JMP <метка>`. Определитель тем или иным способом указывает адрес перехода, т. е. адрес команды, которая будет выписана следующей. #### 1. Прямой переход В качестве оператора указывается метка той команды, на которую передается управление. ```asm JMP L ... L: MOV AX, 0 ``` В ЭВМ имеется 2 машинные команды прямого перехода. В одной из них относительный адрес перехода задается в виде байта (**короткий прямой переход**), а в другой команде - в виде слова (**длинный прямой переход**). В этих командах операнд рассматривается как целое число со знаком, поэтому возможен переход и вперед, и назад. Встречая символьную команду, ассемблер вычисляет разность между адресом метки и адресом самой команды перехода, и оценивает величину этой разности. Если разность укладывается в байт, то ассемблер формирует команду короткого перехода. Если разность большая - формируется команда длинного перехода. Однако сделать этот выбор ассемблер может, если метка описана до команды перехода. Т. е., метка является ссылкой назад. При ссылке вперед ассемблер не знает адрес метки и на всякий случай формирует команду длинного перехода. Однако, программист может предупредить ассемблер, что переход будет коротким, с помощью оператора `SHORT`, который ставится в команде перехода перед меткой: ```asm JMP SHORT L ``` Если переход оказывается длинным, то ассемблер выдаст ошибку. #### 2. Косвенный переход В этом случае в команде перехода указывается не сам адрес перехода, а то место (ячейка или регистр), где находится этот адрес, т. е. содержание регистра/ячейки рассматривается как адрес некоторой команды, по которому и делятся переход. ## Команды сравнения и условного перехода Команда сравнения: `CMP op1, op2`. Условный переход формируется в 2 шага: 1. Сравниваются некоторые величины и соответствующим образом формируются флаги (`CMP`) 2. В зависимости от значений флагов выписывается переход Команда `CMP` аналогична команде `SUB` (вычитание), однако результат никуда не записывается, главный эффект - это установка флагов. Команда условного перехода: `Jxx <метка>`. Все команды условного перехода делятся на 3 группы: 1. Команды, которые ставятся после `CMP` В их мнемокодах с помощью определенных букв описывается тот исход сравнения, при котором нужно сделать переход: - **E** – equal (равно) - **N** – not (не, отрицание) - **G** – greater (больше) – для чисел со знаком - **L** – less (меньше) – для чисел со знаком - **A** – above (больше) – для чисел без знака - **B** – below (меньше) – для чисел без знака 2. Команды, которые реагируют на значение флага и не используют команду `CMP` |Мнемокод|Условие перехода| |:-:|:-:| |JZ|ZF=1| |JS|SF=1| |JC|CF=1| |JO|OF=1| |JP|PF=1| |JNZ|ZF=0| |JNS|SF=0| |JNC|CF=0| |JNO|OF=0| |JNP|PF=0| В этих командах указывается первая буква правого флага. И если переход должен быть выполнен при значении 1, и N, если значение флага равно 0. ```asm MOV AL, A MUL A JC ERROR ; A * A > 255 (CF = 1) → ERROR ADD AL, B JC ERROR ; A * A + B > 255 (CF = 1) → ERROR MOV C, AL ... ERROR: ... ``` 3. Команда, проверяющая значение регистра счетчика CX ```asm JCXZ <метка> ; (if cx := 0 then goto <метка>) ``` ## Команды управления циклом #### 1. Команда LOOP ```asm MOV CX, N ; CX – счетчик цикла L: ... ... ; тело цикла DEC CX ; CX := CX - 1 CMP CX, 0 ; CX = 0? JNE L ; CX <> 0 → L ``` ```asm MOV CX, N L: ... ... ; тело цикла LOOP L ``` **Пример:** найти N! и записать результат в регистр AX, где N – байтовая переменная. ```asm MOV AX, 1 ; AX := 1 MOV CL, N ; CX := N как слово (счетчик цикла) MOV CH, 0 ; CX := N как слово (счетчик цикла) JCXZ F1 ; N = 0 MOV SI, 1 ; i = 1 F: MUL SI ; (DX, AX) := AX * i (DX = 0) INC SI ; i := i + 1 LOOP F F1: ... ``` #### 2. команды LOOPE/LOOPZ и LOOPNE/LOOPNZ `LOOPE <метка>` и `LOOPZ <метка>`. **Пример:** записать в регистр BL наименьшее число из отрезка \[2, K\], на которое не делится число N (N и K – байтовые переменные, 2 ≤ K < N) или записать 0, если такого числа нет. ```asm MOV DL, N MOV DH, 0 MOV CL, K MOV CH, 0 DEC CX ; CX := K-1 (счетчик цикла) MOV BL, 1 DV: INC BL ; очередное число из [2, K] MOV AX, DX DIV BL ; AH := N mod BL CMP AH, 0 ; mod = 0? LOOPE DV ; цикл CX раз и пока mod = 0 JNE DV1 ; mod <> 0 → DV1 MOV BL, 0 ; нет искомого числа DV1: ... ```