GBA ASM - День 11: Переменные и рабочая память — Архив WASM.RU

Все статьи

GBA ASM - День 11: Переменные и рабочая память — Архив WASM.RU

Почему?

Сначала я собирался в этот День писать о проигрывании wav-файла. Затем я понял, что не рассказал об одной вещи, которую всегда использовал, но никогда не говорил о ней ничего конкретного, а именно - загадочная область памяти, располагающая в 0x3000000. Мы немного использовали это пространство для некоторых (32-х битных) переменных, т.е. не совсем переменных, но это так близко к переменным как может быть для нас, программистов на ассемблере.

Как это делается

Начнём с начала. Если вы программировали на C или QBasic или чём-угодно, вы знаете, что у переменных есть тип. Ок, сейчас я развею это заблуждение. Наши переменные всегда 32-х битные (на самом деле не всегда, они могут быть размером с байт или 16-ти битными, об этом позже). Да, именно так, никаких типов, считайте, что это почти тоже самое, что регистр CPU (gbaguy весьма волен в допущениях - прим.пер.), не считая того, что требуется 2 строки кода, чтобы получить к ним доступ.

Чтобы объявить переменную, нужно сделать следующее:

variable_name @DCD initial_value

Соответственно, если я хочу объявить переменную под названием num1 с начальным значением 0x0000F6A2, то делаю так:

num1 @DCD 0x0000F6A2

Мило, правда?

Несколько проблем

Если вы действительно искусны, вы можете заметить, что этот способ объявления переменные порождает несколько проблема.

  • Переменная теперь находится в ROM.
  • Объявление переменной в ROM заставить CPU выполнить байты, находящиеся в ней.

Мне нужно признаться кое в чём. Я уже говорил об этом, но повторю ещё раз: наши переменные не большее метки адреса в памяти, и Goldroad, вероятно, должен назначить им адреса. Как бы то ни было, избавиться от этих проблем также легко, как добавить две строки с директивами Goldroad'а (которые начинаются с символа '@'). Вот эти строки:

@textarea 0x3000000 и @endarea.

Т.о., получилось следующее:

@textarea 0x3000000
num1 @DCD 0
@endarea

Обратите внимание, что в этот раз я инициализовал область памяти (нашу переменную) нулём. Я люблю помещать все свои переменные в один блок @textarea, так как если вы используете другой, то

@textarea 0x3000000
num2 @DCD 0x9
@endarea

обратите внимание, что теперь у вас есть две переменные, которые указывают на одну и ту же область в памяти. Измените одну и попробуйте получить доступ к другой и вы увидите, что её значение так же изменилось, они обе - это алиасы одной и той же области памяти. Поэтому помещайте все ваши "переменные" в один блок @textarea@!

Установка значения WRAM

Теперь, когда мы их объявили, нам следует установить их значение. Вот, что нужно сделать для этого, предположив, что в r1 находится нужное нам нужно нам значение.

ldr r0,=num1     ; помещаем адрес num1 в r0.
str r1,[r0]    ; помещаем содержимое r1 в память по адресу, хранящемуся в r0.
; помните, что наши переменные - всего лишь алиасы для адресов памяти.

Вот и всё. Довольно просто. Получение значения будет немного сложнее.

Получение значения переменной в WRAM

Ок, я просто сделаю это и прокомментирую:

ldr r0,=num1    ; помещаем адрес num1 в r0
ldr r1,[r0]     ; загружаем в r1 содержимое памяти по адресу, хранящемуся в r0
; там хранился адрес нашей переменной, а значит теперь в r1 - её значение.

Обратите внимание, что последняя строка кода - это прямая противоположность инструкции str, так как если бы мы написали str r1, [r0], то мы бы поместили r1 в память по адресу в r0, вместо того, чтобы поместить в r1 содержимое памяти по адресу в r0. Как вы можете видеть, это обратные друг другу инструкции.

Это всё, что вам нужно знать. Не слишком сложно, но важно.

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

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

Вот и всё на сегодня, надеюсь, вам понравилось.

2002-2013 (c) wasm.ru