Symbian OS 6.1 Section

Symbian OS 6.1 Development using VC++ 6.0 Tutorial
 
Chapter 2: Basics and principles of Assembler:

 

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.

 

Go on to Chapter 3 (not implemented yet)