Системы счисления
Форум |
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 |
A => 10 * 163 = 40960 |
||||||||||
Весовые коэффициенты: | Перевод 3B8D2h в десятичную форму: | ||||||||||
|
3 => 3 * 164 = 196608 |
Переведите следующие шестнадцатеричные числа в десятичную форму:
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. Рассмотрим алгоритм нахождения дополнительного кода:
- Инвертировать исходное число, т.е. заменить все цифры числа на противоположные:
F => 0, E => 1, D => 2, C => 3, B => 4 и т.д. После инверсии 8FEFh выглядит так: 7010h - К инверсному числу добавить единицу: 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
Форум |