Системы счисления

From AsIsWiki
Revision as of 11:59, 4 April 2015 by Alex (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search
Форум

Оглавление | Дальше


Contents

Введение

В повседневной деятельности мы привыкли к счету с применением цифр 1, 2, 3 и т. д. Вследствие технических особенностей, компьютер применяет другой метод счета, в котором используется всего две цифры 0 и 1. Например, до пяти компьютер считает так: 1, 10, 11, 100, 101. Числа 10, 11, 100 ... являются двоичными, они базируются на системе счисления, состоящей из двух цифр. Десятичная система состоит из десяти цифр 0 ... 9.

Одно и тоже число можно записать в разных системах счисления. Например: двоичное число 10 соответствует десятичному 2.

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

Изучение шестнадцатеричной системы счисления мы начнем в специальной программе - DEBUG.EXE, которая входит в состав операционной системы Windows.


Debug

Название Debug произошло от слова "Bugs" (насекомые) - так программисты именуют ошибки в программе.

Используя Debug можно проверить работу программы в пошаговом режиме. Это позволяет найти и исправить возможные ошибки. Данный процесс называется отладка "debugging", отсюда и произошло название программы.

Термин "debugging" (обезжучивание) имеет глубокие корни - он появился в тот день, когда перестал работать компьютер Гарвардского университета Марк 1. После долгих поисков техники обнаружили небольшую моль, попавшую между контактами реле. Они удалили моль и внесли запись в сменный журнал о процессе под названием "debugging", произведенном над Марком.

Наиболее удобной средой для изучения Debug является файл-менеджер FAR. Для запуска Debug необходимо в командной строке FAR-а набрать команду "debug" и нажать [Enter]:

debug <Enter>
-

Дефис означает, что Debug ждет команды. Чтобы покинуть программу наберите команду "Q" (Quit - выход) и нажмите ввод:

-q <Enter>

Для сложение и вычитание двух шестнадцатеричных чисел используем команду "H" (Hex – шестнадцатеричный), например:

-h 3 2 <Enter>
0005 0001

Debug печатает сумму 3 + 2 = 5 и разность 3 - 2 = 1. С числами от 0 до 9 Debug ведет себя как с десятичными числами. Сходство между шестнадцатеричной и десятичной системами заканчивается при получении результата больше девяти, например 9 + 1:

-h 9 1
000A 0008

A - это шестнадцатеричное число, аналог десятичного числа 10. Выполните вычисления: 9 + 2, 9 + 3, 9 + 4, 9 + 5, 9 + 6. В результате получатся остальные числа: B, C, D, E, F. Такой способ записи чисел является очень компактным и удобным с точки зрения представления информации в компьютере.

Debug работает только с шестнадцатеричными числами. Некоторые операции с такими числами могут давать не совсем обычные результаты. Например, сложите 8 + 8:

-h 8 8
0010 0000

10 - это шестнадцатеричное число, аналог десятичного числа 16. Теперь найдите разность между числами 2 и 3:

-h 2 3
0005 FFFF

Разность чисел FFFF - это шестнадцатеричное число, соответствующее единице со знаком минус "-1". Попробуйте получить -2, -3 и другие отрицательные числа.


Перевод шестнадцатеричных чисел в десятичную форму

Название "шестнадцатеричный" произошло от числа 16. Цифры 0 ... 9 одинаковы и для шестнадцатеричной, и для десятичной систем счисления. Шестнадцатеричные цифры от A до F соответствуют десятичным числам от 10 до 15. Соответствие между десятичными числами (Decimal) и шестнадцатеричными (Hexadecimal) можно представить в виде таблицы:

dec hex
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
16 10
17 11
18 12
19 13
20 14

Обычно шестнадцатеричные числа помечают специальным символом "h": 12h, F8h, 10h и др. Это позволяет избегать путаницы между десятичными и шестнадцатеричными числами, не содержащими букв: 12 - десятичное, 12h - шестнадцатеричное.

Для перевода чисел из hex- в dec- форму используется очень простой алгоритм.
Например, переведем A7h в десятичную форму:

1 переводим обе цифры в десятичную форму A => 10
7 => 7
2 умножаем каждое число на коэффициент, соответствующий разряду числа (весовой коэффициент) 10 * 161 = 160
7 * 160 = 7
3 складываем полученные числа 160 + 7 = 167











Шестнадцатеричное число A7h соответствует десятичному числу 167.
Данный пример можно записать более компактно:

A => 10 * 161 = 160
7 =>  7 * 160 =   7   перевод числа A7h в десятичную форму
A7h = 160 + 7 = 167


Примеры перевода чисел из одной системы счисления в другую:

Перевод числа 2E8h в десятичную форму:Перевод числа AF1Ch в десятичную форму:

   2 =>  2 * 162 = 512
   E => 14 * 161 = 224
   8 =>  8 * 160 =   8    
2E8h = 512 + 224 + 8 = 744

        A => 10 * 163 = 40960
        F => 15 * 162 =  3840
        1 =>  1 * 161 =    16
        C => 12 * 160 =    12         
AF1Ch = 40960 + 3840 + 16 + 12 = 44828



Весовые коэффициенты:Перевод числа 3B8D2h в десятичную форму:
164 65535
163 4096
162 256
161 16
160 1

      3 =>  3 * 164 = 196608
      B => 11 * 163 =  45056
      8 =>  8 * 162 =   2048
      D => 13 * 161 =    208
      2 =>  2 * 160 =      2      
3B8D2h = 196608 + ... + 2 = 243922


Переведите следующие шестнадцатеричные числа в десятичную форму:

A7h       100h       4F8Ch
45h       5E9h       1000h
FFh       FFFh       FFFFh


Сложение и вычитание шестнадцатеричных чисел

Сложение и вычитание шестнадцатеричных чисел проходит аналогично действиям над десятичными числами.
Приведем несколько простых примеров:

A + 1 = B       B - A = 1       F + 1 = 10       A + C = 16
B - 2 = 9       7 + 7 = E       F + F = 1E       10 - 8 = 8

Рассмотрим, как получается 1Eh в результате сложения F + F. Запишем результат операции в десятичном виде: F + F = 15 + 15 = 30.

Проверим, сколько шестнадцатеричных десятков содержится в числе 30: 30 / 16 = 1 (один десяток). Шестнадцатеричный десяток 10h соответствует десятичному числу 16. Проводим вычитание 30 - 16 и получаем остаток 14, откуда: 14 + 16 = Eh + 10h = 1Eh.

Числа с большим числом разрядов можно складывать "столбиком":

1          1        1           1111         1 1
 C        2A7        F451        BCD8        BCD8
+D       +92A       +CB03       +FAE9       +0509
19        BD1       1BF54       1B7C1        C1E1

Вычислите "столбиком" следующие примеры, а результаты проверьте в Debug:

3F8h + AB9h       4E5h + 4F3h       DF8h - AB9h
FF7h + 8BFh       FFFh + FFFh       FF7h - 8BFh
CD0h + A82h       FFFh + 001h       CD2h - A82h


Пятизначные шестнадцатеричные числа

Что произойдет, если в сложении использовать пятизначное шестнадцатеричное число? Вычислим сумму следующих чисел:

-h 5C3F0 4BC6
       ^Error

Debug сообщил об ошибке. Команда "h" не может обрабатывать числа, длина которых больше четырех разрядов. Шестнадцатеричное число, состоящее из четырех разрядов называют так: "СЛОВО" или "WORD".

Если сложить два "слова", например C000h и D000h, то вместо действительного результата 19000h получится "урезанный" до четырех разрядов результат 9000h:

-h C000 D000
9000 F000

Debug сохраняет четыре младших цифры ответа, а единицу из старшего разряда заносит в специальную ячейку, которая будет рассмотрена позже.

Подумайте, какое значение имеет старший (пятый) разряд при сложении четырехразрядных шестнадцатеричных чисел?


Перевод десятичных чисел в шестнадцатеричную форму

Перевод десятичного числа в шестнадцатеричную форму выполняется делением исходного числа на 16. Например, переведем 300 в шестнадцатеричную форму:

_300 |16                        То же самое можно записать иначе:
 16  _18 |16                    300 / 16 = 18 остаток 12 => C
_140  16  1 -> 1                 18 / 16 = 1  остаток  2 => 2
 128   2 ----> 2  => 12Ch         1 / 16 = 0  остаток  1 => 1
  12 --------> C                         300 = 12Ch

Примеры перевода чисел 1000 и 60000 в шестнадцатеричную форму:

60000/16 = 3750 остаток  0 => 0       1000/16 = 62 остаток  8 => 8
 3750/16 =  234 остаток  6 => 6         62/16 =  3 остаток 14 => E
  234/16 =   14 остаток 10 => A          3/16 =  0 остаток  3 => 3
   14/16 =    0 остаток 14 => E               1000 = 3E8h
         60000 = EA60h

Переведите следующие числа в шестнадцатеричную форму:

945, 138, 1100, 885, 230, 256, 1024

Шестнадцатеричный результат переведите обратно в десятичную форму - это позволит проверить корректность ваших действий.


Отрицательные числа

Ранее было отмечено, что FFFFh фактически равно -1. Однако если перевести число FFFFh в десятичную форму, то получится 65535. Почему так происходит? Действительно ли FFFFh ведет себя как отрицательное число?

Пусть так, тогда если сложить FFFFh и 5, то должно получиться 4:

-h 5 FFFF
0004 0006

Похоже, Debug действительно обращается с FFFFh, как с -1. Рассмотрим механизм сложения чисел 5 и FFFFh, при суммировании "столбиком":

1111
 0005
+FFFF
10004   5 + (-1) = 4

Если игнорировать единицу в старшем разряде, то получается правильный ответ 5 + (-1) = 4. Debug сохраняет четыре младшие цифры результата. Старший (пятый) разряд запоминается в специальной ячейке памяти и называется - "ПЕРЕПОЛНЕНИЕ".

FFFF -1
FFFE -2
FFFD -3
FFFC -4
FFFB -5
FFFA -6
FFF9 -7
FFF8 -8
FFF7 -9
FFF6 -A
FFF5 -B
FFF4 -C
FFF3 -D
FFF2 -E
FFF1 -F
FFF0 -10


Сложение чисел, больших чем 8000h дает переполнение. Такие числа ведут себя аналогично отрицательным числам:

1111                       1111
 0008                       FFF0
+FFFA                      +8FFF
10002   8 + (-6) = 2       18FEF   -10h + (-7001h) = -7011h

В последнем примере установлено соответствие чисел 8FEFh и -7011h. Как проверить справедливость этого утверждения? Ранее отмечалось, что FFFFh это (-1), значит FFFEh это (-2) и т.д. В приведенной таблице представлен ряд отрицательных чисел. Если ряд продолжить, то при достижении числа 8FEFh мы увидим его отрицательный эквивалент: -7011h

Любой язык программирования позволяет оперировать двумя типами чисел: знаковыми и беззнаковыми. Представление числа зависит от конкретной ситуации. Например: FFFAh можно рассматривать как число без знака, и как отрицательное число -6. Если в программе нужны отрицательные числа, то диапазон 0 ... FFFFh делится на две части:

   0h ... 7FFFh - положительные числа
8000h ... FFFFh - отрицательные числа

Отрицательный аналог числа 8FEFh называется его дополнительным кодом, и выражается числом -7011h. Рассмотрим алгоритм нахождения дополнительного кода:

  1. Инвертировать исходное число, т.е. заменить все цифры числа на противоположные:
    F => 0, E => 1, D => 2, C => 3, B => 4 и т.д. После инверсии 8FEFh выглядит так: 7010h
  2. К инверсному числу добавить единицу: 7010h + 1 = 7011h - получилось искомое число.

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

0 ... FFFFh или 0 ... 65535

Если в вычислениях требуются отрицательные числа, то предыдущий диапазон смещается в отрицательную область:

-8000h ... 7FFFh или -32768 ... 32767

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

Вычислите дополнительный код следующих чисел:

FF00h, AD3Fh, 9000h, EDF4h, B348h


Двоичная система счисления

Микропроцессор, будучи устройством электронным, воспринимает цифры, как комбинации электрических сигналов. Например, число может быть представлено так:

0 вольт соответствует цифре "0"
1 вольт соответствует цифре "1"
...
9 вольт соответствует цифре "9"

При этом вероятность возникновения ошибки (например, из-за колебаний напряжения) очень велика. Наиболее надежным способом представления чисел в электронном устройстве, является двоичная система счисления:

0 ... 0,5 вольт соответствует цифре "0"
2,5 ... 5 вольт соответствует цифре "1"

Такая разница между уровнями сигналов (соответствующих "0" и "1") практически исключает ошибки связанные с колебаниями напряжения и другими искажениями сигнала. Кроме того, значительно упрощается компонентная база компьютера.

Таким образом, двоичная система счисления стала единым стандартом представления чисел в любом "думающем" электронном устройстве.

Двоичная система оптимальна для разработки микропроцессорных систем, но очень неудобна для написания программ. Чтобы упростить процесс общения с микропроцессором, были разработаны программы, транслирующие шестнадцатеричные числа в двоичный код, и выполняющие обратное преобразование. Одной из таких программ является Debug.

Для вывода на экран чисел в шестнадцатеричном формате, Debug использует небольшую подпрограмму, которая переводит двоичные числа (обрабатываемые микропроцессором), в шестнадцатеричную форму.

Двоичные числа мы будем помечать индексом "b" (binary - двоичный), например: 10010111b

Рассмотрим число 1101b. Все разряды числа характеризуются весовыми коэффициентами, которые получаются возведением основания системы счисления (два) в степень, соответствующую номеру разряда. Нумерация разрядов начинается с нуля.

Для перевода числа из двоичной системы в десятичную, необходимо выбрать весовые коэффициенты тех разрядов, где есть единица (в случае числа 1101b, это: 23, 22 и 20). Далее нужно сложить эти числа: 23 + 22 + 20 = 13

Номера разрядов 3 2 1 0
Весовые коэффициенты 23 22 21 20
Число 1 1 0 1

Перевод числа 11010010b в десятичную форму:

27 26 25 24 23 22 21 20
1 1 0 1 0 0 1 0
27 + 26 + 24 + 21 = 210

Переведите следующие двоичные числа в десятичный формат:

0110b       0101b       10111001b       10101101b
1011b       1001b       10011001b       11111111b

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

                  1   бит
               1011   полубайт
          1101 0011   байт
1001 0110 0101 1110   слово

Графически это разделение можно показать так:

sign bit  bit      byte 
      |    |    |       |
      1001 0110 1101 0111
      |       word      |
bin hex dec
0000 0 0
0001 1 1
0010 2 2
0011 3 3
0100 4 4
0101 5 5
0110 6 6
0111 7 7
1000 8 8
1001 9 9
1010 A 10
1011 B 11
1100 C 12
1101 D 13
1110 E 14
1111 F 15

Рассмотрим таблицу, в которой отражено соответствие двоичных, шестнадцатеричных и десятичных чисел.

Из таблицы видно, что двоичная и шестнадцатеричная системы кратны между собой. Данную пропорциональность в размерности чисел можно сформулировать так:

            1111b = Fh      двоичный полубайт
        11111111b = FFh     двоичный байт
1111111111111111b = FFFFh   двоичное слово

Благодаря кратности, преобразования чисел из двоичной системы в шестнадцатеричную, выполняются очень просто. Двоичное число разбивается на декады (четырехбитные фрагметны):

1001001001011011b => 1001.0010.0101.1011b

Каждая декада переводится в шестнадцатеричный формат, аналогично преобразованию чисел из двоичной системы счисления в десятичную:

1001b = 23 + 20      =  9 => 9
0010b = 21           =  2 => 2
0101b = 22 + 20      =  5 => 5
1011b = 23 + 21 + 20 = 11 => B
1001.0010.0101.1011b = 925Bh

Переведите следующие числа в шестнадцатеричную форму:

1111b       1110b       10101001b
1010b       1001b       10001001b
1011b       1101b       11111111b

Арифметические действия с двоичными числами выполняются аналогично действиям с десятичными числами. Например, сложение одноразрядных двоичных чисел выглядит так:

                  1
 1        0        1
+0       +1       +1
 1        1       10

Сложение четырехразрядных и восьмиразрядных двоичных чисел:

1111                       111111
 1101                      01101110
+0011                     +01011010
10000   13 + 3 = 16        11001000   110 + 90 = 200

Выполните следующие действия:

0101 + 1100       10100011 + 00110011
1110 + 0011       10110011 + 01011100

(проверку результатов выполните в шестнадцатеричной системе счисления)


Дополнительный код

0000 0000 0000 0000 0000h
... ...
0111 1111 1111 1111 7FFFh
1000 0000 0000 0000 8000h
... ...
1111 1111 1111 1111 FFFFh

Раннее отмечалось, что в некоторых случаях числа 8000h ... FFFFh ведут себя как отрицательные.
Рассмотрим числа 0 ... FFFFh в двоичной системе счисления. Данный ряд делится на две равные части. Cтарший бит, в двоичном представлении чисел, выделен жирным шрифтом. Начиная с числа 8000h, старший бит устанавливается в единицу.

Старший бит является признаком отрицательного числа. По его состоянию микропроцессор определяет знак числа. Но если в программе используются команды для чисел без знака, то микропроцессор игнорирует знаковый бит, и воспринимает диапазон [0 ... FFFFh] как ряд положительных чисел.

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

Ранее мы находили дополнительный код шестнадцатеричных чисел (вспомните инверсию шестнадцатеричного числа с добавлением единицы). Дополнительный код двоичного числа определяется аналогично. Например, найдем дополнительный код числа 1101011010001001:

 1101.0110.1000.1001  (D689h)
          ↓                   инвертируем число
 0010.1001.0111.0110
+                  1          добавляем к результату единицу
 0010.1001.0111.0111 (-2977h)

Вычитание двоичных чисел, например A - B, сводится к их сложению A + (-B). При этом: A не меняется, B преобразуется в дополнительный код. Далее числа складываются. Например, надо произвести вычитание 1101b - 1010b:

1. Преобразуем 1010 в дополнительный код:

1010 => 0101 => 0101 + 1 => 0110

2. Выполняем сложение:

11
 1101     1101 + (-1010) => 0011 или 13 + (-10) => 3
+0110
10011     (единица в старшем разряде игнорируется)

Выполните следующие действия:

1110 - 0011       11110000 - 00110111
1001 - 0110       01110110 - 00111001



Форум

Оглавление | Дальше

Personal tools
Namespaces

Variants
Actions
Navigation
Tools