Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
прогр.docx
Скачиваний:
23
Добавлен:
21.12.2018
Размер:
2.58 Mб
Скачать

Лекция № 4. Условные переходы. Арифметиченские команды. Bcd числа.

Микропроцессор имеет 18 команд условного перехода, позволяющие проверить:

отношение между операндами со знаком (больше-меньше);

отношение между операндами без знака (выше-ниже);

состояние арифметических флагов zf,sf, cf, of, pf.

Команды условного перехода имеют одинаковый синтаксис:

Jcc метка_перехода

Межсегментной передачи управления в условных переходах не допускается (максимальный переход равен размеру сегмента).

Источниками условия для перехода могут быть:

любая команда, изменяющая состояние арифметических флагов;

команда сравнения cmp;

состояние регистра ecx/cx.

Команда cmp выполняет вычитание операторов и устанавливает флаги, не записывает результат вычитания на место первого операнда.

Cmp операнд_1, операнд_2

Значения аббревиатур в названии команды jcc:

Пример 7: сравним очередной элемент массива с 5:

Команды условного перехода и флаги

cmp x, y

Опкод

Значение(переход,если...)

Условие

JA

Jump if above (X > Y)

CF=0 & ZF=0

JAE

Jump if above or equal (X >= Y)

CF=0

JB

Jump if below (X < Y)

CF=1

JBE

Jump if below or equal (X < Y)

CF=1 or ZF=1

JC

Jump if carry (cf=1)

CF=1

JCXZ

Jump if CX=0

регистр CX=0

JE (то же, что и JZ)

Jump if equal (X = Y)

ZF=1

JG

Jump if greater (signed) (X > Y)

ZF=0 & SF=OF

JGE

Jump if greater or equal (signed) (X >= Y)

SF=OF

JL

Jump if less (signed) (X < Y)

SF != OF

JLE

Jump if less or equal (signed) (X <= Y)

ZF=1 or SF!=OF

JMP

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

-

JNA

Jump if not above (X <= Y)

CF=1 or ZF=1

JNAE

Jump if not above or equal (X < Y)

CF=1

JNB

Jump if not below (X >= Y)

CF=0

JNBE

Jump if not below or equal (X > Y)

CF=1 & ZF=0

JNC

Jump if not carry (cf=0)

CF=0

JNE

Jump if not equal (X != Y)

ZF=0

JNG

Jump if not greater (signed) (X <= Y)

ZF=1 or SF!=OF

JNGE

Jump if not greater or equal (signed) (X < Y)

SF!=OF

JNL

Jump if not less (signed) (X >= Y)

SF=OF

JNLE

Jump if not less or equal (signed) (X > Y)

ZF=0 & SF=OF

JNO

Jump if not overflow (signed) (of=0)

OF=0

JNP

Jump if no parity (pf=0)

PF=0

JNS

Jump if not signed (signed) (sf=0)

SF=0

JNZ

Jump if not zero (X != Y)

ZF=0

JO

Jump if overflow (signed) (of=1)

OF=1

JP

Jump if parity (pf=1)

PF=1

JP

Jump if parity (pf=1)

PF=1

JPE

Jump if parity even

PF=1

JPO

Jump if parity odd

PF=0

JS

Jump if signed (signed)

SF=1

JZ

Jump if zero (X = Y)

ZF=1

Пример 8: надо преобразовать строчные буквы в прописные. Строчным буквам в таблице ASCII символов соответствует диапазон 61h-7ah, прописным – 41h-5ah. Для выполнения преобразования между строчными и прописными буквами достаточно инвертировать 5 бит.

Например:

а – 01100001 z – 01111010

А – 01000001 Z – 01011010

Таблица ASCII кодов.

0

1

2

3

4

5

6

7

8

9

A

B

C

D

E

F

0

...

...

0

@

P

'

Р

А

Р

а

...

...

...

р

Ё

1

...

...

!

1

A

Q

a

Q

Б

С

б

...

...

...

с

ё

2

...

...

"

2

B

R

b

R

В

Т

в

...

...

...

т

Є

3

...

...

#

3

C

S

c

S

Г

У

г

...

...

...

у

є

4

...

...

$

4

D

T

d

T

Д

Ф

д

...

...

...

ф

Ї

5

...

...

%

5

E

U

e

U

Е

Х

е

...

...

...

х

ї

6

...

...

&

6

F

