Рис.108 – Устройство процессора глазами электроника и программиста
Логические операции в регистрах
Взгляните на эту, на первый взгляд бессмысленную программу.
var A, B, C : integer;
begin
A:= 5; B:=16; C:= A or B;
Writeln( C );
end.
Здесь в переменную C заносится логическая сумма двух других числовых переменных. Но ведь логические операции применяют к булевым данным, причем здесь числа? Так вспомните о регистрах, где эти числа хранятся. Ведь это массивы битов! Содержимое битов можно трактовать и как числа 0 и 1, и как логические значения FALSE и TRUE. Именно так поступает Паскаль, выполняя логические действия с числами. В данном примере логически складываются шестнадцать независимых булевых пар с получением 16 битов результата. Похоже выполняются и другие логические операции с числами.
Известно, что переменная типа BOOLEAN занимает байт целиком, но использует лишь один из восьми битов, – расточительно, не так ли? Тогда как в байте можно хранить 8 булевых значений, в целом числе – 16, а в длинном целом – 32. Но экономия – не самое главное в жизни. Логические операции с числами дают интересные возможности для шифрования данных, их используют при обработке изображений и в иных случаях.
«Ладно, – скажете, – теперь бы увидеть это наяву». Легко! Наша следующая программа исследует булевы операции с числами. Самая серьезная её часть – функция преобразования байта в строку символов, то есть в двоичное представление этого числа. В программе «P_47_1» нечто похожее выполняла функция ConvertFromNumber. Сейчас мы облегчим эту функцию, избавившись от одного параметра – основания системы счисления. К тому же теперь нам надо показать все восемь двоичных разрядов числа, включая незначащие нули. В результате этих изменений появилась на свет функция ConvertTo2, которую мы видим в программе «P_48_1».
{ P_48_1 – исследование логических операций с числами }
function ConvertTo2(aNumber : integer): string;
var n, i : integer; c : char; S : string;
begin
S:=''; { Накопитель цифр }
for i:=1 to 8 do begin
n:= aNumber mod 2; { остаток от деления }
c:= Char(n + Ord('0')); { преобразуем в цифру }
S:= c + S; { вставляем цифру слева }
aNumber:= aNumber div 2; { частное }
end;
ConvertTo2:= S;
end;
var A, B, C : byte; { Операнды и результат }
begin {=== Главная программа ===}
repeat
Write('A= '); Readln(A);
Write('B= '); Readln(B);
C:= A or B; { логическое сложение (объединение) }
Writeln;
Writeln('C= A OR B');
Writeln('A= ',ConvertTo2(A), A:5);
Writeln('B= ',ConvertTo2(B), B:5);
Writeln('C= ',ConvertTo2(C), C:5);
C:= A and B; { логическое умножение (пересечение) }
Writeln;
Writeln('C= A AND B');
Writeln('A= ',ConvertTo2(A), A:5);
Writeln('B= ',ConvertTo2(B), B:5);
Writeln('C= ',ConvertTo2(C), C:5);
C:= not A; { логическое отрицание (инверсия) }
Writeln;
Writeln('C= NOT A');
Writeln('A= ',ConvertTo2(A), A:5);
Writeln('C= ',ConvertTo2(C), C:5);
until A=0;
end.
Главная программа не должна вызывать вопросов: после ввода пары чисел и выполнения логических операций с ними, на экран выводятся как исходные числа, так и результаты. Причем выводятся и в двоичной, и в десятичной системах счисления, например:
C= A OR B
A= 00001101 13
B= 00001011 11
C= 00001111 15
C= A AND B
A= 00001101 13
B= 00001011 11
C= 00001001 9
C= A XOR B
A= 00001101 13
B= 00001011 11
C= 00000110 6
C= NOT A
A= 00001101 13
C= 11110010 242
По результатам этих опытов выведены правила для логических операций (табл. 12). Логическое отрицание «НЕ» отличается от прочих тем, что применяется к одному операнду.
Табл. 12 – Правила выполнения логических операций с битами
Логическая операция |
Пример |
Правило |
«ИЛИ» (сложение) |
1010 OR11001110 |
Результат единица, если ХОТЯ БЫ ОДИН из операндов равен единице. |
«И» (умножение) |
1010 AND11001 000 |
Результат единица, если ОБА операнда равны единице. |
«Исключающее ИЛИ» (сравнение) |
1010 XOR11000 110 |
Результат единица, если операнды ОТЛИЧАЮТСЯ. |
«НЕ» (отрицание) |
1010 NOT0101 |
Результат единица, если операнд РАВЕН НУЛЮ. |
Заменив в этих правилах единицу на TRUE, а ноль на FALSE, вы получите правила для булевых данных.
Читать дальше