单片机C与汇编溷合编程-PPT精品
汇编语言与C的混合编程PPT教学课件
的子程序破坏,即这些寄存器是供所调用的子程 序作为工作寄存器的。
2020/12/10
9
2内嵌的汇编器和armasm的区别
• 与armasm相比,内嵌的汇编器在功能和使用方法上主要 有以下特点:
开成几条指令。例如指令: • ADD R0,R0,#1023 • 可能会被展开成下面的指令序列 • ADD R0,R0,#1024 • SUB R0,R0,#01 • 乘法指令MUL可能会被展开成一系列的加法操作和移位操作。 • 事实上,除了与协处理器相关的指令外,大部分的ARM指令和
Thumb指令中包含常量操作数都可能被展开成多条指令。
器的值,用户不需要去保护和恢复这些寄存器的值。
• 用户可以改变处理器模式,但是编译器并不了解处理器模式的改变。 这样,如果用户改变了处理器模式,将不能使用原来的C表达式;重 新恢复到原来的处理器模式后,才能再使用这些C表达式。
2020/12/10
11
3在C程序中使用内嵌的汇编指令
• 3.1在C程序中使用内嵌的汇编指令的语法格式 • 在ARM C语言程序中使用关键词_asm来标识一段汇编指令程序,其格式如下: • _asm •{ • Instruction[;instruction] • …… • [instruction] •} • 其中,如果一行中有很多个汇编指令,则指令之间使用分号“;”隔开。如
• 通常推荐在内嵌的汇编指令中不要指定物理寄存器,因为这可能会影 响编译器分配寄存器,进而可能影响代码的效率。
2020/12/10
4
1.3常量
单片机C语言与汇编语言的混合编程
单片机C语言与汇编语言的混合编程(选自《单片机C语言编程应注意的若干问题》)在绝大多数场合采用C语言编程即可完成预期的目的,但是对实时时钟系统、要求执行效率高的的系统就不适合采用C语言编程,对这些特殊情况进行编程时要结合汇编语言。
汇编语言具有直接和硬件打道、执行代码的效率高等特点,可以做到C语言所不能做到的一些事情,例如对时钟要求很严格时,使用汇编语言成了唯一的选择。
这种混合编程[2]的方法将C语言和汇编语言的优点结合起来,已经成为目前单片机开发最流行的编程方法。
目前大多数据单片机系统,在C语言中使用汇编语言有两种情况:一种是汇编程序部分和C程序部分为不同的模块,或不同的文件,通常由C程序调用汇编程序模块的变量和函数(也可称为子程序或过程);另一种是嵌入式汇编,即在C语言程序中嵌入一段汇编语言程序。
当汇编程序和C程序为不同模块时程序一般可分为若于个C程序模块和汇编程序模块,C程序模块通常是程序的主体框架,而汇编程序模块通常由用C语言实现效率不高的函数组成,也可以是已经成熟的、没有必要再转化成C语言的汇编子程序。
在这种混合编程技术中,关键是参数的传递和函数的返回值。
它们必须有完整的约定,否则数据的交换就可能出错。
对于嵌入式汇编,可以在C程序中使用一些关键字嵌入下些汇编程序,这种方法主要用于实现数学运算或中断处理,以便生成精练的代码,减少运行时间。
当汇编函数不大,且内部没有复杂的跳转时,可以用嵌入式汇编实现。
下面就以AT89C2051单片机在模拟电压检测中的应用为例说明C语言程序与汇编语言程序的调用。
电路图如图1所示:AT89C2051单片机内置模拟比较器,13脚即P1.1是比较器的负输入端,12脚即P1.0是比较器的正输入端,比较器的输出端做在了CPU内部即P3.6未被引出,CPU可以直接读取P3.6状态来判定两输入端比较的结果其和一个外部电阻及一个外部电容器就可以设计成一个A/D转换器,采用RC模拟转换的原理,来检测外部P1.1引脚的输入电压。
单片机C语言编程与汇编混合编程
单片机C语言编程与汇编混合编程时出现的问题悬赏分:30 - 解决时间:2008-12-29 11:07#include<reg51.h>#pragma srcvoid Delay(){#pragma asmMOV R2,#20D1:MOV R3,#100D2:MOV R4,#229DJNZ R4,$DJNZ R3,D2DJNZ R2,D1#pragma endasm}void main(){unsigned char c,i;while(1){c=0xfe;for(i=0;i>7;i++){P0=c;Delay();c<<=1;}}}TEST1.C(3): error C252: misplaced primary control, line ignoredTEST1.C(6): error C272: 'asm/endasm' requires src-control to be activeTEST1.C(15): error C272: 'asm/endasm' requires src-control to be active用KEIL 编译后出现上面几个错误.我将#pragma src 放在main() 前也不行,有各位高手指点提问者:lzh2113 - 二级最佳答案#include<reg51.h>main(){#pragma asmMOV R2,#20D1:MOV R3,#100D2:MOV R4,#229DJNZ R4,$DJNZ R3,D2DJNZ R2,D1#pragma endasm}void main(){unsigned char c,i;while(1){c=0xfe;for(i=0;i>7;i++){P0=c;Delay();c<<=1;}}TEST1.C(3): error C252: misplaced primary control, line ignoredTEST1.C(6): error C272: 'asm/endasm' requires src-control to be activeTEST1.C(15): error C272: 'asm/endasm' requires src-control to be active#1 楼主:keil C 语言与汇编语言混合编程贴子发表于:2009/2/19 16:41:04文章来看proteus 仿真网 /bbs keil C 语言与汇编语言混合编程1. C 语言中嵌入汇编1、在C 文件中要嵌入汇编代码片以如下方式加入汇编代码:#pragma ASM; Assembler Code Here#pragma ENDASM2、在Project 窗口中包含汇编代码的C 文件上右键,选择“Options for ...”,点击右边的“Generate Assemb ler SRC File”和“Assemble SRC File”,使检查框由灰色变成黑色(有效)状态;3、根据选择的编译模式,把相应的库文件(如Small 模式时,是Keil\C51\Lib\C51S.Lib)加入工程中, 该文件必须作为工程的最后文件;4、编译,即可生成目标代码。
汇编语言和C语言的混合编程(精选)PPT文档共21页
6、最大的骄傲于最大的自卑都表示心灵的最软弱无力。——斯宾诺莎 7、自知之明是最难得的知识。——西班牙 8、勇气通往天堂,怯懦通往地狱。——塞内加 9、有时候读书是一种巧妙地避开思考的方法。——赫尔普斯 10、阅读一切好书如同和过去最杰出的人谈(精选)
16、人民应该为法律而战斗,就像为 了城墙 而战斗 一样。 ——赫 拉克利 特 17、人类对于不公正的行为加以指责 ,并非 因为他 们愿意 做出这 种行为 ,而是 惟恐自 己会成 为这种 行为的 牺牲者 。—— 柏拉图 18、制定法律法令,就是为了不让强 者做什 么事都 横行霸 道。— —奥维 德 19、法律是社会的习惯和思想的结晶 。—— 托·伍·威尔逊 20、人们嘴上挂着的法律,其真实含 义是财 富。— —爱献 生
单片机C与汇编混用
2.在C51中嵌入汇编程序通过C51中的预处理指令#pragma asm/endasm语句来实现的。
其格式如下:#pragma ASM;汇编程序代码#pragma ENDASM3. 在C51中调用汇编程序这种方法应用较多,C模块与汇编模块的接口较简单,分别用C51与A51对源程序进行编译,然后用L51将obj文件连接即可,关键问题在于C函数与汇编函数之间的参数传递和得到正确的返回值,以保证模块间的数据交换。
5.2 混合汇编的参数传递与实现5.2.1 混合汇编的参数传递1.汇编程序调用C51函数的参数传递如C51函数有参数,则汇编程序在调用C51函数前要准备好参数。
在汇编程序中,C51函数最左边的一个参数由寄存器A传递,其他的参数按顺序通过堆栈给出。
C51函数的返回值是返回到A寄存器或者由A寄存器给出的地址。
2.在C51中嵌入汇编程序的参数传递通过变量或特殊功能寄存器来实现难点))中调用汇编程序的参数传递((难点3.在C51中调用汇编程序的参数传递C51中调用汇编程序进行参数传递时都必须严格遵守C51函数的参数和返回值的相关约定。
C51中调用汇编程序进行参数传递的方式有两种,一种是通过寄存器传递参数,第二种是通过固定存储区传递。
5.2.2 混合汇编的实现1.C51中嵌入汇编程序的实现方法第一步:在C文件中以如下方式嵌入汇编程序。
#include <reg51.h>void main(void){P2=1;#pragma asmMOV R7,#10DEL:MOV R6,#20DJNZ R6,$DJNZ R7,DEL#pragma endasmP2=0;}第二步:在Keil C51软件的Project 窗口右击嵌入汇编程序的C文件,在弹出的快捷菜单中选择Options for ...命令,选中右边的Generate Assembler SRC File和Assemble SRC File复选框,使检查框由灰色变成黑色(有效)状态。
单片机 c与汇编混合编程共42页
31、只有永远躺在泥坑里的人,才不会再掉进坑里。——黑格尔 32、希望的灯一旦熄灭,生活刹那间变成了一片黑暗。——普列姆昌德 33、希望是人生的乳母。——科策布 34、形成天才的决定因素应该是勤奋。——郭沫若 35、学到很多东西的诀窍,就是一下子不要学很多。——洛克
单片机 c与汇编混合编程
36、如果我们国家的法律中只有某种 神灵, 而不是 殚精竭 虑将神 灵揉进 宪法, 总体上 来说, 法律就 会更好 。—— 马克·吐 温 37、纲纪废弃之日,便是暴政兴起之 时。— —威·皮 物特
38、若是没有公众舆论的支持,法律 是丝毫 没有力 量的。 ——菲 力普斯 39、一个判例造出另一个判例,它们 迅速累 聚,进 而变成 法律。 ——朱 尼厄斯
第5章 单片机C语言与汇编语言混合编程
第5章 单片机C语言与汇编语言混合编程 5.2.2 混合汇编的实现 1.C51中嵌入汇编程序的实现方法 第一步:在C文件中以如下方式嵌入汇编程序。 #include <reg51.h> void main(void) { P2=1; #pragma asm MOV R7,#10 DEL:MOV R6,#20 DJNZ R6,$ DJNZ R7,DEL #pragma endasm P2=0; } 第二步:在Keil C51软件的Project 窗口右击嵌入汇编程序的C文件, 在弹出的快捷菜单中选择Options for ...命令,选中右边的Generate Assembler SRC File和Assemble SRC File复选框,使检查框由灰色 变成黑色(有效)状态。
第5章 单片机C语言与汇编语言混合编程 作业 1 通过寄存器传递参数时,函数 int function(char a,int b,char * c) 中的三个参数a、b、c及返回值,分别放在哪个寄存器中(如果 一个参数需要多个寄存器来传递参数,是如何安排的)? 2 指出下述代码执行后,片外存储器2001H单元中的内容 指出下述代码执行后,片外存储器 单元中的内容
第5章 单片机C语言与汇编语言混合编程 第三步:根据选择的编译模式,把相应的库文件(如 Small 模式时, 是 Keil\C51\Lib\C51S.Lib)加入到工程中,该文件必须作为工程的最 后文件。 第四步:编译,即可生成目标代码。 2.C51中调用汇编程序的实现方法 第一步:先用C语言程序编写出程序框架,如文件名为a1.c(注意 参数)。 第二步:在Keil C51的Project窗口中右击该C语言文件,在弹出的 快捷菜单中选择Options for ...,右边的Generate Assembler SRCFile和Assemble SRC File,使检查框由灰色变成黑色(有效)状 态; 第三步:根据选择的编译模式,把相应的库文件(如Small模式时, 是Keil\C51\Lib\ C51S.Lib)加入工程中,该文件必须作为工程的最 后文件。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
定义类型(根据其所占的内存大小) char TA0MR,TA0IC,TABSR; unsigned int TA0;
特殊寄存器的操作
• 方法2:嵌入汇编语句asm() 尤其是一些系统寄存器R0, FLG
• 方法3:定义成汇编子函数 另写一个as30文件,将相关的操作封装成函数, 供C程序调用
• 方法4:直接定义指针,并对该指针赋初值
• 使用位域
BIT操作
BIT操作
• 使用宏
#define SET_BIT(n,byteA) { byteA |= (0x01<<n); } /* Set Bit =1 */ #define CLR_BIT(n,byteA) { byteA &= (~(0x01<<n)); } /* Set Bit =0 */ #define TST_BIT(n,byteA) (byteA&(0x01<<n))==0 /* Bit = 0 ? */
CODE
program interrupt program_S
根据芯片修改sect30.inc
1. 注释掉不存在的段
2. 最重要的三个段的位置设定
.section
data_SE,DATA
.org
400H
.section .org
rom_FE,ROMDATA 0C0000H
.section
vector,ROMDATA
《单片机与嵌入式系统》
C和ASM的混合编程
jianghq
2019-5 Tsinghua DEE
Content
• 程序的结构
– 汇编程序 – C程序 – project框架
• 如何改写汇编程序? • 在C程序中如何做一些底层操作?
程序的结构
存储空间结构
汇编程序结构 C程序结构
M30624FGFP Memory Map
系统提供的库程序: #include “stdlib.h”
ASM子程序: init4(); sub5()
一个project的层次图
程序结构小结
• 明白各个Section的含义
• 根据芯片参数和自己的程序需要来修改startup程 序
• 用层次化来保持整个组织结构的清晰
如何改写汇编程序?
目标: 将他人提供的汇编程序转为可供自
关于堆栈
两种堆栈:堆栈指针ISP和USP 使用何种堆栈,由堆栈指针选择标志位(U标志)选取。
U = 0 选取中断堆栈指针ISP U = 1 选取用户堆栈指针USP 响应中断后,该标志清0,执行中断子程序
SP指针位置如何设定: 栈顶指针
Push : SP = SP – 1 Pop : SP = SP + 1
汇编语言部分: .glb _IR_RECV
_IR_RECV: mov.b R0L,N_CSTM mov.w A0, SAVE_ADDR …… …… mov.b #1, R0L
; 全局调用声明 ; 参数传递:用户码 ; 参数传递:接收结果地址
; 返回1,如果收到了数据
改写汇编程序小结
• 看懂源程序 • 在明白自己所需要的功能后,再进行修改 有的时候还是需要改多一些地方。 该例子存放到ftp://166.111.172.7
C和汇编子程序之间的参数传递
• 参数规则(从C到汇编) • 参数规则(从汇编返回到C) • 函数名定义规则
参数规则(从C到汇编)
采用#pragma PARAMETER
参数规则(从汇编到C)
函数名定义规则
最后结果
C程序部分: extern char IR_RECV(char,char*); #pragma PARAMETER IR_RECV(R0L,A0)
memory,DATA ; 数据段 VramTOP
prog,CODE VprogTOP
; 代码段
val_vect,ROMDATA ;用户自定义中断向量段 Vintbase
inter,ROMDATA ;固定中断向量段 Vvector+(8*4)
汇编程序中几个主要的参数
VramTOP VramEND VIstack VprogTOP Vintbase Vvector SB_base
在C程序中如何做一些底层操作 • 特殊寄存器的操作 • BIT操作
特殊寄存器的操作
• 方法1: 使用#pragma ADDRESS
#pragma ADDRESS TA0
0386H
#pragma ADDRESS TABSR
0380H
……
建议将所有SFR地址声明放在一个文件里
#include “mcu16c62.h”
程序编完了…
程序编完了,还要考虑哪些问题?
A. 是否用了动态分配内存的函数 -> HEAPSIZE malloc, allot,..... 如果用了,则Heapsize够不够。 没用,。。。注释掉,节约资源。
B. 堆栈的大小够否? -> STACKSIZE, ISTACKSIZE 可直接用Stack Calulate (TM工具栏上)查看
这两个参数的设定都在ncrt0.a30中
C程序结构
RAM
-> DATA -> data bss stack heap
ROM
-> CODE -> program
ROMDATA -> rom vector fvector
NC编译器对Section的处理
Section的属性
属性:I(是否初值), N/F(扩展区) S(SB寻址区), E/O(偶地址对齐) 举例:bss_SE, bss_NE, data_FE, data_SEI
start:
;---------------------------------------------------------------------
; after reset,this program will start
;---------------------------------------------------------------------
几个主要的参数
• RAM区
ramTOP ramEND
• ROM区
progTOP Vvector
汇编程序结构-段类型
RAM -> DATA ROM -> CODE
ROMDATA
汇编程序结构 - 段定义
.SECTION .ORG
.SECTION .ORG
.SECTION .ORG
.SECTION .ORG
ldc
#istack_top,
isp
;set istack pointer
启动过程
ncrt0.a30
设定单片机工作模式 RAM 清0 变量初值设定 堆初始化 调用全局Init子程序 调用全局Main子程序 exit循环主C程序V源自id Init() {…… }
Void Main() {
}
Project层次框架
C程序中所有的section列表
DATA
data_SE bss_SE data_SO bss_SO data_NE bss_NE data_NO bss_NO stack heap data_FE bss_FE data_FO data_FE
ROMDATA
rom_NE rom_NO rom_FE rom_FO data_SEI data_SOI data_NEI data_NOI data_FEI data_FOI vector fvector
bss_SE, rom_FE, program
– 定义和声明全局子函数
• _IRR_INIT • _IR_RECV • I_timera0 涉及C和汇编子程序之间的参数传递(详见下文)
– 删除不必要的变量和程序 – 如果使用中断,则将中断向量表设置挪至sect30.inc – 最后以.end结束文件
己在C程序中调用的子函数。
例子: 红外接收的子程序
Step1
• 大致看懂原程序
– 完成了一个什么样的功能。 – 主要的几个变量是什么含义。
Step2
• 分析自己的要求
– 如果将该汇编程序独立出来作为一个子函数;
• 那么其功能是什么? • 输入参数:有哪些 • 返回值: 有哪些
– 我希望实现的功能
.EQU 000400H .EQU 002BFFH .EQU 002C00H .EQU 0F0000H .EQU 0FA000H .EQU 0FFFDCH .EQU 000380H
-》 ISP -》 SB
关于SB和FB
.SB SB_base .SBSYM recv_nums 告诉编译器使用该变量的指令寻址方式采用相 对基址寻址方式,可以提高生成代码的效率。
.org
VECTOR_ADR
VECTOR_ADR
.equ
0FA000H
其他的段就交给编译器来处理
例子:一个Section分配的结果
C程序结构 - project
• 可能包括多个asm文件, C文件 • 如何安排project的结构?
程序的入口
• 首先要清楚整个程序的执行过程 • 从哪里开始执行?
• 等待接收一个字节,如果收到立刻返回该字节,没收到且 时间超过300ms,那么也返回,同时指示状态为未接收。
char recv_status = IR_RECV(char userID, char* pByte);
指示接收状态
接收用户码 接收字节地址
Step3
• 对原来的程序进行裁减
– 删去原有的各个段定义 – 重新定义各个Section:
Startup文件
sect30.inc文件