V

f

V

Ж

Ц

ж

...

...

...

ц

Ў

7

...

...

'

7

G

W

g

W

З

Ч

з

...

...

...

ч

ў

8

...

...

(

8

H

X

h

X

И

Ш

и

...

...

...

ш

°

9

...

...

)

9

I

Y

i

Y

Й

Щ

й

...

...

...

щ

A

...

...

*

:

J

Z

j

Z

К

Ъ

к

...

...

...

ъ

·

B

...

...

+

;

K

[

k

{

Л

Ы

л

...

...

...

ы

C

...

...

,

<

L

\

l

|

М

Ь

м

...

...

...

ь

D

...

...

-

=

M

]

m

}

Н

Э

н

...

...

...

э

¤

E

...

...

.

>

N

^

n

~

О

Ю

о

...

...

...

ю

F

...

...

/

?

O

_

o

¤

П

Я

п

...

...

...

я

Команды условного перехода и регистр есх/сх.

Регистр есх/сх выполняет роль счётчика в командах управления циклами и при работе с цепочками символов.

Синтаксис этой команды таков:

Jcxz метка_перехода (Jump if is zero) – прыжок, если сх ноль;

jecxz метка_перехода (Jump equal ecx zero) – переход, если есх ноль.

В отличие от других команд условной передачи управления, команды Jcxz/ jecxz могут адресовать только короткие переходы – на -128 байт или на +127 байт от следующей за ней командой.

Организация циклов

В системе команд микропроцессора существует три команды для работы с циклами. Данные команды:

1) loop метка_перехода – повторить цикл. Работа команды заключается в выполнении следующих действий:

а) декремента регистра есх/сх;

б) сравнение регистра есх/сх с нулём;

если (есх/сх)>0, то управление передаётся на метку перехода;

если (есх/сх)=0, то управление передаётся на следующую после loop команду;

2) loope/loopz метка_перехода – повторить цикл пока сх=0 или zf=0. Команды loope и loopz – абсолютные синонимы. Работа команд заключается в выполнении следующих действий:

а) декремента регистра есх/сх;

б) сравнение регистра есх/сх с нулём;

в) анализа состояния флага нуля zf;

если (есх/сх)>0, и zf=1, управление передаётся на метку перехода;

если (есх/сх)=0, или zf=0, управление передаётся на следующую после loop команду;

3) loopne/loopnz метка_перехода – повторить цикл пока сх<>0 или zf=1. Команды loope и loopz – абсолютные синонимы. Работа команд заключается в выполнении следующих действий:

а) декремента регистра есх/сх;

б) сравнение регистра есх/сх с нулём;

в) анализа состояния флага нуля zf;

если (есх/сх)>0, и zf=0, управление передаётся на метку перехода;

если (есх/сх)=0, или zf=1, управление передаётся на следующую после loop команду;

Команды loop loope/loopz и loopne/loopnz реализуют только короткие переходы (от -128 до _127 байтов). Для работы с длинными циклами необходимо использовать команду jmp.

При работе с вложенными циклами возникает проблема сохранения значения счётчика внешнего цикла есх/сх на время выполнения внутреннего цикла. Для этого можно использовать регистры, ячейки памяти или стек.

Пример программы, содержащей три цикла вложенных один в другой.

Сложение двоичных чисел без знака

Если при сложении результат превышает размерность поля операнда, то результат оказывается неверным. Например: 254+5=259 (11111110+0000101=1 00000011). Для фиксирования ситуации выхода за разрядную сетку результата предназначен флаг переноса cf. Поэтому после операции сложения в программе предполагается включение участков кода, в которых анализируется флаг cf. Это можно сделать с помощью команды условного перехода jc <метка>.

В системе команд микропроцессора имеются три команды двоичного сложения:

INC <операнд> ; операция инкремента, то есть увеличение значения операнда на 1.

ADD <операнд_1><операнд_2>;

Принцип действия:

операнд_1=операнд_1+операнд_2.

В этой команде нельзя использовать переменную одновременно и для опернда_1, и для операнда_2. Команда ADD не различает числа со знаком и без знака.

ADC <операнд_1><операнд_2>; команда сложения с учётом флага переноса cf.

Принцип действия:

операнд_1=операнд_1+операнд_2+значение_cf.

Имеющиеся варианты приёмника и источник:

Операнд_1

Операнд_2

пример

регистр

