Untitled Document
Assembly code using CodeWarrior.
The main processor in the Clie is a 68000 based processor. This cpu is very
convenient because of its large set of instruction and its large amount of registers.
You can use it in CodeWarrior as long as you respect some rules
Why assemby code?
Since it is the lower level you can get, you control exactly what the CPU does.
So, if your code is optimised, it will be as fast as possible when executed.
Use it for the routines where the CPU spends the more time. Use it as well when
you need to know exactly what the CPU is doing (accessing the MQ directly for
instance).
Syntax:
be clean: defines functions containing assembly code aside. Avoid mixing code
too much.
in CodeWarrior, an assembly routine is defined this way
asm
return myAsmRoutine(){
//your code here
}
where return is the format of the returned data. Usualy void (nothing in return),
UInt32, UInt16...
Don't crash everything:
Your assembly snippet has to coexist with the rest of the compiled application
and the OS. You are no longer on your Commodore 64 and have to show some respect
to the environment.
First, you are in a C coded application, so it is cleaner to create a local
stack for the parameters sent to your routine. Just use the macro
fralloc+
that will link the A6 register to the local stack. At the end, befor exiting
the routine perform a
frfree
to clean up the mess before leaving, the most efficient way is to store all
the registers onto the stack on entering your code, and restore em on exiting.
use at the begining
movem.l d0-d7/a0-a5, -(sp)
and on the end
movem.l (sp)+,d0-d7/a0-a5.
You can reduce the amount of registers saved if you are sure you don't unse
them.
by the way, to exit an assembly routine, use the instruction
rts
result:
your code should be enbeded in a skeleton like this:
asm return myAsmRoutine(){
fralloc+
movem.l d0-d7/a0-a5,-(sp)
//your code here
movem.l (sp)+, d0-d7/a0-a5
frfree
rts
}
Avialable registers:
The 68000 features 8 32bits data registers named d0 to d7 and 8 32bits adress
registers named a0 to a7
You can use any of the data registers you want as soon as you restore them on
exit. Usualy the returned value of the asm function is in d0.
You can use the adress registers a0 to a4 freely. a5 is the global variables
pointer, a6 is the local stack pointer and a7 is the global stack pointer.
To access a variable and interface easily your routine with the software, use
diectly their name, for local as for global variables.
example:
move.l myVariable,d0
will move the 32 bits of the variable "myVariable" and store it in
d0. When assembling your code, the assembler will turn the variable name into
an offset to a5 if global, to a6 if local. It will be kind of
move.l 150(a5),d0
You just need to know that to avoid wrong adressing combinations.
parameters.
The code is written without semicolumns ";" at the end of each line
The assembly code is totaly sequential. That means the code is parsed from
to begining and hops to the next instruction. To make loops, condition and all
the kind of structures, use labels. Labels are kind of hooks in the instruction
list where the programm may jump back (or forward). each label if finished by
a ":"
move.w #99,d0 // iteration counter, as in a for(i=0;i<=99;i++)
movea.l baseAsdress,a0 // initialise the source
movea.l destinationAdress,a1 // initialise the destination
loop: // the label
move.l (a0)+,(a1)+ // copy a long from source to destination
dbf d0,loop // decrement d0 and if still positif, jump back to "loop"
this snippet will copy 100 UInt32 from the adress pointed by baseAdress to
the adress pointed by destinationAdress