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

Все статьи

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

Маскировка

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

	and (CPUregister),(CPUregister),(number or register)

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

	and r3,r3,0xFFFF0000

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

		Таблица AND 
	-------------------------------
	Старт  | ANDдится с | Результат
	-------------------------------
          0    |     1      |     0
          0    |     0      |     0
          1    |     0      |     0
          1    |     1      |     1

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

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

	  Шестнадцатиричные в двоичные
	---------------------------------
		0	|    0000
		1	|    0001
		2	|    0010
		3	|    0011
		4	|    0100
		5	|    0101
		6	|    0110
		7	|    0111
		8	|    1000
		9	|    1001
		A	|    1010
		B	|    1011
		C	|    1100
		D	|    1101
		E	|    1110
		F	|    1111

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

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

	; мы хотеим, чтобы биты #3 и #15 обнулились. Не забывайте считать биты
	; от #0 слева направо. 
	and r3,r3,%11111111111111110111111111110111

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

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

		Таблица OR
	-----------------------------
	Start  | ORed with | Result
	-----------------------------
          0    |     1      |   1
          0    |     0      |   0
          1    |     0      |   1
          1    |     1      |   1

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

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

	orr r3,r3,%00000000000000000100000001000000

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

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

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

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

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

	MVN (CPUregister),(CPUregister)

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

	mvn r3,r3

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

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

		Таблица NOT 
		--------------
		Начало | Итог 
		--------------
       	  0    |   1 
		  1    |   0 

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

		Таблица XOR
	--------------------------------
	Начало | ПоXORены с | Результат
	--------------------------------
	  0    |     1      |     1
	  0    |     0      |     0
	  1    |     0      |     1
	  1    |     1      |     0

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

	eor (CPUregister),(CPUregister),(number or register)

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

	eor r3,r3,%00000000000010000000000000000010

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

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

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

	eor r3,r3,SIZE_DOUBLE | MOSAIC
	; переключаем SIZE_DOUBLE и MOSAIC, полагая, что
	; r3 содержит соответствующие OAM-атрибуты

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

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

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

2002-2013 (c) wasm.ru