|
 |
Welcome to PocketMatrix.com, a Mobile Devices enthusiast website. If you're a developer, be sure to check out our developer forums. You can change your sidebar preferences in your Profile. |
Posted: Wed Feb 20, 2002 11:04 am | Post subject: ARM Assembler Programming PPC FAQ> |
|
Wrecked
Guest
|
Can anyone give me any information an writing assembler for arm using VC++ embedded tools.
An example would make all my dreams come true
|
Posted: Wed Feb 20, 2002 11:29 am | Post subject: > |
|
simonjacobs
pm Insider

Joined: 27 Nov 2001
Posts: 322
Location: London, UK

|
This is a FAQ for ARM assembler programming on the Pocket PC.
Maintained by Simon Jacobs
Version 1.0 (22'nd Jan 2002)
I have done my best to make this accurate and useful, but I make no guarantees. Remember that assembler programming is complex and if you are unsure of yourself you should ask for help. Please email me if there are any questions you would like to see added to the list.
--------------------------------------------------------------------------------
1) Is there a good book about ARM assembler?
2) Can I use inline assembler in my c code with Embedded Visual C++?
3) Can I see what assembler code the c compiler creates?
4) How do I add an assembley source file to my project, and get EVC to assemble it?
5) How do I write a function in assembler and call it from the c code?
6) How are values passed to and from the assembler function?
7) Can I use any of the 16 registers for anything?
8) Useful resources.
--------------------------------------------------------------------------------
1) Is there a good book about ARM assembler.
ARM System-on-chip architecture (second edition)
Steve Furber
Addison-Wesley
As well as some chapters aimed more at hardware designers, it has an explanation of the ARM instruction set plus a complete reference of the assembler format for each one. It doesnt teach programming in any way, but if you are experienced in c programming and just need full details of the instruction set and info on how the processor works it is great.
2) Can I use inline assembler in my c code with Embedded Visual C++?
There is no supported way of doing this. You need to put your assembler in seperate functions which can be called from your c code. See below for details of how to do this.
3) Can I see what assembler code the c compiler creates?
Yes, and this is very useful for a few reasons. You can see how optimal the code being produced is, and also learn how the compiler does things. You need to:
From the 'Project' menu choose 'Settings'. Go to the 'C/C++' tab. In the 'Category' drop-down-list choose 'Listing Files'. In the 'Listing file type' drop-down-list choose 'Assembley with Source Code'.
Now the compiler will produce .asm files in the output directory which contain the assembler code with the c source as comments.
4) How do I add an assembley source file to my project, and get EVC to assemble it?
Create a blank file 'myfile.asm' in your project directory with notepad. From the menu in EVC select 'Project->Add to Project->Files' set the 'Files of type' field to 'All Files' and select the myfile.asm file. It will appear in the file list on the left, drag it into the 'Source Files' section.
Select 'Project->Settings' from the menu. On the left of the dialog: select the 'ARM release' configuration and select the 'myfile.asm' file. On the right of the dialog: select the 'Custom Build' tab. In the 'Commands' box add the text 'armasm myfile.asm' and in the 'Outputs' box add the text 'myfile.obj'. Repeat this for the 'ARM debug' configuration.
Now you can open and edit myfile.asm from EVC and it will be assembled into your project.
5) How do I write a function in assembler and call it from the c code?
First a note about the assembler source code layout. All command lines should begin with a tab. Any lines that have text on the left are labels. You need to use labels for function names and as targets for branch instructions. Use a semicolon to mark the rest of a line as a comment. The file should finish with an END command.
Example file:
Code:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| AREA ArmGfxLib,CODE,READONLY EXPORT FunctionA EXPORT FunctionB
FunctionA MOV r12, sp stmfd sp!, {r4-r11,lr}
; useful code to do something goes here!
ldmfd sp!, {r4-r11,pc}
FunctionB MOV r12, sp stmfd sp!, {r4-r11,lr}
; useful code to do something goes here!
ldmfd sp!, {r4-r11,pc}
END
| | 21 lines; 2 keywds; 0 nums; 32 ops; 0 strs; 0 coms Syntactic Coloring v0.3 - Dan East |
Explanation: the AREA command gives a name to this code section. The EXPORT command makes those labels available as functions. The stmfd/ldmfd commands save and restore the registers to the stack, so you dont corrupt values that the calling function depends on.
In your c++ code add the line:
#ifdef ARM
extern "C" void FunctionA(int a, int b);
#endif
The #ifdef is because we have written the function in ARM assembler so it isnt available in MIPS/SH3 builds.
6) How are values passed to and from the assembler function?
If you declare a function of the form:
extern "C" int armfunction(int arg1, int arg2, int arg3, int arg4, int arg5, int arg6);
The first 4 arguments will be passed in the registers r0-r3. These registers will contain the passed values at the start of your assembler function. Further arguments are passed on the stack, see the code below to read them.
The return value should be placed into register r0 at the end of your assembler function (just before you return to the caller).
This works well with int's and pointers (all pointers are 32 bits). If you try and pass a structure directly as an argument it gets more complex. I advise you to only pass/return integers and pointers to/from your assembler functions, at least to start with.
Here is an example function (declared as above) which adds its six arguments and returns the result.
Code:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| armfunction MOV r12, sp ; these two lines are stmfd sp!, {r4-r11,lr} ; standard setup code
; r0-r3 are the first 4 arguments passed
ldr r4, [r12] ; load 5'th argument into r4 ldr r5, [r12, #4] ; load 6'th argument into r5
add r0, r0, r1 ; r0 = r0 + r1 add r0, r0, r2 ; r0 = r0 + r2 add r0, r0, r3 ; r0 = r0 + r3 add r0, r0, r4 ; r0 = r0 + r4 add r0, r0, r5 ; r0 = r0 + r5
ldmfd sp!, {r4-r11,pc} ; standard cleanup and return code
| | 16 lines; 1 keywds; 3 nums; 52 ops; 0 strs; 0 coms Syntactic Coloring v0.3 - Dan East |
7) Can I use any of the 16 registers for anything?
No. You can use r0-r12 and r14 for anything you like. r15 is the program counter, if you write a value to it then execution will jump to that location. Use the branch instruction, dont alter it directly. r13 is the stack pointer, do not alter it unless you are sure you know what you are doing. r14 (which you can use) is the link register. If you want to call another function you need to set this to the return address, I will include an example in a future version of this FAQ.
8) Useful resources.
|
Posted: Wed Feb 20, 2002 11:40 am | Post subject: thanks> |
|
wrecked
Guest
|
Thats great mate..
Im now in ecstasy
cheers!!!!!!!
|
Posted: Wed Feb 20, 2002 11:43 am | Post subject: address> |
|
wrecked
Guest
|
What is the url for soup kitchen and other stuff
|
Posted: Wed Feb 20, 2002 11:44 am | Post subject: > |
|
simonjacobs
pm Insider

