GBA ASM - День 12: Инструкция BL

Дата публикации 6 авг 2006

GBA ASM - День 12: Инструкция BL — Архив WASM.RU

Что мы делаем сегодня?

Сегодня мы рассмотрим подпрограммы (или функции), используя инструкцию BL. Странно, что я никогда не рассказывал о ней, ведь она так проста...

Инструкция BL

Инструкция BL расшифровывается как Branch with Link (Ветвление со связью). Это означает, что она делает то же, что и обычная инструкция B, не считая того, что помещает в r14 определённое значение. r14 также известен как lr. Вы можете использовать оба варианта, т.к. они означают одно и то же, и Goldroad'у не важно, что вы выберите. Если я никогда не говорил этого раньше, то r15 также известен как pc.

С регистр r15 (или pc), как вы уже должны знать из Дня 2, лучше не связываться лишний раз, т.к. он содержит адрес следующей инструкции, которая должна быть выполнена. Если вы меняете значение в нём, то фактически вы совершаете переход на какое-то место в памяти. Позже мы сделаем это, чтобы вернуться из одной из наших "функций".

Это значение в r14...

Я сказал ранее, что инструкция BL кладёт некое значение в 14. Это значение - адрес возврата. Если говорит точнее, это адрес инструкции, идущей сразу после BL. В отличии от x86-процессоров, инструкции RET здесь нет. Мы должны скопировать адрес возврата из r14 в r15. Вот простой способ сделать это.

Код (Text):
  1.  
  2. mov r15,r14

Это и есть наша инструкция возврата. Вы также можете использовать LDR, но мне кажется, я где-то читал, что MOV быстрее, когда дело касается копирование содержимого из одного регистра CPU в другой.

Как только эта строка будет выполнена, CPU вернётся к инструкции, которая шла после инструкции BL, которую вы использовали для перехода к функции.

(Очень) Маленький пример

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

Код (Text):
  1.  
  2. ;;--- НАЧАЛО КОДА ---;;
  3. @include screen.h ; screen.h с необходимыми константантами,
  4.                   ; требуемые даже в такой маленькой программе.
  5.  
  6. ldr r1,=REG_DISPCNT
  7. ldr r2,=(MODE_3|BG2_ENABLE) ; 3 строки для установки режима экрана
  8. str r2,[r1]
  9.  
  10. bl DrawDot   ; переход на процедуру DrawDot
  11.  
  12. infin     ; после возврата начнётся бесконечный цикл
  13. b infin  
  14. ;;--- СТОП КОПИРОВАНИЕ ---;;

Вот процедура DrawDot:

Код (Text):
  1.  
  2. ;;--- НАЧАЛО КОДА ---;;
  3. DrawDot  ; метка под названием DrawDot
  4.  
  5. ldr r1,=VRAM+0x2410 ; эти три линии отрисовывают
  6. ldr r2,=0x45678912  ; 2 пикселя на экране.
  7. str r2,[r1]
  8.  
  9. mov r15,r14 ; возвращение в основную программу
  10. ;;--- КОНЕЦ КОДА ---;;

Обратите внимание, что вам не должны ничего делать с r14 внутри, иначе вы потеряете адрес возврата. Также никогда ничего не делайте с r15, кроме вышеуказанного случая возврата из процедуры.

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

Не знаю, почему не объяснил вам это раньше, ведь это так легко. Сожалею, если вы ожидале чего-то более "крутого". Больше здесь не очень рассказывать. Хорошего программирования. © Mike H, пер. Aquila


0 897
archive

archive
New Member

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