Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование на языке Ассемблер. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
11.08.2026
Размер:
603 Кб
Скачать

ADD – прибавить второй операнд к первому.

SUB – вычесть второй операнд из первого.

CMP – вычесть второй операнд из первого только для флагов.

AND – логическое И между всеми битами двух операндов. При этом соблюдаются правила:

1 AND 1 = 1

1 AND 0 = 0

0 AND 1 = 0

0 AND 0 = 0

TEST – то же самое, что AND, но только для флагов.

OR – логическое ИЛИ между всеми битами двух операндов. При этом соблюдаются правила:

1 OR 1 = 1

1 OR 0 = 1

0 OR 1 = 1

0 OR 0 = 0

XOR – логическое XOR (исключающее ИЛИ) между всеми битами двух операндов. При этом соблюдаются правила:

1 XOR 1 = 0

1 XOR 0 = 1

0 XOR 1 = 1

0 XOR 0 = 0

Вторая группа: MUL, IMUL, DIV, IDIV

Эти типы операндов поддерживаются:

REG memory

REG: AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP.

memory: [BX], [BX+SI+7], переменная, и т. п.

Команды MUL и IMUL влияют только на флаги: CF, OF. Если результат превышает размер операнда, то эти фла-

ги установлены в 1, если результат умещается в размер операнда, то эти флаги установлены в 0.

31

Для команд DIV и IDIV флаги не определены. MUL – беззнаковое умножение:

если операнд – это байт:

AX = AL операнд;

если операнд – это слово:

(DX AX) = AX операнд.

IMUL – умножение со знаком: если операнд – это байт:

AX = AL операнд;

если операнд – это слово:

(DX AX) = AX операнд.

DIV – беззнаковое деление: если операнд – это байт:

AL = AX / операнд

AH = остаток (модуль);

если операнд – это слово:

AX = (DX AX) / операнд

DX = остаток (модуль). IDIV – деление со знаком:

если операнд – это байт:

AL = AX / операнд

AH = остаток (модуль);

если операнд – это слово:

AX = (DX AX) / операнд

DX = остаток (модуль).

Третья группа: INC, DEC, NOT, NEG

Эти типы операндов поддерживаются:

REG memory

REG: AX, BX, CX, DX, AH, AL, BL, BH, CH, CL, DH, DL, DI, SI, BP, SP.

memory: [BX], [BX+SI+7], переменная, и т. п.

32

Команды INC и DEC влияют только на флаги: ZF, SF, OF,

PF, AF.

Команда NOT не влияет ни на какие флаги!

Команда NEG влияет только на следующие флаги: CF, ZF,

SF, OF, PF, AF.

NOT – инвертирование каждого бита операнда.

NEG – меняет знак операнда (дополнение до двух). Обычно она инвертирует каждый бит операнда, а затем прибавляет к нему единицу. Например, 5 преобразуется в -5, а -2 преобразуется в 2.

33

7. УПРАВЛЕНИЕ ХОДОМ ПРОГРАММЫ

Управление ходом программы – очень важная вещь. Это то, что заставляет программу принимать решения в зависимости от поставленных условий.

7.1. Безусловные переходы

Основная команда, которая передает управление в другую точку программы, это JMP.

Основной синтаксис команды JMP:

JMP метка

Чтобы объявить метку, в программе необходимо написать её имя и в конце добавить двоеточие «:». Метка может быть любой комбинацией символов, но не должна начинаться с цифры. Например, ниже представлены три правильных объявления меток:

label1:

label2:

a:

Метка может быть объявлена на отдельной строке или перед любой другой командой, например:

x1:

MOV AX, 1 x2: MOV AX, 2

Ниже представлен пример программы с использованием команды JMP:

ORG 100h

 

MOV AX, 5

; записать в AX число 5

MOV BX, 2

; записать в ВX число 5

JMP calc

; перейти к 'calc'

back: JMP stop

; перейти к 'stop'

calc:

 

ADD AX, BX

; прибавить BX к AX

34

JMP back

; перейти к 'back'

stop:

 

RET

; вернуться в операционную систему

END

; директива для прекращения компиляции

Конечно, есть более простой путь для вычисления результата с двумя числами, но это хороший пример применения команды JMP.