регистр

add ecx, edx

регистр

память

add ecx, dword ptr [104h]/add ecx, [edx]

регистр

значение

add eax, 102

память

значение

add dword ptr [401231h], 80

память

регистр

add dword ptr [401231h], edx

Сложим, например, два 64-битных целых числа: одно число находится в регистрах EDX:EAX, а другое в регистрах ЕВХ:ЕСХ:

add eax,ecx

adc edx,ebx

Если при сложении младших двойных слов произошел перенос из старшего разряда (флаг CF=1), то он будет учтен следующей командой ADC.

Вычислим сумму 254+17 в регистр ах. При этом известно, что результат сложения выходит за границы операнда.

– XADD <операнд_1><операнд_2>; выполняет команду «обменять между собой и сложить».

Выполняет сложение, помещает содержимое операнд_1 в операнд_2, — сумму операндов — в операнд_1. Операнд_2 всегда регистр, операнд_1 может быть регистром и переменной.

Сложение двоичных чисел со знаком.

При сложении чисел с одинаковым знаком необходимо учитывать значение флага переполнения of в регистре eflags (бит 11).

Пример1.

30566=0111011101100110

+

00687=0000001010101111

=

31253=0111101000010101 – результат правильный (sf=0; of=0).

Пример2.

30566=0111011101100110

+

30566=0111011101100110

=

61132=1110111011001100 – результат правильный, но значение считается отрицательное (в старшем бите 1, sf=1; of=0).

Пример3.

-30566= 1000100010011010 (дополнительный код)

+

-04875= 1110110011110101 (дополнительный код)

=

-35441<>1 0111010110001111 – результат неправильный, так как получилось положительное число 95 631 (в старшем бите 0, sf=0; of=1).

Для того, чтобы получить правильный ответ необходимо:

а) инвертировать результат: 1000101001110000

б) прибавить 1: 1000101001110000+1=1000101001110001b

35441d

в) или выполнить команду neg(0111010110001111)=1000101001110001b=

=35441d

Пример4. (sf=1; of=1)

-4875= 1110110011110101

+

-4875= 1110110011110101

=

-9750<>1 1101100111101010b (121 322d) – результат неправильный.

Neg(1101100111101010b)=0010011000010110b=9750d

Таким образом, ситуация переполнения при сложении чисел с одинаковым знаком (установка флага of в 1) происходит при переносе:

  1. из 14-го разряда (для положительных чисел);

  2. из 15-го разряда (для отрицательных чисел).

Переполнения не происходит (флаг of сбрасывается в 0), если есть перенос из обоих разрядов или перенос отсутствует в обоих разрядах.

При сложении чисел с одинаковыми знаками может быть следующая ситуация:

  1. sf=0; of=0 => в приёмнике результат положительный и правильный;

  2. sf=1; of=0 => в приёмнике результат правильный, но он считается отрицательным, так как sf=1. Работать с результатом необходимо как с положительным числом;

  3. sf=0; of=1 => в приёмнике результат в дополнительном коде, необходимо применять команду neg и работать с результатом как с отрицательным числом;

  4. sf=1; of=1 => в приёмнике результат в дополнительном коде, необходимо применять команду neg и работать с результатом как с отрицательным числом;

Правильный процесс сложения чисел со знаком и без знака необходимо проводить, анализируя флаги cf и of. Состояние флагов после выполнения команд ADD, ADC, INC сведено в табл. 1.

Таблица 1.

Сложение чисел с разными знаками

Пример 1: найдём сумму чисел -6+7. Для чисел отведено 2 байта. Для этого -6d (110b) представим в дополнительном коде: 0000000000000110 инвертируем, получим:

1111111111111001

+

0000000000000001

=

11111111111110102 =6553010 =fffa16 =-6d

Тогда:

mov ax,FFFAh

mov dx, 7h

add ax,dx

1111111111111010

+

0000000000000111

=

1 0000000000000001b=65537d (sf=0; cf=1)

fffah+7h=1 0001h – результат не помещается в регистр АХ, будет установлен флаг переноса cf в 1. Если значение cf проигнорировать, то оставшееся в АХ значение будет правильным.

Пример 2: найдём сумму 25+(-300). -300d=1111111011010100b

0000000000011001

+

1111111011010100

=

11111110111011012 =6526110 = -27510 (sf=1; cf=0)

Результат в дополнительном коде.