|
发表于 2008-1-17 12:24:09
|
显示全部楼层
1楼说是对,这个要根据你所使用的C编译器来决定的.具体的方法在它们的HELP中有说明.
下面时ICC中的说明部分:
Assembly Interface and Calling Conventions
External Names
External C names are prefixed with an underscore, e.g. the function main is _main if referenced in an assembly module. Names are significant to 32 characters. To make an assembly object global, use two colons after the name. For example,
_foo::
.word 1
(In the C file)
extern int foo;
Argument and Return Registers
The first argument is passed in registers R16/R17 if it is an integer and R16/R17/R18/R19 if it is a long or floating point. The second argument is passed in R18/R19 if available. All other remaining arguments are passed on the software stack.
Integer arguments smaller than ints (i.e. char) are not extended to in IF the function prototype is available. If registers are used to pass byte arguments, it will use both registers but the higher register is undefined. For example, if the first argument is a byte, both R16/R17 will be used with R17 being undefined. Byte arguments passed on the software stack take up only a single byte. In the future release, byte arguments passed in registers will be packed tightly.
If R16/R17 is used to pass the first argument and the second argument is a long or float, the lower half of the second argument is passed in R18/R19 and the upper half is passed on the software stack.
Integer values are returned in R16/R17 and longs and floats are returned in R16/R17/R18/R19. Byte values are returned in R16 with R17 undefined.
Preserved Registers
An assembly function must save and restore the following registers:
R28/R29 or Y, this is the frame pointer.
R10/R11/R12/R13/R14/R15/R20/R21/R22/R23
These registers are called preserved registers since their contents are unchanged by a function call. You can ask the compiler not to use the registers R20, R21, R22, and R23, then you do not need to save and restore these 4 registers.
Volatile Registers
The other registers:
R0/R1/R2/R3/R4/R5/R6/R7/R8/R9/R24/R25/R26/R27/R30/R31
SREG
can be used in a function without being saved or restored. These registers are called volatile registers since their contents may be changed by a function call.
具体的例子,可参考我编写的<M128>一书第五章中的BOOTLOAD的例程,里面有LZ想要的方式.
=================================================================================
下面是CVAVR的用法:
Calling Assembly Functions from C
The following example shows how to access functions written in assembly language from a C program:
// function in assembler declaration
// this function will return a+b+c
#pragma warn- // this will prevent warnings
int sum_abc(int a, int b, unsigned char c) {
#asm
ldd r30,y+3 ;R30=LSB a
ldd r31,y+4 ;R31=MSB a
ldd r26,y+1 ;R26=LSB b
ldd r27,y+2 ;R27=MSB b
add r30,r26 ;(R31,R30)=a+b
adc r31,r27
ld r26,y ;R26=c
clr r27 ;promote unsigned char c to int
add r30,r26 ;(R31,R30)=(R31,R30)+c
adc r31,r27
#endasm
}
#pragma warn+ // enable warnings
void main(void) {
int r;
// now we call the function and store the result in r
r=sum_abc(2,4,6);
}
The compiler passes function parameters using the Data Stack.
First it pushes the integer parameter a, then b, and finally the unsigned char parameter c.
On every push the Y register pair decrements by the size of the parameter (4 for long int, 2 for int, 1 for char).
For multiple byte parameters the MSB is pushed first.
As it is seen the Data Stack grows downward.
After all the functions parameters were pushed on the Data Stack, the Y register points to the last parameter c, so the function can read its value in R26 using the instruction: ld r26,y.
The b parameter was pushed before c, so it is at a higher address in the Data Stack.
The function will read it using: ldd r27,y+2 (MSB) and ldd r26,y+1 (LSB).
The MSB was pushed first, so it is at a higher address.
The a parameter was pushed before b, so it is at a higher address in the Data Stack.
The function will read it using: ldd r31,y+4 (MSB) and ldd r30,y+3 (LSB).
The functions return their values in the registers (from LSB to MSB):
R30 for char and unsigned char
R30, R31 for int and unsigned int
R30, R31, R22, R23 for long and unsigned long.
So our function must return its result in the R30, R31 registers.
After the return from the function the compiler automatically generates code to reclaim the Data Stack space used by the function parameters.
The #pragma warn- compiler directive will prevent the compiler from generating a warning that the function does not return a value.
This is needed because the compiler does not know what it is done in the assembler portion of the function. |
|