GBA ASM

Discussion of development of software for any "obsolete" computer or video game system. See the WSdev wiki and ObscureDev wiki for more information on certain platforms.
DoNotWant
Posts: 83
Joined: Sun Sep 30, 2012 3:44 am

Re: GBA ASM

Post by DoNotWant »

Sweet, I started with GBA dev just 3 days ago!
Look for "Programming the GBA" by Jonathan S. Harbour. It's online in PDF format in various places, google around for it a little bit. Learn C also. The only reason C would look strange compared to any kind of ASM, is because you just never learned anything about C. You should be able to learn enough C to get going with the GBA book in a weekend, focus on pointers and type casting. The last chapter in the book is about using inline ASM in your C code.

http://jharbour.com/gba/ham-280-full-win32.zip Dev tool-chain
http://jharbour.com/gba/gba_files.zip Example code from book
JRoatch
Formerly 43110
Posts: 422
Joined: Wed Feb 05, 2014 7:01 am
Contact:

Re: GBA ASM

Post by JRoatch »

Whoa, Jonathan S. Harbour is the same author for a old Allegro game programming library book.

Anyway, back when I did GBA programing, tonc and gbatek were the only things I used, and they helped a lot.
User avatar
mikejmoffitt
Posts: 1353
Joined: Sun May 27, 2012 8:43 pm

Re: GBA ASM

Post by mikejmoffitt »

Ah yeah, I remember the HAM devkit. I host a copy of the installer since ngine.de went dead a long time ago. I have a decent tutorial PDF for the hamlib, but it would be nice to dig through actual documentation. I haven't looked at that since 2005 or so!
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: GBA ASM

Post by Drew Sebastino »

Bump! Everyone going to hate me for asking such a stupid question on an old thread, but I'm not going to start a new one for something as simple as this. What is the difference between mov and ldr? It seems that with mov, you can't load a very specific number and have to add latter to get the number you want, while with ldr, no such restriction exists. What is the point of mov then? Unlike the SNES, ARM processors are apparently supposed to do every instruction using one cycle, so you would have wasted twice as much time using mov than ldr. I even took the code from earlier:

Code: Select all

.text
main:
	mov r0, #0x4000000
	mov r1, #0x400
	add r1, r1, #3
	str r1, [r0]

	mov r0, #0x6000000
	mov r1, #0xFF
	mov r2, #0x9600
loop1:
	strh r1, [r0], #2
	subs r2, r2, #1
	bne loop1

infin:
	b infin
and made it...

Code: Select all

.text
main:
	ldr r0, =#0x4000000
	ldr r1, =#0x403
	str r1, [r0]

	ldr r0, =#0x6000000
	ldr r1, =#0xFF
	ldr r2, =##0x9600
loop1:
	strh r1, [r0], #2
	subs r2, r2, #1
	bne loop1

infin:
	b infin
And it works exactly the same way. (By the way, is there a good SNES Starterkit equivalent for the GBA? I think I saw the HAM Devkit thing was using C, and all of the other ones I've seen are too. Another thing, if THUMB is supposedly faster on the GBA than ARM, then why is just about every single tutorial/document regarding GBA development exclusively using ARM instead of THUMB?)
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: GBA ASM

Post by lidnariq »

LDR ("LoaD Relative") takes an extra memory access cycle.
And the assembler is supposed to convert it to a MOV if possible.

LDR actually stores your literal number somewhere else in memory, and instead stores a pointer to it, and tells it to load that value from memory.

See also http://www.coranac.com/tonc/text/asm.htm , scroll down to "PC-Relative specials"; or http://www.raspberrypi.org/forums/viewtopic.php?t=16528
Shonumi
Posts: 342
Joined: Sun Jan 26, 2014 9:31 am

Re: GBA ASM

Post by Shonumi »

Espozo wrote: Everyone going to hate me for asking such a stupid question on an old thread
Actually, keep the questions coming. For the past 6+ months, I've been doing GBA dev. Personally, I'd be more than happy to answer anything.
Espozo wrote: What is the difference between mov and ldr? It seems that with mov, you can't load a very specific number and have to add latter to get the number you want, while with ldr, no such restriction exists. What is the point of mov then?
MOV is just as it sounds, it moves a value into a register, however, the value is not from memory. In ARM, MOV's 2nd operand can be a register, a register shifted by another register, a register shifted by an immediate, an 8-bit immediate value, or a shifted 8-bit immediate value. Yes, it's a lot of options, but it explains why you can't load some of those "specific" values.

Any value you want to put into a register through MOV must 1) already exist in another register, or 2) can be created using bit-shifts of existing registers or immediates. LDR does not have this restriction since it's just taking bytes from memory, and memory values are generally arbitrary; they can be whatever.

To illustrate this, it's easy enough to use MOV to put the value 0x4000000 into R0. The assembler just specifies (when writing the actual ARM opcode), that the instruction will use an immediate value of 0x1 and perform a Rotate-Right shift of 6 (R0 is a 32-bit register, so the 1 wraps around to the top of the register, look up what ROR is if you're curious). On the other hand, putting something like 0x13371337 is not something you should tackle with MOV.

