GBA ASM - День 16: Маскировка и переключение битов

Дата публикации 10 сен 2006

GBA ASM - День 16: Маскировка и переключение битов — Архив WASM.RU

Маскировка

Сегодня мы перейдём прямо к делу. Наложение маски - это очищение определённых битов, оставляю другие нетронутыми. Это делается с помощью инструкции AND (по крайней мере в большей части случаев).

Код (Text):
  1.  
  2.     and (CPUregister),(CPUregister),(number or register)

Скажем, нам нужно очистить последние 16 битов регистра, но оставить другие как есть. Предположим, что мы используем r3:

Код (Text):
  1.  
  2.     and r3,r3,0xFFFF0000

Помните, что применение AND над битом и 1 всегда будет давать то значение, которое и было в AND изначально, а если использовать 0, то и результат всегда будет 0, так как логическая таблица AND следующая:

Код (Text):
  1.  
  2.         Таблица AND
  3.     -------------------------------
  4.     Старт  | ANDдится с | Результат
  5.     -------------------------------
  6.           0    |     1      |     0
  7.           0    |     0      |     0
  8.           1    |     0      |     0
  9.           1    |     1      |     1

Хорошо, если вы уже знаете это, такие таблиц нужны для людей, которым нужно понять всю эту двоичную логику (AND, OR, XOR, NOT) собственными силами, потому что они не использовали ассемблер ранее.

Ок, теперь вам, возможно, интересно, как шестнадцатиричные числа соотносятся с двоичными. Вот таблица:

Код (Text):
  1.  
  2.       Шестнадцатиричные в двоичные
  3.     ---------------------------------
  4.         0   |    0000
  5.         1   |    0001
  6.         2   |    0010
  7.         3   |    0011
  8.         4   |    0100
  9.         5   |    0101
  10.         6   |    0110
  11.         7   |    0111
  12.         8   |    1000
  13.         9   |    1001
  14.         A   |    1010
  15.         B   |    1011
  16.         C   |    1100
  17.         D   |    1101
  18.         E   |    1110
  19.         F   |    1111

Теперь вы знаете (если не знали раньше) как сконвертировать любое шестнадцатиричное число в двоичное. Так 0x0000FFFF становится %00000000000000001111111111111111. Процент - это символ, который используется в Goldroad'е для двоичных чисел.

Теперь, что если вы хотите замаскировать определённые биты. Вы можете использовать двоичную систему для инструкции AND. Какие биты вы сделает 0, так и будут 0, когда AND закончен, а те, что были 1 сделают так, что соответствующий бит останется тем, что и был (1 или 0). Пример:

Код (Text):
  1.  
  2.     ; мы хотеим, чтобы биты #3 и #15 обнулились. Не забывайте считать биты
  3.     ; от #0 слева направо.
  4.     and r3,r3,%11111111111111110111111111110111

Обратите на подчёркнутые '0'. Соответствующие биты в r3 будут также нулями, но всё остальное останется таким же, каким и было.

Теперь, если нам нужно установить биты в единицу, то мы используем OR. Посмотрите на таблицу этой инструкции:

Код (Text):
  1.  
  2.         Таблица OR
  3.     -----------------------------
  4.     Start  | ORed with | Result
  5.     -----------------------------
  6.           0    |     1      |   1
  7.           0    |     0      |   0
  8.           1    |     0      |   1
  9.           1    |     1      |   1

Вы можете видеть, что единица является результатом AND, если оба аргумента равны единице. Результатом OR является единица, если последняя является одним из аргументов (или оба).

Чтобы установить определённые биты в 1 (не знаю, зачем вам это может понадобится, но метод, о котором я вам говорю, работает), вам нужно применить на них OR. Биты, которые вы не хотите меня, вам нужно OR'ить с помощью 0. Таким образом, чтобы установить биты #6 и #4 регистра r3 в 1, нам нужно сделать следующее:

Код (Text):
  1.  
  2.     orr r3,r3,%00000000000000000100000001000000

Обратите внимание, что инструкция для OR - это ORR. Мне кажется, что это в каком-то смысле традиция для ARM-инструкций быть 3-х буквенными. Я надеюсь, что вы поняли, что над битами, которые нам нужно установить в 1, мы применяем 1, а над остальными 0.

Также заметье, что GBA - это 32-х битная система, поэтому нам нужно все 32 бита в наших двоичных числах. Если вы не поместите все 32, то думаю, что Goldroad будет считать неуказанные биты равными 0, но я не уверен.

Переключение

Во-первых, давайте определим, что это такое. Переключение - это изменение состояния между 1 и 0. Метод, показанный здесь полезен, чтобы переключать биты с помощью одной инструкции.

Простейший способ переключить все биты регистры сразу - это использовать инструкцию MVN. Её синтаксис следующий:

Код (Text):
  1.  
  2.     MVN (CPUregister),(CPUregister)

Все биты во втором регистре будут переключены, а результат возвращён в первый. Поэтому если вы просто хотите переключить все биты r3, сделайте так:

Код (Text):
  1.  
  2.     mvn r3,r3

Просто! MVN расшифровывается как "MoVe Negated" или "MoVe Not").

NOT - это битовая операция как OR и AND, но на входе она имеет лишь один аргумент:

Код (Text):
  1.  
  2.         Таблица NOT
  3.         --------------
  4.         Начало | Итог
  5.         --------------
  6.           0    |   1
  7.           1    |   0

NOT - это просто, не так ли? В то же время, иногда вам нужно переключить лишь некоторые биты, а не все из них. Для этого вам нужен XOR. Вот соответствующая таблица:

Код (Text):
  1.  
  2.         Таблица XOR
  3.     --------------------------------
  4.     Начало | ПоXORены с | Результат
  5.     --------------------------------
  6.       0    |     1      |     1
  7.       0    |     0      |     0
  8.       1    |     0      |     1
  9.       1    |     1      |     0

XOR возвращает 1, только если один (но не оба) из аргументов был равен 1. Поэтому XOR с единицей переключит бит. Синтаксис XOR'а следующий:

Код (Text):
  1.  
  2.     eor (CPUregister),(CPUregister),(number or register)

Обратите внимание, что инструкция для XOR'а - это EOR. Оба они расшифорвываются как "Exclusiv OR" (EOR) или "eXclusive OR" (XOR). Поэтому если мы хотим переключить биты #1 и #20:

Код (Text):
  1.  
  2.     eor r3,r3,%00000000000010000000000000000010

XORинг с нулём оставит бит в том же состоянии, что и раньше, но XORинг с единицей установит его в противоположное значение.

Несколько вещей, которые нужно запомнить

Несколько замечаний относительно переключения. Зачастую вам нужно будет задавать бит/биты, которые вам нужно переключить, с помощью константы. Вы можете переключить более чем один бит за раз, отделив константы символом '|':

Код (Text):
  1.  
  2.     eor r3,r3,SIZE_DOUBLE | MOSAIC
  3.     ; переключаем SIZE_DOUBLE и MOSAIC, полагая, что
  4.     ; r3 содержит соответствующие OAM-атрибуты

Надеюсь, что это было не слишком сложно.

Обзор этого дня

Я действительно надеюсь, что вы узнали сегодня что-то новое. Переключение и маскировка битов - это весело! © Mike H, пер. Aquila


0 1.607
archive

archive
New Member

Регистрация:
27 фев 2017
Публикаций:
532