如何在CVAVR中嵌入汇编?C和汇编之间的参数调用方法,以及注意点如何?
久没用做作业了,马老师布置的作业就尽量做好, 争取做个好学生。1.在CVAVR中嵌入汇编的一般格式:
#asm
….
….
Assembly language code
….
….
#endasm
2.在CVAVR中嵌入汇编时寄存器的使用注意事项:
尽量使用R4到R20这17个寄存器。其他的15个寄存器CVAVR编译器可能有其他用途,如中断等。
3.明确定义寄存器的地址:
即 .equ 语句
例如:即使已经有
#include <mega162.h>,但sfrb的说明对汇编不起作用。
在汇编中仍然要:
#asm
….
.equ PORTB= $17
.equ PIND= $….
….
out PORTB,r16
….
#endasm
4.汇编中的标签的第一个字符避免使用下划线。
例如,以下要尽量避免使用
_delay:
push r16 非常好!
-----此内容被machao于2005-03-19,01:58:27编辑过 5.汇编调入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
编译器先把a放入数据栈,然后是b, 最后是c。每推入一个参数,Y值递减相应的字节。
例如整数a,b各占两个字节,c占一个字节。
对于多字符的数据,先放入MSB,然后LSB。
6.汇编函数返回参数到C的方法:
将要返回的参数存储到以下寄存器中
R30 存放字符
R30, R31 存放整型
R30, R31, R22, R23存放长整型.
例如:
unsigned long int number;
unsigned long int IncLong(unsigned long int n);
void main(void)
{
number = 1234567;
number = IncLong(number);
while (1);
}
#pragma warnunsigned
long int IncLong(unsigned long int i)
{
#asm
;
; 数据栈如下:
;
; MSB
; 2nd MSB
; 3rd MSB
; LSB <- Y
;
; Y 转向LSB
;
ldd r23,y+3 ; get MSB into r23
ldd r22,y+2 ; next into r22
ldd r31,y+1 ; next into r31
ld r30,y ; least into r30
inc r30 ; increment LSB
brne done_IncLong
inc r31
brne done_IncLong
inc r22
brne done_IncLong
inc r23
done_IncLong:
;
; 因为结果已经存放在适当的寄存器上,R30, R31, R22, R23
; 可以直接返回
;
#endasm
}
#pragma warn+
7.全局变量的调用:
有全局变量如下:
char temp;
unsigned int value;
CVAVR在自生成汇编时,在SRAM中预存空间,并且用同样的变量名字,除了在变量名字前加入一个下划线,
即生成_temp以及 _value的变量名字。
所以可以用以下方法直接调用:
lds r17, _ch
sts _value+1, r17
调用时注意多字节的数据的存放次序是:
先LSB存放在低位,然后MSB存放在高位。
Reference:
1. CodeVisionAvr User Manual;
2. CodeVision C Tutorial; 记号
页:
[1]