Во-первых, инструкции ADD и SUB расшифровываются как сложение (addition) и вычитание (substraction). Они обе могут иметь суффикс установки флагов, что особенно полезно, когда надо узнать, был ли результат операции равен нулю (0).
У обеих инструкций 3 операнда (параметра): ADD r0, r1, 1 r0 = r1 + 1
Инструкция ADD складывает последние два параметра и помещает их в первый.
ПРИМЕЧАНИЕ: я думаю, что первые два параметра должны быть регистрами, но я не уверен.
SUB r0, r1, 2 r0 = r1 - 2
Инструкция SUB вычитает третий операнд из первого и помещает результат в первый.
Теперь, когда вы поняли, что такое ADD и SUB, давайте поместим на экран GBA картинку.
Используемый инструмент
Я использовал программу под названием Bimbo для экспорта картинки размером 240x160 в asm-формат. Скачайте её из раздела gfx-утилит на GBADev.Org. Теперь идите в Microsoft Paint (а лучше в какой-нибудь более приличный редактор - прим. пер.) и нарисуйте картинку размером 240 на 160 и сохраните её как 256-ти цветный битмап. Запустите Bimbo и нажмите кнопку "Открыть".
Нажмите кнопку "Export". При сохранение укажите "Assembler Source". Теперь начинается самое интересное. Bimbo не помещает '@' перед директивами в коде, который он генерирует, поэтому мы должны открыть наш любимый текстовый редактор и заменить DCW на @DCW. Чтобы сделать это как можно быстрее используйте функцию 'Replace All'.
Ок, теперь давайте напишем код для вывода нашей картинки на экран:
Замечание: переименуйте ваш asm-файл, в котором задана картинка, в pic.asm и откройте
Теперь идёт сам код:
; --Начинайте копировать здесь--
@include screen.h ; подключаем screen.h
b start ; перепрыгиваем через картинку (вы ведь не хотите,
; чтобы GBA попытался её выполнить? :-) )
@include pic.asm ; подключаем картинку
start ; метка по имени start
@textarea ; код начинается после этой директивы
; Так же как и в День 1 устанавливаем режим 3 с фоном 2
ldr r1,=REG_DISPCNT ; также как и в День 1
ldr r0,=(MODE_3|BG2_ENABLE)
str r0,[r1]
; Приготовляемся к помещению картинки в VRAM (видеопамять)
ldr r0,=VRAM ; делаем r0 указателем на VRAM (0x06000000).
ldr r1,=picBitmap ; делаем r1 указателем на данные с вашей картинкой
ldr r3,=19200 ; мы хотим получить доступ к памяти 19200 раз
; цвет экрана в режиме 3 16-ти битен,
; 240x160 pixels = 38400
; 19200, так как за раз мы копируем 2 пиксела
; (инструкция сохранения 32-х битна)
label1 ; метка по имени label1
ldr r2,[r1]+4! ; загружает в r2 следующие два (2) пикселя из данных с
; с картинкой (на которые указывает r1).
str r2,[r0]+4! ; сохраняет содержимое r2 (в нём 2 пикселя) в VRAM.
subs r3,r3,1 ; вычитает 1 количества раз, которое мы хотим получить
; доступ к видеопамяти (VRAM).
; обратите внимание на суффикс S в инструкции SUB - здесь
; мы задаём состояние флагов.
bne label1 ; эта инструкция перехода проверяет, указывает ли
; состояние флагов на нулевой результат. Если количество
; раз, которое мы хотим получить доступ к VRAM, не равно
; нулю (0), тогда продолжаем выполнение цикла.
infin ; метка под названием infin
b infin ; переход на infin
; предыдущие 2 строки являются бесконечным циклом. :-) while(1) {}
; сохраните этот файл как picscrn.asm
;--Заканчивайте копировать здесь--
Вы посмотрели код. Теперь давайте сассемблируем его!
Поместите pic.asm, screen.h и picscrn.asm в папку Goldroad. Сначала попытайтесь перетащить picscrn.asm в goldroad.exe, если он не создаст файл .GBA, тогда откройте DOS-окно, смените директорию на папку Goldroad'а и напечатайте:
Goldroad picscrn.asm и нажмите ввод
Эмулятор тоже должен быть в папке ассемблера, поэтому если это VisualboyAdvance, напечатайте:
Visualboyadvance picscrn.gba
Посмотрите на свою прелестную картинку на эмуляторе.
Поздра... Нет, есть ещё несколько вещей, которые требуют объяснений.
Вот эти 2 строки:
ldr r2,[r1]+4! str r2,[r0]+4!
Вы, вероятно, интересуетесь, что такое +4!, правильно? Я тоже не знал, что это такое, пока не провёл некоторые исследования. '!' означает хитрую вещь под названием "write-back", поэтому строка 'ldr r2,[r1]+4!' на самом деле означает следующее:
Загрузить в регистр r2 содержимое того, на что указывает r1, а затем, после того как всё сделано, добавить 4 к r1. Чтобы добавить 4 к r1 до того, как произойдёт загрузка в r2, необходимо составить инструкцию следующим образом:
ldr r2,[r1+4]! * +4 внутри скобок '[]' означает "добавьте 4 к r1 ДО выполнения инструкции" * Восклицательный знак должен находится в конце всей инструкции и означает 'write-back'.
Причина для делания 'write-back' на +4 заключается в том, что мы загружаем 2 пикселя за раз, а каждый пиксель равен 2 байтам (2*2=4). И помните, что мы обрабатываем 2 пикселя за раз, потому что каждый пиксель занимает 2 байта, а инструкции загрузки и сохранения 32-х битны.
Ух! Это была тяжёлая работа! Поздравляю! Вы прошли безжалостный День 3.
Я не знаю ещё о чём будет День 4, либо об обработке нажатия на клавиатуру, либо о БИОСе GBA.
- Надеюсь, вам понравилось.
[C] Mike H, пер. Aquila