For those that have never coded in assembler before, you can think of it as another programming language, with a limited amount of variables and instructions available to the programmer. Very limited that is. Variables in assembly are called registers. They are an integral part of the CPU. There are general purpose registers for doing all your math and special registers that have dedicated use.
Furthermore, since everything in the system uses these registers, you need to take great care of restoring them after your functions are done using them. This is usually done using the stack as a temporary storage area.
Now lets get down to coding.
Cut and paste the code below into your mytest.cpp file:
#include <e32std.h>
void ClearScreen(TUint16* address, TUint16 color)
{
TUint16* tmpScreenAddress = address;
for(TInt k = 0; k < 176 * 208; k++)
*(tmpScreenAddress++) = color;
}
Then create mytest.h inside your mygame/inc directory. This should be the contents:
#include <e32std.h>
void ClearScreen(TUint16* address, TUint16 color);
Just a forward declaration for the function we are about to implement.
Add the following line to the include section at the top of MyGameContainer.cpp.
#include "mytest.h"
And finally add these lines at the beginning of the void CMyGameContainer::Draw(const TRect& aRect) const method:
TUint16 testarea[256];
ClearScreen(testarea, 0xfff);
I will also show how to take some of the mysteries of assembly coding by letting the compiler show us how certain things are done. For now, change the following lines in your mygame.mmp file:
//#ifdef MARM
//SOURCE mytest.s
//#else
SOURCE mytest.cpp
//#endif
This enables mytest.cpp to be included in the ARMI build we are about to do and disables the mytest.s file (this is the one we are creating right now) to be included. At the command prompt type:
C:\code\MyGame\group>abld makefile vc6
This will update your workspace to include mytest.h
Then type:
C:\code\MyGame\group>abld build armi urel
To compile the code and:
C:\code\MyGame\group>abld listing armi urel
To create the listing file.
This will cause the compiler to spit out assembly listings for everything it compiles. The one we are interested in is the mytest.lis file. It resides in the mygame/src directory.
Open it in your favorite code editor and look at these 2 lines:
6
.global ClearScreen__FPUsUs
7 ClearScreen__FPUsUs:
The first line tells the linker that the ClearScreen function is defined here. Note that C++ mangles names of the functions so it can do proper overloading.
The second line is the actual label itself where our subroutine lives.
Parameter passing if there are only few parameters works conveniently using registers. In this case, r0 contains address and r1 contains the color.
Now here is something interesting:
Since the second parameter is a TUint16, it clears out the upper half of r1 before using it, like so:
10 0000 0118A0E1
mov r1, r1,
asl #16
ß
shift left by 16
11 0004 2118A0E1 mov r1, r1, lsr #16 ß shift right by 16, pulling in 0’s in the upper 16 bit.
This isn’t the most efficient way to do things in our example, since all we do is store the lower half of r1 (our color) anyways and we don’t care about the upper 16 bit.
So, if you are to implement the .s file, you can cut and paste the .lis file, get rid of the line numbers and leave the 2 lines above out. Your mytest.s file should now look like this:
@ Generated by gcc 2.9-psion-98r2 (Symbian build
540) for
ARM/pe
.file "Mytest.cpp"
.gcc2_compiled.:
.text
.align 0
.global ClearScreen__FPUsUs
ClearScreen__FPUsUs:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 0, current_function_anonymous_args = 0
@ this is where the 2 deleted lines should have been
mov
r3, #0
ldr
r2, .L636
.L634:
strh
r1, [r0], #2 @
movhi
;; CYGNUS LOCAL nickc
add
r3, r3, #1
cmp
r3, r2
ble
.L634
bx
lr
.L637:
.align 0
.L636:
.word 36607
All you need to do now, is restore the .mmp file to its original state (remove all the comments we put in earlier), then do a new armi build:
C:\code\MyGame\group>abld build armi urel
And everything should compile and link.
Voila, you just created your first assembly file and optimized it as well! Use the listing method every time you wish to figure out the C++ mangling since it is not very intuitive.