Как можно видеть из этого примера, команда JMP может передавать управление другому участку программы, который может находиться как после этой команды, так и перед ней. Этот переход может быть осуществлен в пределах текущего сегмента кода (65535 байтов).

7.2. Короткие условные переходы

Подобно команде JMP, которая выполняет безусловный переход, существуют команды, которые осуществляют условный переход (переход, который осуществляется только в том случае, если выполняется определенное условие). Эти команды разделяются на три группы. Первая группа только проверяет отдельный флаг, вторая – сравнивает числа со знаком, третья – сравнивает числа без знака.

Команды перехода, проверяющие одиночный флаг, представлены в табл. 2.

 

 

 

 

 

Таблица 2

 

 

 

 

 

 

Команда

 

Описание

 

Условие

Обратная

 

 

команда

 

Переход,

если

«равно»

 

 

JZ,JE

(«ноль»). Т. е. если сравни-

ZF = 1

JNZ,JNE

ваемые значения равны, то ZF

 

= 1 и переход выполняется

 

 

JC,JB,JN

Переход, если есть перенос («ни-

CF = 1

JNC,JNB,

AE

же»,«невышеилиравно»)

JAE

35

Окончание табл. 2

Команда

Описание

Условие

Обратная

 

 

 

команда

JS

Переход по знаку

SF = 1

JNS

JO

Переход по переполнению

OF = 1

JNO

JPE, JP

Переход, если есть паритет

PF = 1

JPO

или паритет четный

 

 

 

JNC, JNB,

Переход, если нет переноса

CF = 0

JC, JB,

(«выше или равно» или «не

JAE

ниже»)

 

JNAE

 

 

 

JNS

Переход, если нет знака

SF = 0

JS

JNO

Переход, если нетпереполнения

OF = 0

JO

JPO,JNP

Переход, если нет паритета

PF = 0

JPE, JP

 

или паритет нечетный

 

 

Как видно из таблицы, существуют команды, которые выполняют одинаковые действия. Это нормально, они даже ассемблируются в одинаковый машинный код, поэтому необходимо запомнить, что при компиляции команды JE, после дизассемблирования будет получена команда JZ.

Различные имена используются для того, чтобы делать программы более легкими для понимания и кодирования.

Команды перехода для чисел со знаками представлены в табл. 3.

 

 

 

Таблица 3

 

 

 

 

Команда

Описание

Условие

Обратная

команда

JE, JZ

Переход,если«равно»(=).

ZF = 1

JNE, JNZ

Переход, если«ноль».

 

 

 

JNE, JNZ

Переход,если«неравно»(<>).

ZF = 0

JE, JZ

 

Переход,если«неноль».

 

 

 

Переход,если«больше»(>).

ZF = 0

 

JG, JNLE

Переход, если «не меньше или

and

JNG, JLE

 

равно»(not<=).

SF = OF

 

36

Окончание табл. 3

Команда

Описание

Условие

Обратная

 

 

 

команда

JL, JNGE

Переход,если«меньше»(<).

SF <> OF

JNL, JGE

Переход, если «не больше или

 

равно»(not >=).

 

 

 

Переход, если «больше или

 

 

JGE, JNL

равно» (>=).

SF = OF

JNGE, JL

Переход, если «не меньше»

 

(not <).

 

 

 

Переход, если «меньше или

ZF = 1

 

 

равно» (<=).

 

JLE, JNG

or

JNLE, JG

 

Переход, если «не больше»

SF <> OF

 

 

(not >).

 

 

В табл. 3 знак <> – означает «не равно».

Команды перехода для чисел без знаков представлены в табл. 4.

 

 

 

Таблица 4

 

 

 

 

Команда

Описание

Условие

Обратная

команда

JE, JZ

Переход, если «равно» (=).

ZF = 1

JNE, JNZ

Переход, если «ноль».

 

 

 

 

Переход, если «не равно»

 

 

JNE, JNZ

(<>).

ZF = 0

JE, JZ

 

Переход, если «не ноль».

 

 

JA, JNBE

Переход, если «выше» (>).

CF = 0

JNA, JBE

Переход, если «не ниже или

and

 

равно» (not <=).

ZF = 0

 

JB, JNAE,

Переход, если «ниже» (<).

 

JNB, JAE,

Переход, если «не выше или

CF = 1

JC

равно» (not >=).

