cpubbs论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

LabVIEW+单片机学习套件全套教程资料下载[免费]LabVIEW论坛精华列表贴USB0816数据采集卡《LabVIEW宝典》
LabWindows/CVI论坛精华贴NET0816以太网数据采集卡RC0210远程设备授权系统 关闭关停锁定打开设备 户外分布式数据采集
NET1624低速高精度以太网数据采集卡WIFI0824SD无线WIFI网络数据采集卡脱机运行 SD存储 小尺寸微型 串口采集远程采集 安卓 手持移动采集 纪录仪
查看: 1929|回复: 0

[转帖]程序中嵌入汇编的实例

[复制链接]
发表于 2005-8-4 20:18:53 | 显示全部楼层 |阅读模式




<>C51编译器能对C语言程序进行高效率的编译,生成高效简洁的代码,在大多数的应用场合,采用C语言编程即可完成预期的任务,但是,在有些场合还是会用到汇编,例如在下面的几种情况下,采用汇编可能会有很多好处:</P>
<>1、已有程序的移植:在单片机领域工作很久的工程人员可能会保留有很多的早期用汇编语言编制的程序模块,并且这些模块已经经过实际应用的验证,如果重新用C编程,可能工作量很大,这时就可以用嵌入汇编的方式把以前的汇编模块植入新的应用,可以明显的加快开发的进度。</P>
<>2、局部功能需要足够短的执行时间:在有些应用中,部分的功能模块需要有很高的执行效率,而有些汇编的指令在C中没有对应的指令,这给我们对单片机的高效操作带来困难,嵌入汇编可是我们的程序执行更有效率。</P>
<P>3、对一些特定地址进行操作:在C中我们要对特定地址进行读写,一般用以下两种方式:用_AT_指令定义变量;定义指向外部端口或数据地址的指针;在汇编中只需要使用MOVX A,@DPTR或MOVX @DPTR,A就可以了,这样可以增强程序的可读性。</P>
<P>4、其他的需要汇编的应用:在这里我们不可能举出所有可能要用汇编的例子,在你的应用中,你可能在一个或多个应用中感到C语言的不足,而需要用到汇编指令,请你记住,可以在C中嵌入汇编子程序,这对你的程序非常有用。</P>
<P>首先介绍一下调用汇编的参数传递规则,见下表</P>
传递的参数 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


<P>在下面的例子中我们首先给出一个C程序调用汇编的例子,先说明一下,在这个例子中,你完全可以用C完成,我用这个例子,只是为了说明嵌入汇编的方法。</P>
<P>例1:</P>
<P>下面是C语言的主程序</P>
<P>#include &lt;REG52.H&gt;
#include &lt;stdio.h&gt;
extern char asm(char c,char b);
bit VAL;
void main (void)
{
  char out=0x49;
  char direct;
  char key;
  SCON = 0x50; /* SCON: mode 1, 8-bit UART, enable rcvr */
  TMOD |= 0x20; /* TMOD: timer 1, mode 2, 8-bit reload */
  TH1 = 0xfd; /* TH1: reload value for 9600 baud @ 11.0592MHz */
  TR1 = 1; /* TR1: timer 1 run */
  TI = 1; /* TI: set TI to send first char of UART */
  VAL=0;
  while (1)
  {
    key=getchar();
    if(key=='R')
    {
      direct=0X01;
      out=asm(out,direct); /*汇编子程序调用*/
      printf ("Right rotate\n");
    }
    if(key=='L')
    {
      direct=0X02;
      out=asm(out,direct); /*汇编子程序调用*/
      printf ("Left rotate\n");
    }
    printf("%bx\n",out);
  }
}</P>
<P>下面是汇编的子程序(文件名称asmtest.asm)</P>
<P>NAME ASM
?PR?_asm?ASMTEST SEGMENT CODE
?BI?_asm?ASMTEST SEGMENT BIT
PUBLIC ?_asm?BIT
PUBLIC _asm
RSEG ?BI?_asm?ASMTEST
?_asm?BIT:
VAL: DBIT 1
RSEG ?PR?_asm?ASMTEST
_asm:
MOV A,R7
MOV C,VAL
DJNZ R5,JP1
RRC A
JP1:
DJNZ R5,JP2
RLC A
JP2:
MOV 90h,A
MOV R7,A
MOV VAL,C
RET
END</P>
<P>现在对这个例子简短的说明,这个例子是用来驱动一个不带细分的三相步进电机,用的是循环移位的指令来实现的,由于一个字节是8位,如果算上进位位,共9位,通过付值,可以得到这样的数100100100,大家可以看到任意取中间的3位,相邻的每3位与它都一样,这样我们就可以去中间的3位输出到端口去驱动一个三相的步进电机,通过对这个9位的二进制数进行循环移位,可以实现电机的步进,在51系列单片机中有两条指令可以帮助我们进行循环移位操作,这就是RRC A和RLC A指令,我们只要把第九位保存好,在需要移位操作时,把它付给PSW中C,再执行循环移位就可以了。</P>
<P>在这个例子中,我发现了几个需要注意的地方:</P>
<P>1、在C程序中,我不能把VAL变量设为extern类型,否则在连接时会有警告,导致数值不能传递;</P>
<P>2、在汇编模块中,不能把SEGMENT BIT段置为OVERLAYABLE即可覆盖段,如果置为可覆盖段,那么在进入汇编模块时VAL变量值丢失;</P>
<P>3、如果把VAL变量作为函数的参数传递,出现在返回后在执行printf函数后变量值丢失;</P>
<P>上面是本人写的一个C程序调用汇编的小例子,在本例中的几个printf函数是为了便于在Keil C51中模拟调试时观察运行结果的,在实际应用中可以将这几条去掉,这只是一个简短的示例,目的在于介绍一下C调用汇编的用法,希望对大家有帮助,同时由于本人水平有限,在程序中有些地方可能仍有不周到之处,欢迎广大单片机高手不吝指出。</P>
<P>[转自http://www.51c51.com]</P>
[此贴子已经被作者于2005-8-4 12:23:58编辑过]

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|cpubbs论坛. ( 粤ICP备09171248号 )

GMT+8, 2025-5-4 23:48 , Processed in 0.742916 second(s), 7 queries , Gzip On, File On.

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表