double arrow

Основные сведения. Внутри компьютера числа, как и все остальные данные и команды, хранятся в двоичном виде

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

Каждые восемь бит образуют байт. Одним байтом можно представить 28=256 различных значений от 000000002 до 111111112. Несколько байт образуют слово, которое по длине обычно соответствует разрядности регистра данных процессора. Мы будет рассматривать 16-ти разрядные слова.

Группы бит. Отдельные биты внутри байта или слова могут нести определённую информацию. Например, информация в байте, отвечающем за цветовой атрибут текста, распределена следующим образом:

               
B b b b f f f f

· ffff = 4-битный цвет символов (от 0 до 0xF)

· bbb = 3-битный цвет фона (от 0 до 7)

· B = бит мерцания (или бит интенсивности)

Наборы битов ffff, bbb и B называются полями.

Поля цвета имеют побитовое смысловое значение: RGB, то есть младший бит отвечает за синий (B lue) цвет, средний бит – зеленый (G reen) а старший бит – красный (R ed). Наличие установленных битов в разных цветах RGB даёт соответствующую смесь цветов [2]. Для четырёхбитного поля ffff самый старший бит отвечает за интенсивность цвета (см. Табл. 2.1.)

Таблица 2.1. Коды цветов.

Инт./ мерц. R G B Значение байта цвета Цвет (интенсивный/мигающий)
          Черный
          Синий
          Зеленый
          Бирюзовый
          Красный
          Малиновый
          Коричневый
          Светло-серый
          Темно-серый /Черный
          Ярко-синий /Синий
        A Ярко-зеленый /Зеленый
        B Ярко-бирюзовый /Бирюзовый
        C Ярко-красный /Красный
        D Ярко-малиновый /Малиновый
        E Желтый /Коричневый
        F Белый /Светло-серый

В языке Си для изменения цветового атрибута текста служит стандартная функция textattr (CONIO.h): void textattr(int newattr).

Следует отметить, что стандартные функции вывода на стандартное устройство не реагируют на изменение атрибута цвета [3]. Для вывода цветного текста следует использовать стандартные функции вывода в текстовое окно, например, cprintf (CONIO.h).

Пример 2.1. На синем фоне жёлтыми буквами вывести фразу "Hello, world!".

#include <conio.h>

#include <stdio.h>

void main()

{ clrscr(); //очистка экрана

textattr(0x1E); //установка цветов фона и символов

printf("Это печать стандартного устройства");

printf("\nА это печать в текстовое окно:");

cprintf("\n\rHello, world!");

getch(); //ожидание нажатия клавиши

}

Функция cprintf () в отличие от printf() выводит управляющую комбинацию \n (перевод строки) просто как перевод строки. Для привычного начала новой строки в функции cprintf () следует дополнительно применять еще одну управляющую комбинацию \r (возврат каретки).

Команда textattr(0x1E) устанавливает цвет символов – жёлтый на синем фоне. В данной команде мы использовали шестнадцатеричное представление чисел с той целью, чтобы было легче определить цвет фона и цвет символа. Но результат выполнения команды не изменится, если мы будем использовать десятичные числа: textattr(30).

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

Пример 2.2. Задать цвет фона и символа с клавиатуры и вывести фразу "Hello, world!" на языке Си.

#include <conio.h>

#include <stdio.h>

int i,j;

void main()

{ clrscr(); //очистка экрана

printf("Введите цвет фона: ");

scanf("%d",&i); //чтение цвета фона

printf("Введите цвет символов: ");

scanf("%d",&j); //чтение цвета символов

textattr(j+(i<<4)); //установка цветовых атрибутов

cprintf("\n\rHello, world!"); //вывод фразы на экран

getch(); //ожидание нажатия клавиши

}

Чтобы задать ярко-синий фон для выводимого текста, недостаточно одной команды textattr(0x9E). По умолчанию эта команда даёт в результате мигающие жёлтые символы на синем фоне. Для переключения режима интенсивность/мерцание используется прерывание BIOS 10h, функция 10h, подфункция 3. Если регистр bl=0, то включается режим интенсивного цвета фона:

