Для того чтобы освоить программирование в машинных кодах (на
языке Ассемблера), необходимо знать, как организовано хранение информации в
ячейках памяти и в регистрах процессора.
Основной единицей информации является байт, который в
свою очередь состоит из восьми битов. Бит может быть включен (равен 1) или
выключен (равен 0), т.е. может принимать только два значения, а байт,
соответственно, может принимать 256 (два в восьмой степени) значений и имеет
диапазон от 0 до 255.
Те числа, с которыми мы имеем дело в повседневной
практике, называются десятичными. Они строятся из разрядов (единицы, десятки,
сотни и т.д.), каждый из которых может быть выражен степенью числа 10.
Так, 567 = 5*102 + 6*101 + 7*100
Компьютеру работать в десятичной системе очень неудобно.
Поскольку информация в нем представлена электрическими зарядами и можно
выделить только два устойчивых состояния (есть заряд/нет заряда), то самое
удобное - это хранить числа в компьютере в двоичной системе. Например, обычное десятичное
число 156 может быть записано в двоичной форме как 1001 1100B. Здесь буква B на
конце означает, что число записано в двоичной (binary)
системе. Преобразовать его в десятичную форму можно разложением по степеням
числа 2 так, как мы это делали для числа 567 выше, раскладывая его по степеням
числа 10.
10011100B = 1*27 + 0*26 + 0*25
+ 1*24 + 1*23 + 1*22+ 0*21 + 0*20
= 128 + 0*64 + 0*32 + 16 + 8 + 4 +0*2 + 0*1 = 128 + 16 + 8 + 4 = 156
Вы видите очевидные недостатки двоичной формы записи.
Во-первых, это очень громоздкая (длинная) запись, а потому и очень
утомительная. Во-вторых, она с трудом переводится в десятичную форму. Все это
вызывало бы массу ошибок, если бы программисты, разрабатывая программу,
применяли бы двоичное представление целых чисел.
Гораздо удобнее в работе шестнадцатеричная система. Она
имеет в качестве основания число 16, поэтому уже двумя разрядами можно выразить
256 целых чисел от 0 до 255 (т.к. 162 =256).
Поскольку для шестнадцатеричной системы не хватает
арабских цифр, то для выражения шестнадцатеричных цифр 10…15 приходится
прибегать к буквенным обозначениям:
0 – 0 1 – 1 2 – 2 3 - 3
4 – 4 5 – 5 6 – 6 7 - 7
8 – 8 9 – 9 10 – A 11 - B
12 – C 13 – D 14 – E 15 - F
То же самое число 156 в шестнадцатеричной форме запишется
как 9CH. Здесь буква H в конце числа говорит о том, что оно записано в шестнадцатеричной
(hexadecimal) системе.
9C = 9*161 + 12*160 = 144 + 12 =
156
Перед начинающим программистом встает вопрос, в какой
системе работать - десятичной или шестнадцатеричной? За десятичную есть только
один довод - многолетняя привычка. Шестнадцатеричная система удобна той
простотой, с которой двоичная форма в нее переводится, а ведь двоичная форма
отражает физическую суть операции, что делает шестнадцатеричную систему
основной для программистов-профессионалов, а также для специалистов в
электронике и схемотехнике. Простота перевода из двоичной системы в шестнадцатеричную
и наоборот обеспечивается вследствие того, что число шестнадцать может быть
выражено четвертой степенью числа два: 24 = 16. Поэтому, чтобы
перевести число из двоичной формы в шестнадцатеричную, можно перевод выполнять
по каждому полубайту (по каждым четырем битам отдельно):
1001 1100 B = 9C H [прим.4]
Таблица для связи между системами приведена ниже.
Выбирая, в какой системе Вам в дальнейшем работать, надо
также учесть, что большинство прикладных программ, поддерживающих
программирование в машинных кодах - Ассемблеров и Дизассемблеров, работают в шестнадцатеричной
системе.
Связь между
системами счисления.
DEC
|
BIN
|
HEX
|
DEC
|
BIN
|
HEX
|
0
|
0000
|
0
|
8
|
1000
|
8
|
1
|
0001
|
1
|
9
|
1001
|
9
|
2
|
0010
|
2
|
10
|
1010
|
A
|
3
|
0011
|
3
|
11
|
1011
|
B
|
4
|
0100
|
4
|
12
|
1100
|
C
|
5
|
0101
|
5
|
13
|
1101
|
D
|
6
|
0110
|
6
|
14
|
1110
|
E
|
7
|
0111
|
7
|
15
|
1111
|
F
|
Приведенная выше двоичная форма позволяет работать с
целыми положительными числами от 0 до 255. Такая двоичная форма называется абсолютной,
а операции с такими числами – абсолютной двоичной арифметикой.
Рассмотрим, например, что происходит с содержимым аккумулятора, если его
постоянно увеличивать на единицу.
Флаг C регистра F
|
Регистр A
|
HEX
|
DEC
|
0
|
0000 0000
|
00
|
0
|
0
|
0000 0001
|
01
|
1
|
…
|
…
|
…
|
…
|
0
|
1001 1100
|
9C
|
156
|
…
|
…
|
…
|
…
|
0
|
1111 1111
|
FF
|
255
|
1
|
0000 0000
|
00
|
0
|
и т.д.
В то же время, есть операции, в которых необходимо
наличие и целых отрицательных чисел. Например, это операции перехода (аналог GO
TO). Переход может быть как вперед на n шагов (n - положительное), так и назад (n
- отрицательное).
Когда процессор встречает такую команду, он воспринимает
следующий за кодом операции операнд n не как
записанный в абсолютной двоичной форме, а как записанный в дополнительной
двоичной форме. В этой форме могут записываться целые числа от 0 до 127 и
от -128 до -1. Таким образом, она может служить для записи целых чисел со
знаком.
Рассмотрим наш предыдущий пример с постепенным
наращиванием содержимого аккумулятора, но для двоичной дополнительной
арифметики.
Флаг C регистра F
|
Регистр A
|
HEX
|
DEC
|
0
|
0000 0000
|
00
|
0
|
0
|
0000 0001
|
01
|
1
|
…
|
…
|
…
|
…
|
0
|
0111 1111
|
7F
|
127
|
0
|
1000 0000
|
80
|
-128
|
0
|
1000 0001
|
81
|
-127
|
…
|
…
|
…
|
…
|
0
|
1111 1111
|
FF
|
-1
|
(1)
|
0000 0000
|
00
|
0
|
и т.д.
Запомните простое правило двоичной дополнительной
арифметики: чтобы поменять знак числа, надо все его единицы заменить нулями, а
все нули - единицами и к результату прибавить 1.
+ 5 - это 0000 0101B (05H)
Тогда -5 - это 1111 1010B + 1 = 1111 1011B (FBH)
Сложение и вычитание в этой системе выполняются как
обычно (поразрядно), но перенос при переполнении старшего разряда игнорируется.
Так +5 + (-5) = 0.
Флаг переноса
0000 0101
регистра F +1111
1010
(1) 0000 0000
игнорируется
Ниже показаны значения каждого бита восьмиразрядного
числа в абсолютной и в дополнительной двоичной форме.
|
7
|
6
|
5
|
4
|
3
|
2
|
1
|
0
|
Абсолютная двоичная форма
|
128
|
64
|
32
|
16
|
8
|
4
|
2
|
1
|
Дополнительная двоичная
форма
|
-127
|
64
|
32
|
16
|
8
|
4
|
2
|
1
|
Это особый вид представления целых чисел в регистрах
процессора. Он называется BCD-арифметикой. BCD – binary coded
decimal (двоичный код десятичных чисел).
Эта форма основана на том, что каждый разряд десятичного
числа можно представить в виде четырех двоичных битов:
0 – 0000 1 – 0001 2 – 0010 3 - 0011
4 – 0100 5 – 0101 6 – 0110 7 - 0111
8 – 1000 9 – 1001
Значения от 1010 до 1111 - не используются.
Четырехбитную группу называют полубайтом и, таким
образом, один байт в этой форме может содержать двухразрядное десятичное число
от 0 до 99.
На рисунке показано представление в этой форме десятичного
числа 74.
Левый полубайт
|
Правый полубайт
|
0 1 1 1
|
0 1 0 0
|
0+4+2+1 = 7
|
0+4+0+0 = 4
|
Как Вы видите, один полубайт в BCD-арифметике может
содержать число от 0 до 9, в то время как в абсолютной двоичной арифметике - от
0 до 15. Очевидно, что BCD-арифметика является довольно расточительной, но у
нее есть свои преимущества.
Для двух чисел, записанных в BCD-арифметике, обычные
принципы сложения и вычитания неприменимы. Это происходит потому, что в
абсолютной двоичной арифметике полубайт является заполненным, когда он равен
1111 и тогда выполняется переход старшему разряду. В BCD-арифметике полубайт
заполнен, когда он равен 1001 и уже здесь выполняется переход старшему разряду.
Абс. двоичная арифметика
|
BCD-арифметика
|
1111
|
1001
|
+ 1
|
+ 1
|
----
|
----
|
1 0000
|
1 0000
|
В наборе команд процессора есть всего только три команды,
которые работают с числами, представленными в этой форме, но они достаточно
часто встречаются, поскольку их применение значительно упрощает преобразование
чисел перед выдачей их на экран в десятичной форме.
В предыдущей главе мы рассматривали флаги регистра F
процессора и указали на то, что флаги N и H программистом не
используются. Они участвуют в операциях с BCD-арифметикой.
Флаг N - флаг сложения/вычитания. Он равен 1 для
всех операций вычитания и равен 0 для всех операций сложения.
Флаг H - флаг полупереноса. Он включается при
переполнении младшего полубайта, когда начинается заполнение старшего
полубайта.