在C中嵌入汇编
早前公布了C和汇编混编的温度控制器程序,收到一些朋友的询问,他们无法在自己程序中使用我的18B20的汇编子程序或无法正常通过混编后的程序编译。
其实在KEIL中嵌入汇编的方法很简单。如图一,在C文件中要嵌入汇编的地方用#pragma asm和#pragma endasm分隔开来,这样编译时KEIL就知道这中间的一段是汇编了。

在有加入汇编的文件中,还要设置编译该文件时的选项

Generate Assembler SRC File 生成汇编SRC文件
Assemble SRC File 封装汇编文件
(如图三的状态为选中)
选上这两项就可以在C中嵌人汇编了,设置后在文件图示中多了三个红色的小方块。

图3
为了能对汇编进行封装还要在项目中加入相应的封装库文件, 在笔者的项目中编译模式是小模式所以选用C51S.LIB。这也是最常用的。这些库文件是中KEIL安装目录下的LIB目录中。 加好后就可以顺利编译了。(注:我只在7.0以上版本使用过)

C51编译器能对C语言程序进行高效率的编译,生成高效简洁的代码,在大多数的应用场合,采用C语言编程即可完成预期的任务,但是,在有些场合还是会用到汇编,例如在下面的几种情况下,采用汇编可能会有很多好处:
1、已有程序的移植:在单片机领域工作很久的工程人员可能会保留有很多的早期用汇编语言编制的程序模块,并且这些模块已经经过实际应用的验证,如果重新用C编程,可能工作量很大,这时就可以用嵌入汇编的方式把以前的汇编模块植入新的应用,可以明显的加快开发的进度。
2、局部功能需要足够短的执行时间:在有些应用中,部分的功能模块需要有很高的执行效率,而有些汇编的指令在C中没有对应的指令,这给我们对单片机的高效操作带来困难,嵌入汇编可是我们的程序执行更有效率。
3、对一些特定地址进行操作:在C中我们要对特定地址进行读写,一般用以下两种方式:用_AT_指令定义变量;定义指向外部端口或数据地址的指针;在汇编中只需要使用MOVX A,@DPTR或MOVX @DPTR,A就可以了,这样可以增强程序的可读性。
4、其他的需要汇编的应用:在这里我们不可能举出所有可能要用汇编的例子,在你的应用中,你可能在一个或多个应用中感到C语言的不足,而需要用到汇编指令,请你记住,可以在C中嵌入汇编子程序,这对你的程序非常有用。
首先介绍一下调用汇编的参数传递规则,见下表
|
传递的参数 |
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:下面是C语言的主程序
#include <REG52.H>
#include <stdio.h>
extern char asm(char c,char b);
bit VAL;
void main (void)
{
charout=0x49;
chardirect;
charkey;
SCON = 0x50;/* SCON: mode 1, 8-bit UART, enable rcvr */
//10位异步接收器,可变。REN=1,允许接收数据
TMOD |= 0x20;/* TMOD: timer 1, mode 2, 8-bit reload */
//定时器1工作于模式2
TH1 = 0xfd;/* TH1: reload value for 9600 baud @ 11.0592MHz */
TR1 = ;/* TR1: timer 1 run */
TI = ;/* TI: set TI to send first char of UART */
VAL=;
)
{
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);
}
}
下面是汇编的子程序(文件名称asmtest.asm)
NAME ASM ?PR?_asm?ASMTESTSEGMENT CODE ?BI?_asm?ASMTESTSEGMENT BIT PUBLIC?_asm?BIT PUBLIC_asm RSEG?BI?_asm?ASMTEST ?_asm?BIT: VAL:DBIT1 RSEG?PR?_asm?ASMTEST _asm:MOV A,R7 MOV C,VAL DJNZ R5,JP1 RRC A JP1:DJNZ R5,JP2 RLC A JP2:MOV90h,A MOV R7,A MOVVAL,C RET END
现在对这个例子简短的说明,这个例子是用来驱动一个不带细分的三相步进电机,用的是循环移位的指令来实现的,由于一个字节是8位,如果算上进位位,共9位,通过付值,可以得到这样的数100100100,大家可以看到任意取中间的3位,相邻的每3位与它都一样,这样我们就可以去中间的3位输出到端口去驱动一个三相的步进电机,通过对这个9位的二进制数进行循环移位,可以实现电机的步进,在51系列单片机中有两条指令可以帮助我们进行循环移位操作,这就是RRC A和RLC A指令,我们只要把第九位保存好,在需要移位操作时,把它付给PSW中C,再执行循环移位就可以了。
在这个例子中,我发现了几个需要注意的地方:
1、在C程序中,我不能把VAL变量设为extern类型,否则在连接时会有警告,导致数值不能传递
2、在汇编模块中,不能把SEGMENT BIT段置为OVERLAYABLE即可覆盖段,如果置为可覆盖段,那么在进入汇编模块时VAL变量值丢失
3、如果把VAL变量作为函数的参数传递,出现在返回后在执行printf函数后变量值丢失;
上面是本人写的一个C程序调用汇编的小例子,在本例中的几个printf函数是为了便于在Keil C51中模拟调试时观察运行结果的,在实际应用中可以将这几条去掉,这只是一个简短的示例,目的在于介绍一下C调用汇编的用法,希望对大家有帮助,同时由于本人水平有限,在程序中有些地方可能仍有不周到之处,欢迎广大单片机高手不吝指出。
在C中嵌入汇编的更多相关文章
- linux内核分析作业4:使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
系统调用:库函数封装了系统调用,通过库函数和系统调用打交道 用户态:低级别执行状态,代码的掌控范围会受到限制. 内核态:高执行级别,代码可移植性特权指令,访问任意物理地址 为什么划分级别:如果全部特权 ...
- [汇编] C语言中嵌入汇编
>_<" 下面是在C语言中嵌入汇编的例子,下面是三点要注意的~ 1.内联式汇编 2._asm关键字 3.并不是所有中断都能被支持 #include<iostream> ...
- 实验--使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用(杨光)
使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 攥写人:杨光 学号:20135233 ( *原创作品转载请注明出处*) ( 学习课程:<Linux内核分析>MOOC课程 ...
- 在c语言中嵌入汇编语句,对于我来说相当难。
今天早上在csdn论坛上看到一个帖子http://topic.csdn.net/u/20120917/14/82f42e17-977a-4824-95bd-7b79db15d283.html:“C语言 ...
- LInux内核分析--使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
实验者:江军 ID:fuchen1994 实验描述: 选择一个系统调用(13号系统调用time除外),系统调用列表参见http://codelab.shiyanlou.com/xref/linux-3 ...
- 实验四——使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
实验目的: 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 实验过程: 查看系统调用列表 get pid 函数 #include <stdio.h> #include & ...
- Linux内核设计第四周学习总结 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
陈巧然原创作品 转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 实验目的: 使用库函数A ...
- 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用
本周作业的主要内容就是采用gcc嵌入汇编的方式调用system call. 系统调用其实就是操作系统提供的服务.我们平时编写的程序,如果仅仅是数值计算,那么所有的过程都是在用户态完成的,但是我们想将变 ...
- 通过库函数API和C代码中嵌入汇编代码剖析系统调用的工作机制
作者:吴乐 山东师范大学<Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 本次实验的主要内容就是分别采用A ...
随机推荐
- win10系统加载ahci驱动的操作方案(Win10之家)
win10系统使用的过程中很多用户会想要加载ahci驱动,但是大部分用户根本不知道怎么操作加载ahci驱动,这样的话很多用户会遇到一些问题,那如果使用的过程中想要加载ahci驱动的话我们应该怎么操作呢 ...
- 64位调试器花费的时间比预期的要长(A 64-bit debugging operation is taking longer than expected)
在stackoverflow上找到解决方案的: http://stackoverflow.com/questions/21329899/vs2013-professional-local-64-bit ...
- centos Minicom通信终端
minicom是linux下的串口通信软件,他使用完全使用键盘操作.它虽然没有windows下的超级终端好用,但是它也是一种串口通信的方法.一.minicom安装在超级终端中输入:sally@sall ...
- Android 之窗口小部件详解(三) 部分转载
原文地址:http://blog.csdn.net/iefreer/article/details/4626274. (一) 应用程序窗口小部件App Widgets 应用程序窗口小部件(Widget ...
- linux考试基础知识测验
Linux系统管理基础测试(100分钟) 姓名: 座位号: 一.单项选择题:(每小题0.5分,共计30分) 1. cron 后台常驻程序 (daemon) 用于:D A. 负责文件在网络中的共 ...
- WPF与输入法冲突研究之二:汉字输入法会导致WPF程序的崩溃!
如果是输入非汉字的数据信息,可以添加一下内容: xmlns:input="clr-namespace:System.Windows.Input;assembly=PresentationCo ...
- python高级编程:有用的设计模式2
# -*- coding: utf-8 -*- __author__ = 'Administrator' #python高级编程:有用的设计模式 #代理 """ 代理对一 ...
- OCP-1Z0-051-题目解析-第28题
28. Which two statements are true regarding constraints? (Choose two.) A. A foreign key cannot cont ...
- 【剑指offer】二叉树深度
转载请注明出处:http://blog.csdn.net/ns_code/article/details/27249675 题目描写叙述: 输入一棵二叉树,求该树的深度.从根结点到叶结点依次经过的结点 ...
- Mysql配置调优(转自阿铭论坛)
Mysql配置文件my.cnf参数优化对于新手来讲,是比较难懂的东西,其实这个参数优化,是个很复杂的东西,对于不同的网站,及其在线量,访问量,帖子数量,网络情况,以及机器硬件配置都有关系,优化不可能一 ...