asm { mov ax, 1003h

mov bl, 0

int 10h}

В случае bl=1 – включается режим мерцания символов:

asm { mov ax, 1003h

mov bl, 1

int 10h}

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

Более подробно рассматривать вызов прерываний и регистры процессора мы будем на лабораторном занятии №6.

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

Операция, при которой изменяется только часть байта, а остальные биты остаются неизменными, называется маскированием. Установкой бита называется присваивание ему значения единица. Сбросом бита называется присваивание ему значения нуль. Инвертирование бита означает изменение его значения на противоположное (в двоичной системе счисления значения 0 и 1 являются противоположными).

Маской называется байт, в котором установлены биты, соответствующие битам измененяемого байта. Если значения всех битов в маске инвертированы, то маска называется инвертированной.

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

Таблица 2.2. Описание побитовых операторов.

Оператор языка Си Описание операторов
& и
^ исключающее или
| или
~ не (отрицание)
>> k побитовый сдвиг на k бит вправо
<< k побитовый сдвиг на k бит влево

Таблица 2.3. Значения побитовых операторов.

Аргументы Значения функций
           
           
           
           

Для установки битов в байте (или слове) применяется следующая последовательность действий:

1. Создаётся маска на изменяемые биты.

2. Маска накладывается на байт (слово) с помощью операции "или".

В последующих примерах мы будем производить операции над неким числом а, которое может быть определено в программе так: unsigned char a (целое беззнаковое число, длиной 1 байт, см. табл. 1.4). Это означает, что мы будем изменять биты числа только с нулевого по седьмой.

Пример 2.3. Установить седьмой бит в числе а.

Для установки седьмого бита используем выражение a |= 0x80 (тоже самое, что a = a | 0x80). В таблице 3.4 показано формирование маски и накладывание на исходный байт с помощью оператора | "или".

Таблица 2.4. Установка седьмого бита

Номера разрядов ® Основание
   
7 6 5 4 3 2 1 0 1 0
Пример исходного байта (a) 0 0 1 1 0 0 1 0 3 2
Маска 1 0 0 0 0 0 0 0 8 0
Результат операции "или" 1 0 1 1 0 0 1 0 B 2

Чтобы установить группу бит в байте (или слове), необходимо сложить маски для изменяемых бит или определить одну общую маску на все изменяемые биты, а затем накладывается на искомый байт (слово) с помощью операции "или".

Пример 2.4. Установка седьмого, четвёртого и третьего бита в числе а.

Для изменения указанных битов используем выражение a |= 0x98 (a = a | 0x98). Как формируется маска, можно посмотреть в таблице 2.5.

Таблица 2.5. Установка группы бит.

Номера разрядов ® Основание
   
7 6 5 4 3 2 1 0 1 0
Исходный байт (a) 0 0 1 1 0 0 1 0 3 2
Маска на седьмой бит 1 0 0 0 0 0 0 0 8 0
Маска на четвёртый бит 0 0 0 1 0 0 0 0 1 0
Маска на третий бит 0 0 0 0 1 0 0 0 0 8
Сумма масок или общая маска на 7, 4 и 3 1 0 0 1 1 0 0 0 9 8
Результат операции "или" 1 0 1 1 1 0 1 0 DA

Для сброса битов в байте (или слове) применяется следующая последовательность действий:

1. Создаётся маска на изменяемые биты.

2. Маска инвертируется.

3. Инвертированная маска накладывается на байт (слово) с помощью команды "и".

Пример 2.5. Сброс седьмого бита в числе а.

Для сброса седьмого бита используем выражение a &= ~0x80. Как формируется маска и результат операции можно посмотреть в таблице 2.6.

Таблица 2.6. Сброс седьмого бита.

Номера разрядов ® Основание
   
7 6 5 4 3 2 1 0 1 0
Исходный байт (a) 1 0 1 1 0 0 1 0 B 2
Маска 1 0 0 0 0 0 0 0 8 0
Инвертированная маска 0 1 1 1 1 1 1 1 7 F
Результат операции "и" 0 0 1 1 0 0 1 0 3 2

