第八章 BIOS
BIOS是一些GBA中预先写好的函数集。我们能使用指令SWI来调用它们。
SWI
SWI是SoftWare Interrupt(软件中断)。SWI的实质就是调用那些内置的函数,只要给出函数号就能工作了。比如:
mov r0, #0x10
swi 0x80000 @ SWI编号8是SQRT(SQuare RooT,开根号)。它会对r0开根号,然后把结果放到r0。
注意虽说SWI编号是8,但需要把SWI编号乘上0x10000(或者<< 16,一回事)。运行上述代码后,r0应该变成了4。
GBA上有很多BIOS函数,可以在到GBATEK上找到清单和用法。
现在我们有两件事情要做,一个是看看除法的BIOS函数,还有就是我们要用BGAffineTransform函数来旋转模式3的背景层。
除法的SWI编号是6,用法如下:
输入:
r0 = 有符号被除数
r1 = 有符号除数
输出:
r0 = r0 / r1
r1 = r0 MOD r1(也就是余数)
r3 = ABS(r0 / r1)(也就是商的绝对值)
我不觉得你需要一个示例代码,这个很一目了然了。
下面看我们的第二个小程序:
.arm
.data @ 所有.data的内容会被GCC的初始化程序放到RAM中
@ 我们想要的只是这个BGAffineSrc
.align 4
BG_affine_src:
.word 100<<8 @ 这些数字都是测试出来的(译注:原文并没有写这些值的具体含义,
.word 100<<8 @ 我也不给出了,看GBATEK去吧,下同)
.short 0x6F
.short 0x45
.short 0x280
.short 0x280
.zero 2.text
.global main
main:
mov r0, #0x4000000
mov r1, #0x400
add r1, r1, #3
strh r1, [r0]
@ 这就是第四章的代码
mov r0, #0x6000000
ldr r1, =pic
mov r2, #0x960
loop1:
ldmia r1!, { r3,r4,r5,r6,r7,r8,r9,r10 }
stmia r0!, { r3,r4,r5,r6,r7,r8,r9,r10 }
subs r2, r2, #1
bne loop1
mov r4, #0x4000000 @ 使用索引地址模式来访问I/O寄存器
ldr r0,=BG_affine_src @ r0指向BGAffineSrc这个结构
mov r1, #0x4000000
add r1, r1, #0x20 @ BIOS将计算结果写入到r1指向的地址
@ 我这里直接把它指向硬件寄存器了
mov r2, #1
eor r3, r3, r3
infin:
wait1:
ldrh r5, [r4, #6]
cmp r5, #161 @ 等待VBlank(译注:参考第五章)
bne wait1
strh r3, [r0, #16] @ 将角度写入结构中
add r3, r3, #40 @ 角度是一个8:8定点数
stmia sp, { r0,r1,r2,r3,r4,r5 } @ 保存现场
swi 0xE0000 @ 调用BIOS函数
ldmia sp, { r0,r1,r2,r3,r4,r5 } @ 恢复现场
b infin @ 无限循环
.ltorg
pic:
.incbin "pic.bin" @ 还是那个mode 3的图片
我不觉得这你通过一些工作后会难以理解这些东西。有一点要当心,你使用这些BIOS函数的话,那么运行VBA或者no$gba测试时要载入BIOS文件。还有no$gba的BIOS模拟比VBA略好些。这段程序可以在GBA实机上运行,和其他所有我给出的程序一样,除非我特别指明。