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

Архитектура вычислительных систем и Ассемблер с приложением методических указаний к лабораторным работам. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
2.6. Альтернативная арифметика 81
Подобная арифметика в целом циклична по модулюP, так что, в частности,
(P 1) + 1 = 0; ассоциативна и коммутативна.
Некоторые операции выполняются сложнее, чем в позиционных системах счис-
ления. Такие операции называются
немодульными.
Это, прежде всего,
сравнение
то есть установление порядка (установление равенства — модульная операция), и все операции, в реализации которых оно используется:
– контроль переполнения; – деление;
– квадратный корень и т. п. Из-за немодульности сравнения расширение модулярного представления на все целые числа возможно только в виде значения со знаком. При использовании для отрицательных чисел кода со смещением
(x) P x
кода
нет простого способа отличить отрицательное число от
x x + ξ
или дополнительного
положительного. На вещественные числа модулярное представление естественным путём не расширяется.
Модулярная арифметика позволяет реализовать очень быстрые вычисления над неотрицательными целыми числами, а также контролировать корректность ре­зультата в процессе вычислений, что позволяет обнаруживать аппаратные ошибки.
2.6.3. Арифметика с насыщением
— Чего? — спросил Дуб. — Стоять и не выпускать, — перевела Мергиона.
А. В. Жвалевский, И. Е. Мытько.
Личное дело Мергионы или Четыре чёртовы дюжины
,
В предыдущих разделах рассматривалась циклическая арифметика, то есть, если обрабатываемые числа находятся в диапазоне
[Min,Max]
,то
Max+1=
Minи Min1=Max. Это основная используемая в ЭВМ схема.
Для некоторых задач в случае выхода за границы допустимого диапазона удоб­нее схема с насыщением — если «правильный» результат операции превышает наибольшее представимое значение
Max
, то он считается равным
Max
, если он
меньше Min, то, соответственно, формируется результат Min.
Таким образом, Max+1=Maxи Min1=Min.
Арифметика с насыщением коммутативна, но неассоциативна, в частности
(Max− 1) − (Max− 1) = 0,
но
Max(1 + Max)+1=MaxMax+1=1.
Процессоры семейства x86 поддерживают арифметику с насыщением в рамках команд расширения MMX.
82 Глава 2. Представление данных
Арифметика чисел с плавающей запятой (раздел 2.8.2) не является арифмети­кой с насыщением.
2.7. Битовые операции
— Умная игра, — подтвердил Дубль таким же низким голосом, — клеточек куда больше, чем в крестиках-ноликах!
А. В. Жвалевский, И. Е. Мытько.
Девять подвигов Сена Аесли. Подвиги 5-9
Битовые операции — операции, производимые над цепочками битов.
Существует три основных класса битовых операций:
– поразрядные операции (not, and, or, xor); – операции расширения (увеличения разрядности); – сдвиги.
Все поразрядные операции рассматривают операнды как однородные цепочки битов; операции расширения и сдвиги делятся на два типа — знаковые, особым образом обрабатывающие старший (знаковый) бит цепочки, и беззнаковые.
2.7.1. Поразрядные операции
Почему так? Потому что развитое тело легче изучать, чем клеточку тела.
К. Маркс. Капитал
Поразрядные операции применяются к каждому разряду операнда (для унарных операций) или к каждой паре соответствующих разрядов операндов (для бинарных операций) независимо от соседних разрядов.
Так как один двоичный разряд может принимать только два значения, которые можно трактовать как «ложь» и «истина», набор поразрядных операций обычно включает все логические операции (таблица 2.7).
Логические операции над разрядами
Таблица 2.7
ab
00 01 10 11
¬a (not, !) a b (and, &) a b (or, |) a b (xor,ˆ)
1
0
000 011 011 110
2.7. Битовые операции 83
Для поразрядных операций применяются различные обозначения, наиболее популярные из них показаны в шапке таблицы 2.7. В последующих примерах используются обозначения, принятые в языке C++ (!, &, |,ˆ).
Результат в каждом разряде рассчитывается независимо от соседних (отсут­ствует перенос между разрядами). Разрядность результата соответствует разрядно­сти операндов, для бинарных операций разрядность обоих операндов должна быть одинаковой. Поразрядные операции не могут быть знаковыми или беззнаковыми: обработка старшего бита не отличается от остальных.
Таким образом, поразрядное отрицание (битовая инверсия, дополнение до единицы) — это унарная операция, где к каждому разряду единственного операнда применяется логическое отрицание:
!2
= ! 0000 0010 = 1111 1101 (2.65)
10
Полученное значение можно трактовать как тат как знаковый, либо как
25310, если интерпретировать его как беззнаковый. Ни
310, если интерпретировать резуль-
одно из этих двух значений здесь не будет «правильным» или «ошибочным».
Если трактовать операнды как знаковые и представленные в дополнительном коде, x :!x = x 1.
При этом необходимо помнить, что если операнд
210имеет б´ольшую раз-
рядность (и, соответственно, включает больше ведущих нулей), то и результат будет содержать больше ведущих единиц. Соответственно, в общем случае раз­рядностиNзначение
!210в знаковой интерпретации будет иметь значение
310,
а в беззнаковой — (2N− 3)10.
Поразрядное «и» (конъюнкция) — бинарная операция, к каждой паре разрядов операндов применяется логическое «и»:
3
&510= 0000 0011 & 0000 0101 = 0000 0001 = 1
10
10
(2.66)
разряд результата равен нулю, если хотя бы один операнд содержит ноль в соот­ветствующем разряде.
При помощи поразрядного «и» можно получить неотрицательный остаток от деления целого числаxна
2n. В этом случае второй операнд («маска») состоит
из n единиц: x mod 2n= x &(2n− 1).
mod 810= 18910&710=
189
10
= 1011 1101 & 0000 0111 = 0000 0101 = 5
10
(2.67)
Поразрядное «или» (дизъюнкция) — бинарная операция, к каждой паре разря­дов операндов применяется логическое «или»:
3
10|510
= 0000 0011 | 0000 0101 = 0000 0111 = 7
10
(2.68)
84 Глава 2. Представление данных
разряд результата равен единице, если хотя бы один операнд содержит единицу в соответствующем разряде.
Поразрядное исключающее «или» (также называется сложением по модулю два, но, в отличие от арифметической операции сложения, нет переноса между разрядами) — бинарная операция, к каждой паре разрядов операндов применяется исключающее «или»:
3
10ˆ510
= 0000 0011ˆ0000 0101 = 1111 0110 = 1010= 246
10
(2.69)
разряд результата равен единице, если один и только один операнд содержит единицу в соответствующем разряде.
Так как для одного разряда
b ∈{0, 1} :1⊕ b = ¬b
, для чисел любой
разрядности верно x :(1)ˆx =!x.
Поразрядные логические операции используются как в алгоритмах криптогра­фии, так и, в некоторых ситуациях, для ускорения арифметических вычислений. Последнее возможно, только если один из операндов является константой специ­фического вида.
2.7.2. Расширение целых чисел
...Даже самые абстрактные категории <...> представляют собой в такой же мере и продукт исторических условий и обладают полной значимостью только для этих условий и в их пределах.
К. Маркс. Капитал
Часто необходимо увеличить разрядность числа, сохранив его значение. В C++ подобное происходит, в частности, при присваивании переменных разного размера:
1 int i; 2 short int s = -1; 3 i=s; // расширение short int до int (знаковое)
Операция увеличения разрядности называется расширениемn-разрядного чис­лаxдоmразрядов (
m>n
). Младшиеnразрядов результата совпадают с расши-
ряемым значением x, старшие m n должны быть как-то инициализированы.
Существует две операции расширения, по-разному инициализирующие расши­ряемую часть:
беззнаковое расширение — расширяемая часть заполняется нулями (такая опе-
рация сохраняет значение беззнаковой интерпретации x);
знаковое расширение — расширяемая часть заполняется значением знакового
бита (сохраняет значение знаковой интерпретации x).
2.7. Битовые операции 85
В языках высокого уровня знаковость расширения определяется знаковостью ис­пользуемых типов (так, в C++ расширение
до
unsigned
unsigned
— беззнаковое). В ассемблере знаковое и беззнаковое рас-
short intдоint
— знаковое,
short
ширение выполняются разными командами.
В таблице 2.8 показаны примеры знакового и беззнакового расширения восьми­битных чисел до шестнадцати бит.
Знаковое и беззнаковое расширение
Таблица 2.8
Значение
bin hex dec
знак
dec
беззн
x (8 бит) 0000 0000 00 00
беззнаковое
−−−−−−→ 16 бит 0000 0000 0000 0000 0000 00
x
знаковое
−−−−−→ 16 бит 0000 0000 0000 0000 0000 00
x
x (8 бит) 0000 0001 01 11
беззнаковое
−−−−−−→ 16 бит 0000 0000 0000 0001 0001 11
x
знаковое
−−−−−→ 16 бит 0000 0000 0000 0001 0001 11
x
x (8 бит) 0000 1111 0F 15 15
беззнаковое
−−−−−−→ 16 бит 0000 0000 0000 1111 000F 15 15
x
знаковое
−−−−−→ 16 бит 0000 0000 0000 1111 000F 15 15
x
x (8 бит) 1000 0000 80 128 128
беззнаковое
−−−−−−→ 16 бит 0000 0000 1000 0000 0080 128 128
x
знаковое
x
−−−−−→ 16 бит 1111 1111 1000 0000 FF80 128 65 408
x (8 бит) 1111 1111 FF 1 255
беззнаковое
−−−−−−→ 16 бит 0000 0000 1111 1111 00FF 255 255
x
знаковое
−−−−−→ 16 бит 1111 1111 1111 1111 FFFF 1 65 535
x
Каждая строка таблицы соответствует одному значению (цепочке битов). Во втором столбце показано его двоичное представление, в третьем — шестнадца­теричное, в четвёртом — десятичное представление его знаковой интерпретации, в пятом — десятичное представление беззнаковой интерпретации. Строки сгруп­пированы по три — восьмибитное значениеx, его беззнаковое расширение до шестнадцати бит и знаковое расширение до того же размера.
Видно, что для неотрицательных (в знаковой интерпретации) чисел знаковое и беззнаковое расширение выполняется одинаково.
86 Глава 2. Представление данных
2.7.3. Битовые сдвиги
Заметьте: справа налево двигать могу и слева направо.
В. В. Маяковский. Человек
Битовые сдвиги — семейство бинарных операций с несимметричными операн­дами. Один из операндов представляет собой цепочку битов, второй — неотри­цательное целое число — величину сдвига. Цепочка битов смещается вправо или влево на указанное количество битов. Разрядность результата равна разрядности операнда-цепочки. Кроме явных операндов и результата, в сдвигах используется флаг переноса CF.
Сдвиг наnразрядов эквивалентен повторённомуnсдвигу на один разряд, соответственно, для простоты ниже рассматривается только сдвиги на один бит.
Как было сказано выше, сдвиги различаются направлением — вправо (в сто­рону младших разрядов) или влево (в сторону старших). Кроме того, при сдвиге крайний с одной стороны разряд выдвигается за пределы разрядной сетки (его зна­чение попадает в ячейку флага переносаCF), а крайняя ячейка с другой стороны освобождается.
В зависимости от способа заполнения освободившейся ячейки различаются следующие типы сдвига:
– знаковые (арифметические); – беззнаковые (логические);
– циклические. Ниже различные виды сдвигов рассматриваются на примере восьмибитных значе­ний.
Знаковый и беззнаковый сдвиги вправо
В случае беззнакового (логического) сдвига вправо (в сторону младших раз­рядов) освободившийся старший разряд инициализируется нулём (рис. 2.3, а). В случае знакового (арифметического) сдвига вправо — копией знакового бита (рис. 2.3, б).
Логический сдвиг вправо соответствует беззнаковому делению на2с остат­ком, арифметический — знаковому. Знаковое деление при этом выполняется по правилам математики, подразумевающим неотрицательный остаток даже при отри­цательном делимом, то есть при делении минус единицы на2частное равно минус единице, а остаток — плюс единице.
Остаток как для знакового, так и для беззнакового деления на2сдвигом
CF
на один бит равен биту
(вышедшему за разрядную сетку младшему биту
исходного числа).
2.7. Битовые операции 87
N 0
0
1 1 1 1 1 0 1 1
shr
0 1 1 1 1 1 0 1 1
а)
= 251
= 125
CF
CF
?
CF
N 0
1 1 1 1 1 0 1 1
sar
1 1 1 1 1 1 0 1 1
б)
= 5
= 3
CF
CF
?
CF
Рис. 2.3. Беззнаковый (а) и знаковый (б) сдвиги вправо
Сдвиг вправо наnразрядов соответствует делению на
2n, причём в случае
знакового (арифметического) сдвига отрицательных чисел также выполняется
«математическое» деление, подразумевающее неотрицательный остаток.
Во многих языках программирования (в частности, в C/C++) считается, что при делении знаковых чисел остаток может быть отрицательным, то есть при делении минус единицы на2частное будет равно нулю, а остаток — минус единице. Команды знакового деления ЭВМ реализуют именно эту схему.
Результат «программистского» деления отрицательного числаxна
2nв общем
случае не равен результату «математического» (подразумевающего неотрицатель­ный остаток и рассчитываемого сдвигом случае, когдаxделится на
2nнацело. Для всех остальных
x sar n
). Они совпадают только в том
x<0
результат «про-
граммистского» деления будет на единицу больше.
Таким образом, чтобы получить при помощи арифметического сдвига значение
«программистского» частного, необходимо до сдвига прибавить к отрицательному
делимому значение
2n− 1
. Для положительного делимого или нуля коррекция не
требуется.
Знаковый и беззнаковый сдвиг влево
В случае сдвига влево (в сторону старших разрядов) освободившийся младший бит инициализируется нулём (рис. 2.4).
Знаковый и беззнаковый (арифметический и логический) сдвиги влево не раз­личаются. Сдвиг влево на один бит эквивалентен умножению на2(так как разряд­ность результата равна разрядности исходной цепочки, неважно — знаковому или нет). Коррекция операндов не требуется.
Битовые сдвиги выполняются гораздо быстрее, чем умножение и деление с по­мощью специализированных команд. Соответственно, умножение и деление на специальные константные значения часто выполняются оптимизирующими компи­ляторами при помощи сдвигов или комбинации сдвигов и сложения.
88 Глава 2. Представление данных
CF
CF
?
CF
N 0
0 0 0 0 0 1 0 1
shl/sal
0 0 0 0 1 0 1 00
0
=5
=10
Рис. 2.4. Знаковый (беззнаковый) сдвиг влево
Циклические сдвиги
В случае простого циклического сдвига освободившаяся ячейка с одной сторо­ны замещается разрядом, вышедшим с другой стороны за разрядную сетку (рис. 2.5, а) и б).
CF
N 0
а)
N 0
б)
CF
Рис. 2.5. Простой циклический сдвиг: а) влево, б) вправо
В случае циклического сдвига через флаг переноса освободившаяся ячейка инициализируется значением флага переносаCF, а ячейка
CF
замещается разря-
дом, вышедшим за разрядную сетку (рис. 2.6, а) и б). Таким образом, результат зависит не только от операндов, но и от текущего значения CF.
CF
N 0
а)
N 0
б)
Рис. 2.6. Циклический сдвиг через флаг переноса: а) влево,
б) вправо
Если простой циклический сдвигN-разрядного числа циклически перемеща­ет разрядыN-битной цепочки, то сдвиг через флаг переноса —
(N +1)
цепочки (операнд + CF).
Циклические сдвиги не эквивалентны какой-либо арифметической операции. Они широко используются в криптографии.
CF
-битной
2.8. Представление вещественных чисел 89
2.8. Представление вещественных чисел
Опять скажу: никто не обнимет необъятного!
К. П. Прутков. Плоды раздумья. Мысли и афоризмы
Какой бы код ни использовался, с помощьюNбитов лучить только более
2Nзначений. При этом, в отличие от целых чисел, вещественных значений
в любом диапазоне
2Nразных кодовых комбинаций и, соответственно, представить не
[ν1,ν2] R
бесконечно много (причём эта бесконечность
b
...b1b0можно по-
N1
несчётна, то есть количество вещественных чисел, помещающихся на любом ин­тервале, превышает общее число существующих целых чисел).
Таким образом, для того, чтобы закодировать вещественные числа, необходи­мо не только ограничить допустимый диапазон, но и проредить его внутреннюю часть. Большую часть вещественных чисел описываемого диапазона
[ν1,ν2] R
невозможно точно представить в ЭВМ.
Представление вещественных чисел основано на описанной в разделе 2.3.4 позиционной двоичной записи.
2.8.1. Представление вещественных чисел с фиксированной запятой
Сие редко встречающееся явление требует двоякого объяснения.
М. В. Ломоносов. Явление Венеры на Солнце
Представим неотрицательное вещественное числоXв виде бесконечной дво­ичной дроби
(2.11)
, округлим доnразряда после запятой, обозначив результат
округления˘X:
X ˘X = x
· 2k+ ...+ x1· 21+ x0· 20+ x−1· 21+ ...+ x−n· 2n=
k
x
= x
· 2k+ ...+ x2+x0+
k
=
xk...x1x0,x−1...x−n, 0 xi< 2 — целые
1
2
+ ...+
x
n
=
n
2
(2.70)
и последовательно запишем цифры с младшей цифры
x−nи младшего бита
x−n,...xkв биты кода
b0. После старшей цифры
b0,...b
N1
xkзаписываются
, начиная
нули. Таким образом, изNбитов, отведённых под представление числа, для дробной части используется n, для целой остаётся N n.
˘
X = b
N1
Nn1
· 2
+ ...+ b
b
=
N1
n+1
...bn,b
· 2+bn+
...b
n1
b
n1
+ ...+
2
0
b
0
=
n
2
(2.71)
90 Глава 2. Представление данных
Двоичная запятая, отделяющая дробную часть от целой, всегда расположена между разрядамиnи
n 1
. Соответственно, такой способ кодирования называется
представлением с фиксированной запятой.
Целая часть числа может принимать значения от0до
0=0,00 ...00до1
от
1
= 0,11 ...11
n
2
(всего
2nзначений). Таким образом,
числа, представимые в формате с фиксированной запятой с помощью из которых отведены под дробную часть, заключены в диапазоне На каждом полуинтервале
[ν, ν +1)
находится
2nчисел, представимых в виде
2
Nn
1
, дробная —
N
Nn
0, 2
бит,
1
n
2
с фиксированной запятой с n-битной дробной частью.
Точность двоичных чисел с фиксированной запятой
При округлении вещественного числа
X 0, 2
после запятой абсолютная погрешность округления не превышает
  
