"); //-->
C51编译器能对C语言程序进行高效率的编译,生成高效简洁的代码,在大多数的应用场合,采用C语言编程即可完成预期的任务,但是,在有些场合还是会用到汇编,例如在下面的几种情况下,采用汇编可能会有很多好处:电子园51单片机学习网|;eWu]E
1、已有程序的移植:在单片机领域工作很久的工程人员可能会保留有很多的早期用汇编语言编制的程序模块,并且这些模块已经经过实际应用的验证,如果重新用C编程,可能工作量很大,这时就可以用嵌入汇编的方式把以前的汇编模块植入新的应用,可以明显的加快开发的进度。
^5WhX)Ouq3g446062、局部功能需要足够短的执行时间:在有些应用中,部分的功能模块需要有很高的执行效率,而有些汇编的指令在C中没有对应的指令,这给我们对单片机的高效操作带来困难,嵌入汇编可是我们的程序执行更有效率。
&K0u.g.{S(Q446063、对一些特定地址进行操作:在C中我们要对特定地址进行读写,一般用以下两种方式:用_AT_指令定义变量;定义指向外部端口或数据地址的指针;在汇编中只需要使用MOVX A,@DPTR或MOVX @DPTR,A就可以了,这样可以增强程序的可读性。
?&B{&oY]D)x6x'x&x446064、其他的需要汇编的应用:在这里我们不可能举出所有可能要用汇编的例子,在你的应用中,你可能在一个或多个应用中感到C语言的不足,而需要用到汇编指令,请你记住,可以在C中嵌入汇编子程序,这对你的程序非常有用。
9h3{;`oVO$F$QUN6{)s44606首先介绍一下调用汇编的参数传递规则,见下表
3KSpXPdi2Io+h Vu44606传递的参数 | char、1字节指针 | int、2字节指针 | long、float | 一般指针 |
第一个参数 | R7 | R6,R7 | R4~R7 | R1,R2,R3 |
第二个参数 | R5 | R4,R5 | R1,R2,R3 | |
第三个参数 | R3 | R2,R3 | 无 | R1,R2,R3 |
在下面的例子中我们首先给出一个C程序调用汇编的例子,先说明一下,在这个例子中,你完全可以用C完成,我用这个例子,只是为了说明嵌入汇编的方法。电子园51单片机学习网q\b7h3V
例1:电子园51单片机学习网juO2z C\
下面是C语言的主程序
.Ly%b{.t4s/Pd0j44606#include <REG52.H>
!A l;L&W| s9]44606#include <stdio.h>电子园51单片机学习网8Bp*`+M8s*M$N/Y
extern char asm(char c,char b);
8p[z(l6_-z44606bit VAL;
%}&y7|3~uH3?u5D}44606void main (void)
N"X_P4m-{-}-UN44606{
S hv qLIOr44606 charout=0x49;电子园51单片机学习网u @&`-wQ C Ta;M
chardirect;电子园51单片机学习网9O2u!IK4oeu
charkey;电子园51单片机学习网%XMNbA A5_:vv@
SCON = 0x50;/* SCON: mode 1, 8-bit UART, enable rcvr */电子园51单片机学习网0I R:~c?3]4Uj @K
TMOD |= 0x20;/* TMOD: timer 1, mode 2, 8-bit reload */电子园51单片机学习网RE!a;U^3L5K\
TH1 = 0xfd;/* TH1: reload value for 9600 baud @ 11.0592MHz */电子园51单片机学习网F%c T O M3Q N
TR1 = 1;/* TR1: timer 1 run */
S KTH*GU44606 TI = 1;/* TI: set TI to send first char of UART */
SCByX#t,vR:Z44606 VAL=0;电子园51单片机学习网-a^&Kn.n3H
while (1)
.v]B ~ LJf44606 {
0p,E#jM+} m@#T44606 key=getchar();电子园51单片机学习网 [3UWf!R
if(key=='R')电子园51单片机学习网)BlX/G/n'qt@*l
{电子园51单片机学习网t @8^u9Grn*u
direct=0X01;电子园51单片机学习网I~|H'Q
out=asm(out,direct);/*汇编子程序调用*/电子园51单片机学习网Q*E}@jJcHy
printf ("Right rotate\n");电子园51单片机学习网7d)SW@KA Cc
}
Ti%qv-G#k(L44606 if(key=='L')电子园51单片机学习网y }{a9Z+W5mV
{
sswU.p44606 direct=0X02;
u;hZ*C&U44606 out=asm(out,direct);/*汇编子程序调用*/
AFo9St F.D44606 printf ("Left rotate\n");电子园51单片机学习网4r4Z:@(X-p*j sQ
}
5B.n"se q;R [44606 printf("%bx\n",out);
s'p5~&Yu"[k5K44606 }电子园51单片机学习网z+IR!R)t
}
下面是汇编的子程序(文件名称asmtest.asm)
'tF]6{0s)D44606电子园51单片机学习网.V,_%M.`3oVM;_vKNAMEASM电子园51单片机学习网JRTh%j
?PR?_asm?ASMTESTSEGMENT CODE电子园51单片机学习网 Z#Doi|$Jt
?BI?_asm?ASMTESTSEGMENT BIT
Ll N3r Y;Z44606PUBLIC?_asm?BIT电子园51单片机学习网,GY9Q-OWZ+n
PUBLIC_asm电子园51单片机学习网)X}V|SY~7z&_`
RSEG?BI?_asm?ASMTEST电子园51单片机学习网)e/q5\6v{H iB1X&m
?_asm?BIT:电子园51单片机学习网5E@d'@)^'{!V{
VAL:DBIT1电子园51单片机学习网 [ K@B ^]RFV
RSEG?PR?_asm?ASMTEST
4a)zJ.LN&l"Y'm44606_asm:电子园51单片机学习网[fO/ri]|N \
MOV A,R7
)\I&bxDOP44606MOV C,VAL
m[Y+~!|L3U,j$k44606DJNZ R5,JP1
_ [Y-t Wr.m44606RRC A
AN#i-R6T M44606JP1:
V r"]7x7L$hJb.K/f44606DJNZ R5,JP2电子园51单片机学习网LL9Sv[*j
RLC A电子园51单片机学习网-mU WvQae
JP2:
'LU,j"S5V2S2t44606MOV90h,A
]0p2DE l.W44606MOV R7,A
$ubwk2{9{44606MOVVAL,C
^s&hMy$D7jH1W44606RET
mlBlW44606END
现在对这个例子简短的说明,这个例子是用来驱动一个不带细分的三相步进电机,用的是循环移位的指令来实现的,由于一个字节是8位,如果算上进位位,共9位,通过付值,可以得到这样的数100100100,大家可以看到任意取中间的3位,相邻的每3位与它都一样,这样我们就可以去中间的3位输出到端口去驱动一个三相的步进电机,通过对这个9位的二进制数进行循环移位,可以实现电机的步进,在51系列单片机中有两条指令可以帮助我们进行循环移位操作,这就是RRC A和RLC A指令,我们只要把第九位保存好,在需要移位操作时,把它付给PSW中C,再执行循环移位就可以了。
al9`4D9wu.O44606在这个例子中,我发现了几个需要注意的地方:
6Mx-UG&y||8m446061、在C程序中,我不能把VAL变量设为extern类型,否则在连接时会有警告,导致数值不能传递;电子园51单片机学习网} _t)a|
2、在汇编模块中,不能把SEGMENT BIT段置为OVERLAYABLE即可覆盖段,如果置为可覆盖段,那么在进入汇编模块时VAL变量值丢失;电子园51单片机学习网3DE z%Au,W
3、如果把VAL变量作为函数的参数传递,出现在返回后在执行printf函数后变量值丢失;
x"zOP'QmCl1U44606上面是本人写的一个C程序调用汇编的小例子,在本例中的几个printf函数是为了便于在Keil C51中模拟调试时观察运行结果的,在实际应用中可以将这几条去掉,这只是一个简短的示例,目的在于介绍一下C调用汇编的用法,希望对大家有帮助,同时由于本人水平有限,在程序中有些地方可能仍有不周到之处,欢迎广大单片机高手不吝指出。
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。