Joined: 27 Nov 2001
Posts: 322
Location: London, UK

|
8) Useful resources.
|
Posted: Wed Feb 20, 2002 12:10 pm | Post subject: > |
|
refractor
pm Insider

Joined: 05 Feb 2002
Posts: 2259
Location: Luxembourg
|
Hiya.
Firstly, you can't (easily) embed ARM assembler in EVC++ (which *stinks*).
So, you must make external ARM files.
For example, take this and save it as "clear_screen.s":
Code:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| ; TITLE("clear_screen") ;++ ; ; ; Module Name: ; ; clear_screen.s ; ; Abstract: ; ; Test procedure to compile and run on my IPAQ... (keyword there is test) ; ;
AREA screen_writer, CODE, READONLY ; name this block of code
EXPORT clear_screen_arm
; simple, unoptimised CLS routine, hard-coded to a 16bpp 320x240 screen.
; Takes address of screen in R0 ; colour in R1
clear_screen_arm stmfd sp!, {r0-r12,r14} add r1,r1,r1,lsl #16 ; colour into both pixels please mov r2,r1 mov r3,r1 mov r4,r1 mov r5,r1 mov r6,r1 mov r7,r1 mov r8,r1 mov r9,r1 mov r10,r1 mov r11,r1 mov r12,r1
mov r14,#320 clear_screen_arm_inner stmia r0!,{r1-r12} ; store 24 pixels in one shot. stmia r0!,{r1-r12} ; store 24 pixels in one shot. stmia r0!,{r1-r12} ; store 24 pixels in one shot. stmia r0!,{r1-r12} ; store 24 pixels in one shot. stmia r0!,{r1-r12} ; store 24 pixels in one shot. stmia r0!,{r1-r12} ; store 24 pixels in one shot. stmia r0!,{r1-r12} ; store 24 pixels in one shot. stmia r0!,{r1-r12} ; store 24 pixels in one shot. stmia r0!,{r1-r12} ; store 24 pixels in one shot. stmia r0!,{r1-r12} ; store 24 pixels in one shot.
subs r14,r14,#1 bne clear_screen_arm_inner
ldmfd sp!, {r0-r12,pc}
END
| | 57 lines; 1 keywds; 12 nums; 135 ops; 1 strs; 0 coms Syntactic Coloring v0.3 - Dan East |
Now, you need to compile it. With your path set correctly, at a command/dos prompt run:
armasm clear_screen.s
(you can include a macro to compile your *.s files elsewhere in you project - this has already been discussed somewhere on this board, IIRC).
Now, move the clear_screen.obj file to where you want it, and make sure that the directory is in the:
Tools -> Options ->Directories -> Library files
list.
In the C file that calls the function, put (I put it just after the #includes):
Code:1
| extern "C" void clear_screen_arm(DWORD,unsigned short);
| | 1 lines; 4 keywds; 0 nums; 4 ops; 1 strs; 0 coms Syntactic Coloring v0.3 - Dan East |
... and here's a function that calls it and sets the screen pink (uses GAPI to get the screen location, then munges it for my iPAQ):
Code:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| bool ClearScreen() { unsigned short * pusLine = (unsigned short *)GXBeginDraw(); if (pusLine == NULL) return false; // NOT OK TO DRAW, return failure.
// WARNING hard-coded for the purposes of it actually running on my iPAQ 3600 // gxbegindraw doesn't give me the first pixel of the display buffer, // but the END pixel of the first line.
pusLine-=319;
clear_screen_arm((DWORD)pusLine,0xf81f); // 0xf81f = 1111100000011111 = red + blue = pink GXEndDraw(); return false; }
| | 15 lines; 10 keywds; 2 nums; 30 ops; 0 strs; 5 coms Syntactic Coloring v0.3 - Dan East |
I might be doing silly things with the C code.. ('cos I haven't done C for *years*)... but it compiles and has the desired effect on my iPAQ - I put the code into the FirstGX example and called it instead of their:
Code:1
| bool ClearScreen(int colRed,int colGreen, int colBlue)
| | 1 lines; 4 keywds; 0 nums; 4 ops; 0 strs; 0 coms Syntactic Coloring v0.3 - Dan East |
function. Adding the parameters to the C function to pass the "correct" value to the ARM function is trivial - see the thread about "How to calculate the real RGB color for GAPI? "
http://forums.pocketmatrix.com/viewtopic.php?t=4048
for that.
(a pink screen isn't much, but it's a start. ).
If anybody can point out errors in the C, I'd appreciate it (do I need to cast it to a DWORD?).
Hope that helps, cheers,
Refractor.
|
Posted: Wed Feb 20, 2002 12:16 pm | Post subject: > |
|
simonjacobs
pm Insider

Joined: 27 Nov 2001
Posts: 322
Location: London, UK

|
just a minor note: you only need to save r4-r11, not r0-r12
I prefer the method in my FAQ for adding seperate files just because I can then edit the asm in the evc editor, and it will automatically reassemble it when it changes.
|
Posted: Wed Feb 20, 2002 12:20 pm | Post subject: > |
|
simonjacobs
pm Insider

Joined: 27 Nov 2001
Posts: 322
Location: London, UK

|
the c looks fine, you do have to compute the offset to the first pixel as you say, the only thing i would change is adding a test for the machine type. different machines will need different offsets to work.
my approach is to do all drawing to my own screen buffer then copy to display memory at the end. That is FAR faster on the iPaq than drawing directly to the screen, because the iPaq screen memory is not write-cached.
|
Posted: Wed Feb 20, 2002 12:42 pm | Post subject: > |
|
refractor
pm Insider

Joined: 05 Feb 2002
Posts: 2259
Location: Luxembourg
|
True, true, point taken... for this example.
I tend to optimise the stacking later in the process - a lot of the time I ignore the call standard conventions because I call some ARM functions only from ARM functions (I do a lot of ARM stuff largely because I'm more proficient in ARM than I am in C), later on in the process I know better what does and doesn't need to be stacked for each function, and can start eliminating excess stacking.
I always err on the side of caution to begin with and stack everything; if I called it from another ARM function, I might not expect it to corrupt the first four registers - always expecting the first 4 registers and r12 to be corrupted for every ARM routine is wasteful if you're only ever going to call one or two functions from C.
Your other comment was what I meant when I said:
Quote: (you can include a macro to compile your *.s files elsewhere in you project - this has already been discussed somewhere on this board, IIRC).
Thanks for looking at the C. Sure, it needs to add a test for the machine type, etc, - it was just a quick example I knocked up to help the guy who started the thread.
My implementation uses double buffering at the moment, too. Whether it's faster to do so I haven't checked with my code - my code writes to the buffer in sequential order, but what it doesn't do is 24-pixel writes in a single instruction, which is more cache coherant than my STRs if nothing else.
Cheers,
Refractor.
|
Posted: Wed Feb 20, 2002 12:52 pm | Post subject: > |
|
simonjacobs
pm Insider

Joined: 27 Nov 2001
Posts: 322
Location: London, UK

|
fair enough
are you working on a game in assembler?
i'm busy trying to write a 3d engine, its taking a lot of effort.
|
Posted: Wed Feb 20, 2002 1:22 pm | Post subject: > |
|
refractor
pm Insider

Joined: 05 Feb 2002
Posts: 2259
Location: Luxembourg
|
I've been working on a 3d engine in dribs and drabs. At the moment I'm worked off my feet (not PocketPC related), *and* I've been offered another contract so I'm gearing up for the interview for that.. there just never seems to be enough time right now.
Essentially, yes, I'm working on several games (I never could just do one thing at once, but most of them share the same engine constituents):
a "micro-machines" clone with added 3d-ness (3d cars, obstacles, etc, but tiled-graphics thrown in too for the majority of the 'ground').
a parallax platformer game with *huge* levels (I actually started that one with the GBA in mind.. but the iPAQ will do just as nicely, if not better).. that one's stymied at the moment for technical reasons - real-time decompression of the tiled map is a sticky issue. Well, I know how to decompress it (very) efficiently.. but bizarrely it's the *compression* routine I'm stuck with (it's non-trivial to say the very least). I know how I want to compress it (in a weird way )... I just don't know how to go about doing it algorithmically without running into travelling-salesman type issues (exponential growth of the function's time to run). I'm still attacking some research papers on the techniue though, so it may turn out to be ok in a couple of months.
...after I've either played with those enough, or released them (unfortunately, don't hold your breath), I'll be playing with getting a 3d terrain engine up... or a "fake" 3d platformer.
I know *how* I'm going to do a lot of it, but I just haven't had the time to sit down and do it... Due to the way I study things I'm probably 'missing' some rudimentary knowledge too so my 'know how' may turn out to be flawed. I won't know until I do it, yet I haven't got time to do it. Aaargh, the eternal dilemma. It gets worrying when I'm annoyed at my girlfriend for arranging a one week ski holiday because I'll be without a real development environment for a *whole week*.
If you need any help with anything that I may be able to help with (general comments, ARM stuff), give me a yell - I'm always happy when people give me things to think about.
Cheers,
Refractor
|
Posted: Wed Feb 20, 2002 1:49 pm | Post subject: terrain> |
|
wrecked
Guest
|
Id like any info on how to build a terrain engine..i kinda know what you need but putting it altogether is the problem.
On another point...ive been asked to write a couple of games .. which is great , but ive been offered a profit share as payment...this is ok too, but do these things sell..is there any money in developing for the pocket pc or is it just a fun tool TO PLAY WITH..????/
|
Posted: Wed Feb 20, 2002 2:10 pm | Post subject: > |
|
refractor
pm Insider