X ˘X
 
<
Nn
доnдвоичных разрядов
1
n
2
1
:
n
2
(2.72)
относительная погрешность увеличивается при уменьшении абсолютной величины числа:
 
X ˘X
  
X
  
<
 
1
2n·|X |
(2.73)
n
.
Таким образом, абсолютная погрешность округления при сохранении числа
X
в формат с фиксированной запятой постоянна и зависит только от характеристик формата (от количества n бит, отведённых под дробную часть).
Арифметика чисел с фиксированной запятой
n1
n
получим целое число:
...b0=
b
n1
+ ...+
2
n1
· 2
n1
+ ...+ b0· 20=
b
0
=
n
2
Нетрудно заметить, что при умножении (2.71) на 2
n
= b
=2
N1
n
·b
· 2
N1
N1
=
2
· 2
+ ...+ b
b
N1
·˘X =2b
Nn1
...bnb
+ ...+ b
n+1
n1
· 2
...b0= x, x ∈{0, 1,...2N− 1}
N1
n+1
n+1
+ b2n+ b
...bn,b
· 2+bn+
(2.74) то есть существует взаимно однозначное соответствие между числами с фиксиро­ванной запятой и целыми числами в диапазоне0, 2N− 1:
x
˘
X =
n
2
(2.75)
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]