JNC

 

 

Переход по переносу.

 

 

37

Окончание табл. 4

Команда

 

Описание

Условие

Обратная

 

 

 

 

 

команда

 

Переход, если «выше или

 

 

JAE, JNB,

равно» (>=).

 

CF = 0

JNAE, JB

JNC

Переход,если«нениже»(not <).

 

 

 

Переход, если«нетпереноса».

 

 

 

Переход,

если

«ниже или

CF = 1

 

JBE, JNA

равно» (<=).

 

JNBE, JA

 

or

Переход,

если

«не выше»

 

(not >).

 

 

ZF = 1

 

 

 

 

 

 

Обычно, если требуется сравнить два числовых значения, то используют команду CMP, она делает то же самое, что и команда SUB (вычитание), но не сохраняет результат, а влияет только на флаги.

Логика очень простая. Например, требуется сравнить числа 5 и 2:

5 – 2 = 3

результат – НЕ НОЛЬ (Флаг Нуля Zero Flag (ZF) установлен в 0).

Другой пример, требуется сравнить 7 и 7:

7 – 7 = 0

результат – НОЛЬ! (Флаг Нуля – Zero Flag (ZF) установлен в 1 и команды JZ или JE выполнят переход).

Нижеприведенпримеркоманды CMP и условногоперехода: include emu8086.inc

ORG 100h

MOV AL, 25 ; записать в AL число 25

MOV BL, 10 ; записать в BL число 10 CMP AL, BL ; сравнить AL с BL.

JE equal

; если AL = BL (ZF = 1), то перейти

 

; к метке equal

PUTC 'N'

; иначе, если AL <> BL, то продолжить

 

;выполнение

38

JMP stop

; программы

– напечатать 'N' и

 

; перейти к

метке stop

equal:

; если программа на этой метке,

PUTC 'Y'

; то AL

= BL, поэтому выводим на

 

; экран

'Y'

 

stop:

RET ; сюда приходим в любом случае

END

Попробуйте вышеописанный пример с различными числами в AL и BL, откройте флаги, щелкнув по кнопке [FLAGS]. Используйте [Single Step] – пошаговый режим и наблюдайте за происходящим. Не забывайте перекомпилировать и перезагружать вашу программу после каждого сделанного вами в ней изменения (используйте клавишу F5).

Все условные переходы имеют одно серьезное ограничение – в отличие от команды JMP, они могут выполнять переход только на 127 байтов вперед или на 128 байтов назад (необходимо учитывать, что большие команды ассемблируются в 3 и более байтов).

Но это ограничение можно легко преодолеть, используя следующий метод:

взять обратную команду из табл. 4 и выполнить переход

кметке label_x;

использовать команду JMP для перехода к нужному участку программы;

определить метку label_x: только после команды JMP (label_x: – может быть любым именем).

Пример:

include emu8086.inc ORG 100h

MOV AL, 25

;

записать в

AL

число 25

MOV BL,

10

;

записать в

BL

число 10

CMP AL,

BL ;

сравнить AL с

BL

JNE not_equal

; переход, если AL <> BL (ZF = 0)

39

JMP equal not_equal:

;представим, что здесь у нас

;размещается код, который ассемблируется

;более чем в 127 байтов...

PUTC 'N'

; если мы оказались здесь, то AL <> BL,

JMP stop

; тогда печатаем 'N', и

 

; переходим к метке stop

equal:

; если мы оказались здесь,

PUTC 'Y'

; то AL = BL, тогда печатаем 'Y'

stop:

 

RET

; сюда приходим в любом случае

END

 

Другой, реже используемый метод, представляет собой применение непосредственного значения (адреса) вместо метки. Если непосредственное значение начинается с символа '$', то выполняется относительный переход – переход относительно текущего адреса. Компилятор вычисляет команду, которая находится по заданному смещению, и выполняет переход непосредственно к ней. Например:

ORG 100h

;безусловный переход вперед

;пропускаем следующие два байта

JMP $2

a

DB

3

;

1

байт

b

DB

4

;

1

байт

;переход назад на 7 байтов, если BL <> 0

;(команда JMP занимает 2 байта)

MOV BL,9

DEC BL ; 2 байта

CMP BL, 0 ; 3 байта

JNE $-7

RET

END

40

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]