Битовые операции и маски: управление байтом по битам
Байт — восемь независимых переключателей, живущих в одной ячейке. Как дотянуться до одного из них, не тронув остальные? Для этого служат битовые операции: AND, OR и XOR применяются к байту поэлементно, а число-помощник, которое подставляют к ним в пару, называется маской. В курсе маски встречаются дважды: в шинных вентилях (BusAND/BusOR) и в программе чтения кнопок геймпада на уровне 2.23.
Битовые операции — это поэлементность
Обычное сложение связывает разряды между собой через переносы. Битовые операции — нет: каждая пара битов (байт, маска) обрабатывается независимо. В i-м разряде результата получается ровно то, что даёт таблица операции для i-х битов операндов. Именно поэтому шинные версии вентилей в курсе — это просто восемь обычных вентилей рядом (для Verilog — generate-for из уровня 4.37).
Таблицы вам уже знакомы: AND даёт 1 только на двух единицах, OR — если есть хотя бы одна, XOR — когда биты различны. Не привычные «числа», а восемь независимых мини-вычислений.
Маска: трафарет для байта
Маска — это второй операнд, подобранный так, чтобы нужные разряды изменились, а остальные — нет. Четыре базовых приёма для работы с битом номер k:
— Установить (сделать 1): X OR (1 << k). Единицы маски «рисуют» единицы поверх байта.
— Сбросить (сделать 0): X AND NOT(1 << k) — маска из всех единиц, кроме позиции k. Помните 0xFE из статьи о шине? Это маска «всё, кроме последнего бита».
— Переключить: X XOR (1 << k). XOR с единицей всегда меняет бит на противоположный.
— Проверить: X AND (1 << k). Результат ненулевой — бит был 1; нулевой — был 0.
Геймпад: чтение кнопок масками
Уровень 2.23 «Геймпад» читает кнопки из порта 254: в ответ приходят восемь бит — по одному на кнопку (1 — Вверх, 2 — Вниз, 4 — Влево, 8 — Вправо). Как узнать, нажата ли «Влево»? Наложить маску 4:
LDA 0 ; обнулить аккумулятор
ADD 254 ; Acc = байт кнопок, например 00000101 (Вверх + Влево = 1 + 4 = 5)
AND 4 ; маска 00000100 — оставить только бит Влево
JZ skip ; ноль? кнопка не нажата — прыгаем
... ; сюда попадаем, если Влево нажата
skip: HLT
Три строки — и программа «щупает» один конкретный бит восьмибитного байта. Этот же приём двигает змейку на финальном уровне части 2: опрос кнопок, проверка направлений, изменение координат — всё на AND-масках и переходах по флагам из прошлой статьи.
Проверь себя
Какой операцией установить бит 3, не трогая остальные?
OR с маской 00001000: единица «дорисовывается» в нужном разряде, остальные биты OR не меняет.
Почему AND 0xFF не меняет байт, а AND 0x00 стирает его целиком?
AND с единицей оставляет бит как есть, AND с нулём всегда даёт 0. Маска 0xFF — все единицы, 0x00 — все нули.
Чем XOR полезен при работе с битами?
Он переключает: XOR с 1 меняет бит на противоположный, XOR с 0 оставляет. Повторное применение возвращает всё как было.