Машинное слово - это массив битов. Поэтому алгоритмы работы с машинными словами в первом приближении аналогичны алгоритмам, работающим с массивами. Единственная разница состоит в том, что среди команд процессора отсутствуют команды прямой адресации битов. Взамен их используются поразрядные операции, выполняющие одну и ту же логическую операцию или операцию перемещения над всеми разрядами машинного слова одновременно (рис.12.1). Другое их название - машинно-ориентированные операции - отражает тот факт, что они поддерживаются в любой системе команд и любом языке Ассемблера. К ним относятся:
| - поразрядная операция ИЛИ
& - поразрядная операция И;
^ - поразрядная операция исключающее ИЛИ;
~ - поразрядная операция инверсии;
>> - операция сдвига вправо;
<< - операция сдвига влево.
Формальная сторона логических операций всем известна. Однако программиста интересует содержательная интерпретация поразрядных операций, которая позволяет выполнять различные действия с отдельными битами и их диапазонами - битовыми полями: устанавливать, очищать, выделять, инвертировать. Для этого используют поразрядные операции, в которых первый операнд является обрабатываемым машинным словом. Второй операнд, как правило, определяет те биты в первом операнде, которые изменяются при выполнении операции, и в этом случае называется маской. Если маска жестко задана в программе, то является просто битовой константой в шестнадцатеричной системе.
|
|
0x1F // 0000 0000 0001 1111 - в маске установлены биты 0…4;
0х3С0 // 0000 0011 1100 0000 - в маске установлены биты 6…9;
0x1 // 0000 0000 0000 0001 - в маске установлен младший бит.
Рис.12.1. Логическая операция над n-м разрядом
Часто требуется, чтобы маска была «программируемой», например, занимала заданную последовательность разрядов. В этом случае нужно организовать процесс «пробегания» единичного бита по заданному полю.
//Листинг 12.1
#include <iostream>
using namespace std;
//Формирование маски
//в заданном диапазоне разрядов
int set_mask(int r0, int dn)
{ //r0 - номер самого правого разряда в маске
//dn - число единиц в маске
// m " бегущий” единичного бита, v маска
int m,v;
//Сдвинуть единичный бит на r0 разрядов влево
m = 1<<r0;
for (v=0; dn!=0; dn--){// Повторять dn раз
//Установить очередной разряд из m в v
v|=m;
// Переместить единичный бит в следующий разряд
m <<= 1;}
return v;}
int main()
{int dn=4,r0=6;
int n=set_mask(r0,dn);
cout<<hex<<n<<'\n';
return 0;
}
Результат выполнения программы:
3c0