Well, this is my first tutorial. I'm personally learning ASM as I go, and writing these tutorials full of comments and such to help other beginners. It's really so much easier for a newbie to help a newbie; it sometimes gets hard for someone more advanced to get back down to newbie level and explain things. Hopefully this tutorial will get you past a bit and give you at least the ability partially understand what you see. First off, this assumes you're using GAS (GNU Assembler). Some of the assembly may work for ARM SDT, but I believe you'll have errors and stuff won't compile. Also, the command line to make things work will be different. Beyond that, I'll assume you already have GAS installed. I'm also going to assume you've previously programmed for the GBA using something like C, and therefore have a basic knowledge of how it works. Something important is understanding comments. They come after the line of code, preceded by an @ and followed by whatever you want. It was suggested I also say that standard comments in assembly (on the ARM SDT and other assemblers) are started with a ;. I guess I shall say, with this particular processor, assembly usually comes in the syntax of "opcode destination, source". There's sometimes a third opcode that modifies the second, such as lsl, but not always. Also, the opcode sometimes has a conditional operator or an s on it. The s is to tell it to set status flags, conditional operators (on things like branches) only execute that line if the condition is true. I'll give descriptions of all the opcodes I use in my little tutorial, but for more you'll have to go find a sheet listing opcodes, and/or the arm7tdmi docs (both available at I think www.gbadev.org and joat's website (www.bottledlight.com)). That said, on with the tutorial, which is going to be more of a line-by-line, complete description of everything. Tutorial: line 1: .GLOBAL _start @ exports the start lable for linking comment: Dunno exactly what it does. But, _start is the label in assembly that starts the processint, and you need the .global to export it to anything outside the assembly. Without this, the code will assemble/link/run, but on the linking stage it'll give warnings. line 2: _start: @ start of the code. Comment: a label. This one's special. It's combined with the line above to create the start of the code. Without it you'll get a linker error. line 3: mov r0,#0x4000000 @ Display control opcode: mov destination: r0 source: immediate comment: in this case, I'm putting a number (0x4000000) into the register (r0). Mov is often used for copying one register to another, also. In this case, I'm moving a number into a register for use later. YOu may have noticed it's the display control register. One thing that must be remembered: mov doesn't move things. It actually copies them. Always. Your source will be left exactly as it was found, with the destination containing a copy of the data. line 4: ldr r1,=0x0000403 @ store requested vid mode opcode: ldr destination: r1 source: literal comment: You may have noticed that I didn't use mov. This is because mov requires the number to fit into 8 bits (2 hex digits side by side: ff, 1f, fa; not f0c, 1ff, etc.). While this is true, mov can shift the number anywhere you wish (0xff00, 0xff, 0xff0000). Since mov has this limitation, we use ldr, or load register. This opcode can take any value since it loads it from RAM. One drawback of this, however, is it is slower. line 5: str r1,[r0] @ set it to background 2, mode 3 opcode: str destination: address in r0 source: r1 comment: The opposite of ldr, store register puts a register into RAM. Again, mov can't do this. line 6: mainloop: @ a label for the branch comment: this is another label. This one isn't special like _start is; it's just a label that we can branch to in order to form a loop. This will loop all the main code that needs to be looped. line 7: mov r0,#0x06000000 @ set video ram address opcode: mov destination: r0 source: immediate comment: this puts the number 0x6000000 into register 0. It'll be out holder for the video ram address. line 8: ldr r1,=0x0fff @ make a color opcode: ldr destination: r1 source: literal comment: Again, I have a number that takes up more than 8 bits, so I use ldr. This number is simply going to be a color value that I can put into RAM to plot a few pixels with. line 9: strh r1,[r0] @ put single pixel of above in vid ram opcode: strh destination: address in r0 source: r1 comment: Remember, r1 contains our 15 bit pixel, and r0 contains the start of the video RAM. This line puts 16bits in the destination, thus copying out pixel to the output buffer. The "h" modifier on the end of "str" causes it to copy a half-word. Without, it copies a full 32 bit word. line 10: mov r2,#0x02 @ put 2 to increase the vram by opcode: mov destination: r2 source: immediate comment: moves 2 into r2. It'll be used to add to the video ram address, allowing us to make a second pixel. line 11: strh r1,[r0,r2] @ put the r1 pixel in [r0 + r2] opcode: strh destination: address of: r0 + r2 source: r1 comment: Again we use strh to copy 2 bytes to memory. The 2 bytes are again our pixel contained in r1. The destination is again the address of r0, but because we have ",r2" inside the brackets, they're added together. This makes the address 0x6000002. line 12: b mainloop @ do the shit over and over. opcode: b comment: b is branch. It's used with a label, such as _start and mainloop. When used, it goes to that location and starts executing from there. This code returns the execution to mainloop and thus makes the code loop repeatedly. This is actually desireable. A common use for this is to gather input every loop, or create the new frames and update the display. Also, this is the GBA, and code should never end. line 14: .pool @ so it can ldr r0,=0x0005 stuff... comment: [boofly ] ok, .pool looks like it writes the literal table. be SURE not to put this in the middle of code. You should be able to have multiple .pool s. Each is just a table of data from which your ldr loads its values. The reason you might want multiple ones is that ldr uses a relative offset, so if your 'pool' is too far away it won't assemble - Thanks to Boofly from #gbadev, Efnet End asm tutorial Enter asm.bat line 1: as -marm7tdmi -mthumb-interwork asm.asm comment: the command is as, the first arguement is -m followed by the processor. The second arguement is commonly used, and I think it's to allow changing from arm to thumb, and compilation of thumb, although I'm not sure. asm.asm is the source file. If you wished, you could add a -o outputfilename. All it does is change the output from a.out. line 2: ld -Ttext 0x08000000 -Tbss 0x03000000 -o asm.elf a.out comment: the linker. I have no idea what -Ttext and -Tbss do. I tried it once and it seems to work fine without them. "-o asm.elf" is to specify the output file, and a.out is the file generated by the assembler. I don't know for sure if this step is completely required (if you use objcopy), but it is if you wish to combine multiple assembly files or C source. line 3: objcopy -v -O binary asm.elf asm.bin comment: if you link and output a .elf file, mappy can read that and run it. This is for other emulators who require the binary data only. End tutorial. Hope you learned something, and the next one won't be this descriptive.. I won't point out the opcodes, and it's unlikely I'll point out the destination/source as much, and also won't point out most of the stuff I've explained here. I may update my make batch files to include extra settings that make it run better, but I dunno. Hope you learned, hope there's more to come. -DrkShadow http://drkshadow.no-ip.com http://members.core.com/~blairk