Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CodeVision AVR 1.25.7, user manual.pdf
Скачиваний:
227
Добавлен:
12.08.2013
Размер:
1.22 Mб
Скачать

CodeVisionAVR

3.18 Including Assembly Language in Your Program

You can include assembly language anywhere in your program using the #asm and #endasm directives.

Example:

void delay(unsigned char i) { while (i--) {

/* Assembly language code sequence */ #asm

nop nop #endasm

};

}

Inline assembly may also be used.

Example:

#asm("sei") /* enable interrupts */

The registers R0, R1, R22, R23, R24, R25, R26, R27, R30 and R31 can be freely used in assembly routines.

However when using them in an interrupt service routine the programmer must save, respectively restore, them on entry, respectively on exit, of this routine.

© 1998-2007 HP InfoTech S.R.L.

Page 103

CodeVisionAVR

3.18.1 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

;R26=c

ld

r26,y

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.

© 1998-2007 HP InfoTech S.R.L.

Page 104