Joined: 05 Feb 2002
Posts: 2259
Location: Luxembourg
|
Terrain engine details and some nice references here:
http://www.gamasutra.com/features/20000403/turner_pfv.htm
(you may need to register to read it, but I can highly recommend it and it's free). If you want to program games, there's an awful lot of useful information at GamaSutra.
I'm doing my games as a side-line hobby, 'cos I'm pretty sure I'll always earn more doing what I do than being a games programmer, *especially* on a platform that's not really designed for gamers.
If you want to make money then maybe it's worth considering targeting the ARM based Gameboy Advance... but the problem there is getting a publisher.
I'm messing about with mine simply 'cos I like (where's the 'fawning' smiley when you need one?) ARM processors. iPAQs, etc, make better toys than development boards with no screen and limited upgrade potential.
I would *guess* that the games that have sold the most are aimed at middle-aged businessmen with no lives (thus, Pocket Strip Poker, SimCity2000, boring damn Golf games).
Looking at Handango, it seems that SimCity2000 has been downloaded 29511 times ($30 shareware - no idea how many people actually registered, unfortunately)... which surprised me (very much!).
... and that's just from Handango.
Hrrrrm... maybe I should try and do more to my games after all!
Cheers,
Refractor.
|
Posted: Wed Feb 20, 2002 2:22 pm | Post subject: top one> |
|
wrecked
Guest
|
Great info..top read..ROAM that is...MY DAY STARTED BAD AND HAS ONLY GOT BETTER..cheers for all the help
|
Posted: Thu May 08, 2003 5:25 pm | Post subject: > |
|
Dan East
Site Admin

Joined: 25 Jan 2001
Posts: 4969
Location: Virginia, USA

|
Moved and bumped (only took 15 months to get around to it).
Jacco, I checked and you have admin access for the Overloaded forum now.
Simon, I edited two of your posts to fix formatting that was mangled when the board was converted to phpBB.
Dan East
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum You cannot attach files in this forum You can download files in this forum
|
|
|