So what's the point of MOV? It doesn't use a memory access like lidnariq said, although MOV can take as long as some LDR instructions if you specify the Program Counter (R15) as the 1st operand and use a register shifted by another register as the second operand. MOV is nice and quick for setting registers to equal one another, or for many of the GBA's key addresses in the memory map (0x5000000 for Palette VRAM, for example). I use it a lot to clear out registers by setting them to zero. MOV can also affect the CPSR (Current Program Status Register) e.g. it sets the flags based on the result of the operation.
Espozo wrote: Unlike the SNES, ARM processors are apparently supposed to do every instruction using one cycle
Where did you hear that? At least for the GBA and DS, there are 4 different cycles. N-cycles (Non-sequential memory accesses), S-cycles (Sequential memory accesses), I-cycles (Internal cycles, generally the same length as 1 S-cycle) and C-cycles (Coprocessor stuff, applicable to the DS, but not the GBA). You can find instruction timings for the GBA's ARM7TDMI here -> http://infocenter.arm.com/help/index.js ... 02180.html

As you can see, only a few cases occupy a single type of cycle (generally 1S). A single instruction on the GBA can actually run for multiple CPU cycles depending on the Wait State (basically how long the CPU waits on a memory access). It is possible to write some code that runs exactly for 1Hz of the GBA's CPU clock, but most (at least any code that you want to do anything interesting with) will take more than one cycle. But when you see what MOV is in comparison to LDR, MOV is faster for what it is designed to do.
Espozo wrote: Another thing, if THUMB is supposedly faster on the GBA than ARM, then why is just about every single tutorial/document regarding GBA development exclusively using ARM instead of THUMB?)
Probably because most people aren't worried about following the development practices used for commercial games (e.g. ARM instructions executed in RAM, THUMB for most other things). ROM space likely isn't an issue when testing/distribution is going to be done on flashcarts or emulators, so the fact that ARM opcodes are twice as long as THUMB ones is probably not a concern. People doing ARM ASM on the GBA may also prefer the flexibility that ARM opcodes provide over the simplicity of THUMB opcodes. Then there is the possibility that for the programs they are making, speed just isn't an issue. Lastly, some people just don't like switching between ARM and THUMB. I'm one of them, but I'm a "THUMB everywhere" kinda person.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: GBA ASM

Post by Drew Sebastino »

Personally, I kind of like it simple. Trying to memorize 50,000 different instructions seems more like taking a quiz than doing something as a pastime. :roll:
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: GBA ASM

Post by lidnariq »

Shonumi wrote:I'm a "THUMB everywhere" kinda person.
(Tangent) Many years ago I was doing some development on Nokia's N800 tablet, and someone went and recompiled the entire userland to use THUMB instead of ARM. Just the smaller instructions helped speed things up and reduce memory consumption by a couple percent both. With the GBA's comparatively narrow and high latency memory bus, I have to assume it'd be even more useful.
Shonumi
Posts: 342
Joined: Sun Jan 26, 2014 9:31 am

Re: GBA ASM

Post by Shonumi »

Espozo wrote:Personally, I kind of like it simple. Trying to memorize 50,000 different instructions seems more like taking a quiz than doing something as a pastime. :roll:
Well, there are really only a handful of ARM and THUMB instructions. See GBATEK for a nice breakdown. You can even go further an lump some of them generically as Loading, Storing, Branching, etc. Trust me, before I started digging into the GBA's ARM CPU, I was equally overwhelmed. Just immerse yourself slowly, one piece at a time. I originally came from the GB's Z80-like CPU, so you can imagine what a shock ARM was to me.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: GBA ASM

Post by tepples »

On the GBA, I've found ARM instructions useful for three things: fixed-point multiplication (where you need to get a 64-bit result and then shift it down), IRQ handlers (which the BIOS calls in ARM mode), and signal processing inner loops executed in IWRAM, such as audio mixers. For everything else, Thumb is faster over the 16-bit bus of EWRAM, VRAM, and ROM.
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: GBA ASM

Post by Bregalad »

Unlike the SNES, ARM processors are apparently supposed to do every instruction using one cycle
Thanks to the processor pipeline, if you are using a memory where the processor can fetch instructions every cycle (in GBA's case read IWRAM), then most instructions that does not deal with memory and that does not branch should appear to be 1 cycle (including when there is bitshifts involved for example).

However the GBA is a bit werid because the processor will spend it's time waiting on memory most of it's time when executing from ROM or EWRAM.

Also the reason the tutorial teaches ARM assembly is that assembly is most likely used for the speed critical parts of a game engine, which should be coded in ARM and lay in IWRAM for maximum speed. If you want to save memory however, executing from ROM in THUMB is definitely the choice. Executing THUMB in IWRAM will be faster than ROM, but slower than ARM, and saving a lot of memory, and it also a good options for parts of the programs which are not too badly affected by the restrictions of the THUMB instruction set.
Shonumi
Posts: 342
Joined: Sun Jan 26, 2014 9:31 am

Re: GBA ASM

Post by Shonumi »

Bregalad wrote: most instructions that does not deal with memory and that does not branch should appear to be 1 cycle (including when there is bitshifts involved for example).
With ARM.5, you'll be doing anything greater than 1S cycle as soon as the 2nd operand is a register shifted by another register. Only shifts by immediates will avoid adding a 1I-cycle penalty, but shifting by a register rather than immediate is not something I do often. THUMB.4 has a similar rule about shifting. Essentially, any PSR transfer or ALU operation (THUMB and ARM) that doesn't shift by a register or use the PC as the destination register will have an execution time of 1S which is as fast as you're going to get in any memory location. THUMB.12 and THUMB.13 probably act a lot like specific cases of ADD/SUB, so that explains their 1S execution time as well.

Before I forget, unexecuted code also takes 1S cycle. The GBA will skip them at the speed of light ;)
Post Reply