Чтобы сбросить группу бит в байте (или слове), необходимо сложить маски для изменяемых бит или определить одну общую маску на изменяемые биты, затем общая маска инвертируется и накладывается на искомый байт (слово) с помощью операции "и".

Пример 2.6. Сброс седьмого, шестого и первого бита в числе а.

Для изменения указанных битов используем выражение a &= ~ 0x3D. Как формируются маски и результат операции можно посмотреть в таблице 2.7.

Таблица 2.7. Сброс группы бит.

Номера разрядов ® Основание
   
7 6 5 4 3 2 1 0 1 0
Исходный байт (a) 0 0 1 1 0 0 1 0 3 2
Маска на седьмой бит 1 0 0 0 0 0 0 0 8 0
Маска на шестой бит 0 1 0 0 0 0 0 0 4 0
Маска на первый бит 0 0 0 0 0 0 1 0 0 2
Сумма масок или общая маска на 7, 6 и 1 1 1 0 0 0 0 1 0 С 2
Инвертированная общая маска 0 0 1 1 1 1 0 1 3 D
Результат операции "и" 0 0 1 1 0 0 0 0 3 0

Для инвертирования битов в байте (или слове) применяется следующая последовательность действий:

1. Создаётся маска на инвертируемые биты.

2. Маска накладывается на байт (слово) с помощью команды "исключающее или".

Пример 2.7. Инвертирование шестого и седьмого бита в числе а.

Для инвертирования указанных битов используем выражение a ^= 0xC0. Как формируются маски и результат операции можно посмотреть в таблице 2.8.

Таблица 2.8. Инвертирование группы бит:

Номера разрядов ® Основание
   
7 6 5 4 3 2 1 0 1 0
Исходный байт (a) 1 0 1 1 0 0 1 0 B 2
Маска 1 1 0 0 0 0 0 0 C 0
Результат операции "искл. или" 0 1 1 1 0 0 1 0 7 2

Определение одного или группы бит. Для того чтобы считать один или группу бит из байта (слова), необходимо сбросить ненужные разряды и выделенную группу бит сдвинуть вправо до нулевого разряда.

Пример 2.8. Определение значения пятого бита числа а.

Для определения значения указанных битов используем выражение bit5 = (a & 0x20) >> 5. Как формируется маска и результат операции можно посмотреть в таблице 2.9.

Таблица 2.9. Определение значения пятого бита.

Номера разрядов ® Основание
   
7 6 5 4 3 2 1 0 1 0
Исходный байт (a) 1 0 1 1 0 0 1 0 B 2
Маска 0 0 1 0 0 0 0 0 2 0
Результат операции "и" 0 0 1 0 0 0 0 0 2 0
Результат операции >> 5 0 0 0 0 0 0 0 1 0 1

Обратите внимание на то, что значение переменной bit5 (unsigned char bit5) всегда будет, в зависимости от значения переменной a, либо нулем, либо единицей.

Для получения значений трёх разрядов подряд, например, 5, 4 и 3 бит, можно совершать аналогичные операции. Но результатом может оказаться значение от 0 до 7, что опять потребует расшифровки по разрядам. Поэтому желательно значения в группе бит определять поразрядно: для пятого, четвёртого и третьего бита отдельно, а результат сохранять не в отдельных переменных, а в массиве bit (unsigned char bit [8]):

Пример 2.9. Определение пятого бита числа а.

bit[5] = (a&0x20)>>5, или bit[5] = (a>>5)&1

Пример 2.10. Определение четвёртого бита числа а.

bit[4] = (a&0x10)>>4, или bit[4] = (a>>4)&1

Пример 2.11. Определение третьего бита числа а.

bit[3] = (a&8)>>3, или bit[3] = (a>>3)&1

Пример 2.12. Определение k-того бита числа а в общем виде.

bit[k] = (a&(1<<k))>>k, или bit[k] = (a>>k)&1

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

Пример 2.13. Вывод восьми бит числа а.

for (int i=7; i <=0; i--) printf(a>>i & 1)


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



Сейчас читают про: