C语言与汇编语言混合编程_32位嵌入式共6页word资料
- 格式:doc
- 大小:23.00 KB
- 文档页数:6
2.6 嵌入式Linux下C和汇编的混合编程2.6.1 混合编程概述2.6.1.1 C和汇编的混合编程及类型C语言是被称为高级的低级语言,原因是在C语言中,有许多针对硬件的操作,能很好地利用硬件特性。
从一方面来说,C语言也是高级语言,它能很方便地实现各种复杂的编程算法。
在嵌入式系统编程中,C语言是首选的程序设计语言,但在某些特定条件下,C语言无法精确地操作硬件,此时往往采用嵌入或调用汇编程序的方法来解决此类问题。
这就是混合编程。
混合编程从方式上主要包括三类,即:C程序调用汇编程序;汇编程序调用C程序;C程序内嵌汇编。
本文后续将分别介绍这三类编程方法。
2.6.1.2 ATPCS规范简介基于ARM的嵌入式C和汇编的混合编程需要遵循一定的规范,这就是过程调用标准ATPCS 规范。
ATPCS规定了子程序间相互调用的基本规则,调用过程中寄存器的使用规则、数据栈的使用规则及参数的传递规则。
2007年,ARM公司推出了新的过程调用标准AAPCS(ARM Architecture Produce Call Standard),它只是改进了原有的ATPCS的二进制代码的兼容性。
这里简单介绍寄存器的使用规则、数据栈的使用规则、参数的传递规则和子程序结果返回规则,更详细的内容请参考其它参考资料。
1. 寄存器使用规则●子程序间通过寄存器R0~R3传递参数,寄存器R0~R3可记作A1~A4。
被调用的子程序在返回前无须恢复寄存器R0~R3的内容。
●在子程序中,ARM状态下使用寄存器R4~R11来保存局部变量,寄存器R4~R11可记作V1~V8;Thumb状态下只能使用R4~R7来保存局部变量。
●寄存器R12用作子程序间调用时临时保存栈指针,函数返回时使用该寄存器进行出栈,记作IP;在子程序间的链接代码中常有这种使用规则。
●通用寄存器R13用作数据栈指针,记作SP。
●通用寄存器R14用作链接寄存器。
●通用寄存器R15用作程序计数器,记作PC 。
嵌入式实验(汇编和C语言混合编程实验)汇编和C语言混合编程实验7.1实验目的①掌握C程序中内嵌指令的使用方法。
②理解汇编程序调用C程序函数和变量的方法。
7.2 实验环境①硬件:PC机②软件:ADS1.27.3 实验内容①使用内嵌汇编的方法设计允许和禁止中断程序。
②验证汇编程序调用C程序函数和访问C程序变量的执行过程。
7.4 实验过程1、实验7-1 允许和禁止中断程序本实验使用内嵌汇编的方法完成允许和禁止中断程序设计,这里使用Armulator 作为调试的目标机。
(1)新建ARM工程exp7_1启动ADS开发环境,选择File→New(Project)选项,使用ARM Executable Image工程模板创建一个工程exp5_1.(2) 新建汇编程序文件exp7_1_1.c,并将其添加到工程exp7_1中选择File→New(File)选项,新建汇编源程序文件exp7_1_1.c并添加到工程exp7_1中,exp7_1_1.c源程序的参考代码如下: #include__inline void enable_IRQ(void) {int tmp;__asm {MRS tmp, CPSRBIC tmp, tmp, #0x80 MSR CPSR_c, tmp } }__inline void disable_IRQ(void) {int tmp; __asm{MRS tmp, CPSR ORR tmp, tmp, #0x80 MSR CPSR_c, tmp } }int main(void) {enable_IRQ( ); disable_IRQ( ); return 0;}(3) 设置工程exp7_1的编译和链接选项选择Edit→DebugRel Settings选项,打开DebugRel Settings对话框,设置工程编译和链接选项,在Language Settings→ARM Assembler选项中,选择Target选项卡,修改处理器类型为ARM920T. (4) 编译和链接工程在工程exp7_1窗口中,选择Make工具按钮,编译和链接工程exp7_1,如果有错误提示,请检查修改程序中的语法错误,直到编译和链接通过。
C与汇编语言混合编程⏹嵌入式C语言程序设计技巧⏹C与汇编语言混合编程⏹嵌入式C语言程序构架位运算⏹位运算⏹C语言中位运算符有:⏹按位求反~①按位与&③⏹左移<<②按位异或^④⏹右移>>②按位或|⑤⏹(圆圈中的数字表示运算符的优先级)⏹扩展运算符包括:<<=、>>=、&=、^=、|=。
⏹位运算的实质是对字节或字中的实际位进行检测、设置或移位,它只适用于字符型和整数型变量以及它们的变体,对其它数据类型不适用。
⏹移位运算:⏹右移:变量名>>移位的位数⏹左移:变量名<<移位的位数⏹讨论位运算符和逻辑运算符的不同。
嵌入式系统总是要用户对变量或寄存器进行位操作。
给定一个整型变量a,写两段代码,第一个设置a的bit3,第二个清除a的bit3。
在以上两个操作中,要保持其它位不变。
位操作(Bit manipulation)#define BIT3(0x1<<3)static int a;void set_bit3(void){a|=BIT3;}void clear_bit3(void){a&=~BIT3;}变量修饰符⏹volatile—易失性修饰符,说明所定义的变量或指针,是可以被多种原因修改的.⏹一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。
精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。
下面是volatile变量的几个例子:⏹1)存储器映射的硬件寄存器(如:状态寄存器)⏹2)一个中断服务子程序中会访问到的非自动变量(Non-automaticvariables)⏹3)多线程应用中被几个任务共享的变量⏹volatile定义寄存器⏹C语言中绝对地址0x1D30000只被当做整数,做为地址时要强制转换,如:⏹int*p;p=(*int)0x1D30000;//定义44b0中与看门狗相关的寄存器地址#define rWTCON(*(volatile unsigned*)0x1D30000)#define rWTDAT(*(volatile unsigned*)0x1D30004)#define rWTCNT(*(volatile unsigned*)0x1D30008)⏹硬件端口寄存器读取问题⏹char x=0,y=0,z=0;⏹x=readChar(0x54000000);⏹y=x;⏹x=readChar(0x54000000);⏹z=x;⏹很可能被编译器优化为:⏹char x=0,y=0,z=0;⏹x=readChar(0x54000000);⏹y=x;⏹z=x;⏹嵌入式C语言程序设计技巧⏹C与汇编语言混合编程⏹嵌入式C语言程序构架C语言与汇编语言混合编程⏹C语言和ARM汇编语言程序间相互调用1.汇编代码访问全局C变量2.C程序调用汇编程序3.汇编程序调用C程序⏹在C程序和ARM汇编程序之间相互调用必须遵守ATPCS.C语言与汇编语言混合编程⏹ATPCS介绍⏹ATPCS(ARM-Thumb Produce call Standard)是ARM程序和Thumb程序中子程序调用的基本规则,目的是为了使单独编译的C语言程序和汇编语言程序之间能够相互调用.⏹基本ATPCS规定了在子程序调用时的一些基本规则,包括:各寄存器的使用规则及其相应的名称,堆栈的使用规则,参数传送的规则.C语言与汇编语言混合编程⏹1.寄存器的使用规则⏹子程序间通过寄存器R0-R3来传递参数.⏹在子程序中,使用寄存器R4-R11来保存局部变量.⏹寄存器R12用作子程序间的scratch寄存器,IP.⏹寄存器R13用作数据栈指针,SP.⏹寄存器R14称为链接寄存器,LR.⏹寄存器R15是程序计数器,PC.⏹2.数据栈的使用规则⏹根据堆栈指针指向位置的不同和增长方向的不同可以分为以下4种数据栈:⏹FD(Full Descending)满递减⏹ED(Empty Descending)空递减⏹FA(Full Ascending)满递增⏹EA(Empty Ascending)空递增⏹ATPCS规定数据栈为FD(满递减)类型,并且对数据栈的操作是8字节对齐的。
单片机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引脚的输入电压。
(完整word版)keilC语⾔与汇编语⾔混合编程keil C语⾔与汇编语⾔混合编程1. C语⾔中嵌⼊汇编1、在C ⽂件中要嵌⼊汇编代码⽚以如下⽅式加⼊汇编代码:#pragma ASM;Assembler Code Here#pragma ENDASM2、在Project 窗⼝中包含汇编代码的C ⽂件上右键,选择“Options for ...”,点击右边的“Generate Assem bler SRCFile”和“Assemble SRC File”,使检查框由灰⾊变成⿊⾊(有效)状态;3、根据选择的编译模式,把相应的库⽂件(如Small 模式时,是Keil\C51\Lib\C51S.Lib)加⼊⼯程中, 该⽂件必须作为⼯程的最后⽂件;4、编译,即可⽣成⽬标代码。
来个实例吧:#i ncludevoid main(void){P2=1;#pragma asmMOV R7,#10DEL:MOV R6,#20DJNZ R6,$DJNZ R7,DEL#pragma endasmP2=0;}2 . ⽆参数传递的函数调⽤C51调⽤汇编函数1.⽆参数传递的函数调⽤先来个例⼦:其中example.c和example.a51为项⽬中的两个⽂件***********************example.c***********************************************extern void delay100();main(){delay100;}***********************example.a51***********************************************PRDELAY100 SEGMENT CODE; // 在程序存储区中定义段PUBLIC DELAY100; //声明函数RSEG ?PR?DELAY100; //函数可被连接器放置在任何地⽅DELAY100:MOV R7,#10DEL:MOV R6,#20DJNZ R6,$DJNZ R7,DELRETEND在example.c⽂件中,先声明外部函数,然后直接在main中调⽤即可。
C/C++ 语言和汇编语言混合编程开发为了充分利用DSP芯片的硬件资源,更好发挥C/C++ 语言和汇编语言进行软件开发的各自优点,可以将两者有机的结合起来,兼顾两者优点,避免其弊端。
因此,在很多情况下,采用混合编程方法能更好地达到设计要求,完成设计任务。
C/C++语言和汇编语言混合编程的具体方法有以下几种:(1)独立编写C/C++程序和汇编程序,分开编译或汇编形成各自的目标模块,再用链接器将C/C++模块和汇编模块链接起来,这是一种灵活性较大的方法。
但用户必须自己维护各汇编模块的入口和出口代码,自己计算传递参数在堆栈中的偏移量,工作量稍大,但能做到对程序的绝对控制,也能满足软件设计结构化的要求。
这是主要讲述的方法。
(2)在C/C++程序中使用汇编程序中定义的变量和常量。
(3)在C/C++程序中直接内嵌汇编语句。
这种方法可以在C/C++程序中实现C/C++语言无法实现的硬件控制功能,如修改中断控制寄存器、中断标志寄存器等。
(4)在C/C++源程序中使用内部函数直接调用汇编语言语句。
后3种方法由于在C/C++语言中直接嵌入了汇编语言的成分,容易造成程序混乱,C/C++环境被破坏,甚至导致程序崩溃,而编程者又很难对不良结果进行预期和有效控制。
而如果采用第一种方法,只要遵循有关C/C++语言函数调用规则和寄存器规则,就能预见到程序运行的结果,保证程序正确。
下面分别讲述函数调用规则和寄存器规则。
1.函数调用规则C/C++编译器对函数调用强加了一组严格的原则。
除了特殊的运行时间支持库函数外,任何调用函数和被C/C++函数调用的函数都必须遵守这些原则。
不遵守这些原则可能破坏C/C++环境并导致程序失败。
图1说明了典型的函数调用。
在这个例子中,参数被传递到堆栈中调用者的参数块,函数再使用这些参数调用被调用函数。
注意,第一个参数是在A累加器中传递的。
这个例子还说明了汇编器对被调用函数的局部帧的分配。
局部帧包括局部变量块和局部参数块两部分,其中局部参数块是局部帧中用来传递参数到其他函数的部分。
keil C语言与汇编语言混合编程1. C语言中嵌入汇编1、在C 文件中要嵌入汇编代码片以如下方式加入汇编代码:#pragma ASM;Assembler Code Here#pragma ENDASM2、在Project 窗口中包含汇编代码的C 文件上右键,选择“Options for ...”,点击右边的“Generate Assem bler SRC File”和“Assemble SRC File”,使检查框由灰色变成黑色(有效)状态;3、根据选择的编译模式,把相应的库文件(如Small 模式时,是Keil\C51\Lib\C51S.Lib)加入工程中, 该文件必须作为工程的最后文件;4、编译,即可生成目标代码。
来个实例吧:#i nclude <reg51.h>void main(void){P2=1;#pragma asmMOV R7,#10DEL:MOV R6,#20DJNZ R6,$DJNZ R7,DEL#pragma endasmP2=0;}2 . 无参数传递的函数调用C51调用汇编函数1.无参数传递的函数调用先来个例子:其中example.c和example.a51为项目中的两个文件***********************example.c***********************************************extern void delay100();main(){delay100;}***********************example.a51***********************************************?PR?DELAY100 SEGMENT CODE; // 在程序存储区中定义段PUBLIC DELAY100; //声明函数RSEG ?PR?DELAY100; //函数可被连接器放置在任何地方DELAY100:MOV R7,#10DEL:MOV R6,#20DJNZ R6,$DJNZ R7,DELRETEND在example.c文件中,先声明外部函数,然后直接在main中调用即可。
黄冈师范学院提高型实验报告实验课VC++与汇编语言的混合编程题(实验类型:□综合性□设计性■应用性)汇编语言程序设计实验课程实验时间2008-12-26学生姓名专业班级计科0605学号一、实验目的和要求掌握VC++语言和汇编语言的混合编程方法,了解不同编程语言的接口方法,体会汇编语言的应用。
掌握嵌入汇编函数和汇编语言子程序与VC++的混合编程方法,入口、出口参数的传递方法以及在VC++环境下混合编程的调试方法。
二、实验条件硬件:计算机一台软件:Visual Studio C++ 6.0、MASM 6.0三、实验原理分析在Turbo C++或Borland C++编程环境下,我们可TCC或BCC行命令把一个C语言的源程序转换成汇编语言的源程序。
通过阅读汇编语言程序可以很准确地知道C 语言语句的功能是如何实现的。
C语言源程序转换的命令格式如下:TCC -S t1.c 或 BCC -S t1.c;假设其文件名为t1.c注意:(1)TCC在TC目录下,若命令TCC/BCC不带参数的话,则将显示其使用方法。
(2)其中-S中要求S为大写。
(3)在TC上做以上操作,必须保证:TC正常安装(c:\turboc2),目录名及文件夹名都不能改变。
下面是C语言程序及其相对应的汇编语言程序,希望读者能逐行对照理解它们语句之间的转换关系,这将能进一步理解高级语言的语句功能。
(4汇编语言和高级语言混合编程,需要解决两个主要的技术问题:不同语言程序模块之间的连接;调用过程中参数的传递方法。
对此不同的高级语言或同一种高级语言的不同版本所采取的具体方法不尽相同。
本节主要介绍汇编语言与C/C++语言接口的基本方法。
调用协议是指在进行子程序调用时,主程序向子程序传递参数以及从子程序获得返回值的约定方式。
通常参数传递的方法是:主程序使用系统堆栈向子程序传递入口参数,子程序使用CPU内部寄存器来保存向主程序的返回值。
此外调用协议还将确定哪些寄存器的内容需要保护,哪些寄存器可以自由使用。
实验二C语言与汇编语言混合编程
一、实验目的
1.掌握ARM嵌入式C语言编程基本方法。
2. 掌握嵌入式汇编(Inline Assembly)编程规则和方法。
3.掌握汇编语言程序和C语言程序之间相互调用规则和编程方法。
二、实验步骤
1. 创建工作空间并且添加工程。
2.编写程序并且利用软件仿真查看结果。
三、实验内容
1.利用汇编语言编写初始化程序,实现管理模式下堆栈指针初始化,
并最终跳转到C语言程序开始Main函数处执行。
2.利用汇编语言编写子程序实现字符串拷贝功能,利用C语言在
Main函数中定义字符串“Hello World!”定义并调用该子程序完成字符串拷贝。
3.利用汇编语言编写子程序完成冒泡法排序,利用C语言在Main
函数中定义字符串“Hello World!”定义并调用该子程序将数组中字符按照ASCII码值由小到大重新排序。
思考:
1.GNU编译环境下混合编程与ADS环境下有些什么区别?
.global _start
.global str_cpy
.text
_start:
BIC R0,R0,#MODEMASK @将CPSR中的模式位
ORR R1,R0,#FIQMODE @设置模式位为FIQ模式
MSR CPSR_c, R1 @切换处理器到FIQ模式
LDR SP,=FIQStack @设置该模式下的堆栈
BIC R0,R0,#MODEMASK @将CPSR中的模式位
ORR R1,R0,#IRQMODE @设置模式位为IRQ
MSR CPSR_c, R1 @切换处理器到IRQ模式
LDR SP,=IRQStack @设置该模式下的堆栈
BIC R0,R0,#MODEMASK @将CPSR中的模式位
ORR R1,R0,#USRMODE @设置模式位为IRQ
MSR CPSR_c, R1 @切换处理器到IRQ模式
LDR SP,=IRQStack @设置该模式下的堆栈
BL Main
B .
.equ FIQMODE,0x11
.equ IRQMODE,0x12
.equ SVCMODE,0x13
.equ USRMODE,0x10
.equ SVCStack,0x03FE0100
.equ FIQStack,0x03FE0200
.equ IRQStack,0x03FE0300
.equ MODEMASK,0x1F
str_cpy:
LDRB R2,[R0],#1
STRB R2,[R1],#1
CMP R2,#0
BNE str_cpy
MOV PC,R14
.end
extern void str_cpy(char *x,char *y);
int Main()
char *a="Hello World!\n";
char b[13];
str_cpy(a,b);
return 0;
.global _start
.global str_cpy
.global line
.text
_start:
BIC R0,R0,#MODEMASK @将CPSR中的模式位
ORR R1,R0,#FIQMODE @设置模式位为FIQ模式
MSR CPSR_c, R1 @切换处理器到FIQ模式
LDR SP,=FIQStack @设置该模式下的堆栈
BIC R0,R0,#MODEMASK @将CPSR中的模式位
ORR R1,R0,#IRQMODE @设置模式位为IRQ
MSR CPSR_c, R1 @切换处理器到IRQ模式
LDR SP,=IRQStack @设置该模式下的堆栈
BIC R0,R0,#MODEMASK @将CPSR中的模式位
ORR R1,R0,#USRMODE @设置模式位为IRQ
MSR CPSR_c, R1 @切换处理器到IRQ模式
LDR SP,=IRQStack @设置该模式下的堆栈
BL Main
B .
.equ FIQMODE,0x11
.equ IRQMODE,0x12
.equ SVCMODE,0x13
.equ USRMODE,0x10
.equ SVCStack,0x03FE0100
.equ FIQStack,0x03FE0200
.equ IRQStack,0x03FE0300
.equ MODEMASK,0x1F
str_cpy:
ldrb r2,[r0],#1
strb r2,[r1],#1
cmp r2,#0
bne str_cpy
mov pc,r14 line: mov r4,r0
add r5,r4,#1
mov r6,#12 loop1: mov r0,r4
mov r1,r5 loop:
ldrb r2,[r0]
ldrb r3,[r1]
cmp r3,#0x0a
beq ends
cmp r2,r3
strhib r3,[r0],#1
strhib r2,[r1],#1
addls r0,r0,#1
addls r1,r1,#1
b loop ends: subs r6,r6,#1
bne loop1
mov pc,r14
.end。