C语言与汇编语言混合编程_32位嵌入式共6页word资料

合集下载

嵌入式Linux下C和汇编的混合编程

嵌入式Linux下C和汇编的混合编程

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的混合编程PPT教学课件

汇编语言与C的混合编程PPT教学课件
• 第1个寄存器列表中的寄存器用于存放输入的参数。 • 第2个寄存器列表中的寄存器用于存放返回的结果。 • 第3个寄存器列表中的寄存器的内容可能被所调用
的子程序破坏,即这些寄存器是供所调用的子程 序作为工作寄存器的。
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语言混合编程实验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语言第7讲嵌入式C与汇编语言混合编程

C语言第7讲嵌入式C与汇编语言混合编程

7.1 内嵌汇编器的使用
在C/C++程序中使用内嵌的汇编指令注意事项 程序中使用内嵌的汇编指令注意事项

对于内嵌汇编器可能会用到的寄存器, 对于内嵌汇编器可能会用到的寄存器,编译器自己会保存 和恢复这些寄存器,用户不用保存和恢复这些寄存器。 和恢复这些寄存器,用户不用保存和恢复这些寄存器。常 量寄存器CPSR和寄存器 和寄存器SPSR外,别的寄存器必须先赋值 量寄存器 和寄存器 外 然后再读取,否则编译器将会报错。如下例中, 然后再读取,否则编译器将会报错。如下例中,第一条指 令在没有给寄存器r0赋值前读取其值 是错误的; 赋值前读取其值, 令在没有给寄存器 赋值前读取其值,是错误的;最后一 条指令恢复寄存器r0的值 的值, 条指令恢复寄存器 的值,也是没有必要的
7.1 内嵌汇编器的使用
内嵌的汇编器和armasm的区别 的区别 内嵌的汇编器和
使用内嵌的 汇编器不能 通过寄存器 PC返回当前 返回当前 指令的地址
内嵌的汇编器不 支持伪指令LDR 支持伪指令 Rn,=expression可 可 以使用mov来代替 以使用 来代替
不支持标号 表达式
不支持ADR、 、 不支持 ADRL 伪指令
7.1 内嵌汇编器的使用
内嵌的汇编指令用法——标号 标号 内嵌的汇编指令用法
C/C++程序中的标号可以被内嵌的汇编指令使用。但 程序中的标号可以被内嵌的汇编指令使用。 程序中的标号可以被内嵌的汇编指令使用 是只有指令B可以使用 可以使用C/C++程序中的标号,指令 程序中的标号, 是只有指令 可以使用 程序中的标号 指令BL 不能使用C/C++程序中的标号。指令 使用 程序中的标号。 使用C/C++程 不能使用 程序中的标号 指令B使用 程 序中的标号时,语法格式如下所示: 序中的标号时,语法格式如下所示:

汇编语言与C的混合编程

汇编语言与C的混合编程

1.3常量
• 在内嵌的汇编指令中,常量前的符号#可以省略。如果在一个表达式 前使用#,则该表达式必须是一个#。 • 1.4指令展开 • 内嵌的汇编指令中如果包含常量操作数,则该指令可能会被汇编器展 开成几条指令。例如指令: • ADD R0,R0,#1023 • 可能会被展开成下面的指令序列 • ADD R0,R0,#1024 • SUB R0,R0,#01 • 乘法指令MUL可能会被展开成一系列的加法操作和移位操作。 • 事实上,除了与协处理器相关的指令外,大部分的ARM指令和 Thumb指令中包含常量操作数都可能被展开成多条指令。
1.2物理寄存器
• 在内嵌的汇编指令中使用物理寄存器有一下限制: • 不能直接向PC寄存器中赋值,程序的跳转只能通过B指令和BL指令实 现。 • 在使用物理寄存器的内嵌汇编指令中,不要使用过于复杂的C表达式, 因为当表达式过于复杂时,将会需要较多的物理寄存器,这些寄存器 可能与指令中的物理寄存器的使用冲突。 • 编译器可能会使用R1寄存器或者R13寄存器存放编译的中间结果,在 计算表达式值时可能会将寄存器R0~R3、R2以及R14用于子程序的调 用。因此在内嵌的汇编指令中,不要将这些寄存器同时指定为指令中 的物理寄存器。 • 在内嵌的汇编指令中使用物理寄存器时,如果有C变量使用了该物理 寄存器,编译器将在合适的时候保存并恢复该变量的值。需要注意的 是,当寄存器sp、sl、fp以及sb用做特定的用途时,编译器不能恢复 这些寄存器的值。 • 通常推荐在内嵌的汇编指令中不要指定物理寄存器,因为这可能会影 响编译器分配寄存器,进而可能影响代码的效率。
• 下面是一个在汇编程序中访问C程序全局变量的例子。程序中变量 globv1是在C程序中声明的全局变量。在汇编程序中首先使用 IMPORT伪操作声明该变量;R0中;修改后再将寄存器R0的值赋予变量 globv1.本例中程序如下: • AREA globals,CODE,READONLY • EXPORT asmsub • IMPORT global ;用IMPORT伪指令声明该变量 • asmsum • LDR R1,# globv1 ;将其内存地址读入到寄存器R1中 • LDR R0,[R1] ;再将其值读入到寄存器R0中 • ADD R0,R0,#2 • STR R0,[R1] ;修改后再将寄存器R0的值赋予变量globv1 • MOV PC,LR • END

C语言与汇编语言混合编程

C语言与汇编语言混合编程
1. 基本ATPCS 基本ATPCS规定了在子程序调用是的一些基本规 则,包括下面3方面的内容:
1) 各寄存器的使用规则及其相应的名称。 2) 数据栈的使用规则。 3) 参数传递的规则。
相对于其他类型的ATPCS, 满足ATPCS的程序的 执行速度更快,所占用的内存更少,但是它不能提供以 下的支持:ARM程序和Thumb程序相互调用、数据以 及代码的位置无关的支持、子程序的可重入性和数据 栈检查的支持。
途。 3.参数传递规则 根据参数个数是否固定可以将子程序分为参数
个数固定的子程序和参数个数可变的子程序。 (1)参数个数可变的子程序参数传递规则
对于参数个数可变的子程序,当参数个数不超
过4个时,可以使用寄存器R0~R3来传递参数,当参 数超过4个时,还可以使用数据栈来传递参数。 (2)参数个数固定的子程序参数传递规则
❖ 结果为一个64位整数时,可以通过寄存器R0和R1 返回,依次类推。
❖ 结果为一个浮点数时,可以通过浮点运算部件的寄 存器f0、d0或者s0来返回。
❖ 结果为复合型的浮点数时,可以通过寄存器f0~fN或 者d0~dN来返回。
❖ 对于位数更多的结果,需要通过内存来传递。
对有调用关系的所有子程序必须遵守同一种 ATPCS。
嵌入式系统设计与开发
C语言与汇编语言混合编程
1.1 C程序与汇编程序互相调用规则 1.2 内嵌汇编程序设计 1.3 C语言函数和ARM汇编语言函数间互相调用
C语言与汇编语言混合编程
1.1 C程序与汇编程序互相调用规则 为了使单独编译的C语言程序和汇编程序之间能
够相互调用,必须让子程序间的调用遵循一定的规则。 ATPCS即ARM,Thumb过程调用标准,是ARM程序和 Thumb程序中子程序调用的基本规则,它规定了一些子 程序间调用的基本规则。下面介绍几种ATPCS规则:

C与汇编混合编程_

C与汇编混合编程_

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语言的混合编程

2. 在汇编中使用C定义的全局变量
#include <stdio.h> int gVar_1 = 12; extern asmDouble(void);
int main() { printf("original value of gVar_1 is: %d", gVar_1); asmDouble(); printf(" modified value of gVar_1 is: %d", gVar_1); return 0; }
内嵌汇编使用的标记是 __asm,用法如下: __asm { instruction [; instruction] … [instruction] }
void enable_IRQ(void) { void disable_IRQ(void) {
int tmp;
__asm
int tmp;
__asm
PRESERVE8 AREA Scopy ,CODE,READONLY EXPORT strcopy strcopy LDRB R2,[R1],#1 STRB R2,[R0],#1 CMP R2,0 BNE strcopy MOV pc,lr END
在汇编中调用C的函数
• 在汇编中调用C的函数,需要在汇编中IMPORT 对应 的C函数名,使用BL指令调用
return a + b + c;
}
int g( int a, int b, int c, int d, int e, int f ) { printf(“e=%d\n”, e); printf(“f=%d\n”, f); return (a+b+c+d+e+f); }

C语言与汇编语言混合编程

C语言与汇编语言混合编程

PUSH BP MOV BP,SP PUSH SI
PUSH DI MOV SI,WURD PTR[BP+4妖;取第一参数值 MOV DI.WORD PTR[BP+6〕;取第二参数值
PUSH DI PUSH SI LEA AX,B;取数组 B 首址
MOV DX,AX MOV AX,0900H INT 21H ;DOS 功能调用显示字符串 B
关 键 词 : 双摇杆机构 摆角 Pro/e 中图分类号: TP319 文献标识码: A 文章编号:1002-2422(2010)01-0125-02
Application of Pro / Engineering in the Double Rocker Mechanism
Huang Junjie Zhang Yuanshou Xu Xingxin Abstract: In order to intuitively and easily calculate the tilt angle of the double-rocker mechanism, the solid modeling of the
[2] 龙佑喜,彭三城. C 语言程序设计教程 (第二版)[M]. 湖南:湖南教育出版 社,2005-10.
பைடு நூலகம்
收稿日期:2009-11-20 *陈丹 辽宁工程技术大学职业技术学院讲师(辽宁,阜新 123000)。
· 123 ·
一是汇编与 C 程序模块的连接,二是函数调用过程中参数
的传递。
1 C 模块调用汇编模块
进行混合编程时,一个任务往往被分为若干功能模块,
每个模块以函数的形式存在,根据每一模块的特点选用适合
的语言独立编程,然后使用相应的语言编译系统对其进行编

单片机C语言与汇编语言的混合编程

单片机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引脚的输入电压。

(完整word版)keilC语言与汇编语言混合编程

(完整word版)keilC语言与汇编语言混合编程

(完整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语言和汇编语言混合编程

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累加器中传递的。

这个例子还说明了汇编器对被调用函数的局部帧的分配。

局部帧包括局部变量块和局部参数块两部分,其中局部参数块是局部帧中用来传递参数到其他函数的部分。

汇编语言和C语言的简单混合编程

汇编语言和C语言的简单混合编程

ASM JB COPY
/*转移到C的标号*/
ASM CMP A1,’Z’
ASM JA COPY /
/*不是’A’到’Z’之间的字符原样复制*
ASM ADD A1,20H
/*是小写字母转换成大写字母*/
copy:ASM STOSB
/* C语言定义的标号*/
ASM CMP AL,0
/* C语言中字符串用0结尾 */
12
注意:直接使用Turbo C的连接程序TLINK进行连接时,用户必须指定要连接 的与存储模式一致的初始化模块和函数库文件,并且初始化模块必须是第 一个文件。上例中,Lib\c0m和Lib\cm就是在Lib目录下中型存储模式的 初始化模块c0m.obj和函数库cm.lib。 如果形成的可执行文件exampl. exe正确,它的运行结果将是:
6
}
编辑完成后,假定该文件名为,在命令行输人如下 编译命令(选项-I和-L分别指定头文件和库函数的 所在目录):
TCC –B –Iinclude –Llib example.c 生成可执行文件example.exe,程序运行后输出的结
果将是:
OLD STRING IS I’AM a good STUDENT!
/*GOOD函数返回值缺省为INT型*/
EXTERN char tempvar
/*TEMPVAR变量为CHAR型*/
经说明后,这些外部变量、过程、函数可在C程序中直接使用,函数的参数在传 递过程中要求参数个数、类型、顺序要一一对应。
和纯汇编语言多模块编程要求一样,汇编语言程序的标识符(子程序名和变量名)
以用换行符结束;一行中可以有多个汇编语句,相互间用分号分隔, 但不能跨行书写。嵌入汇编语句的分号不是注释的开始;要对语句注 释,应使用C语言的注释,如/*……*/。例如:

C语言与汇编语言的混合编程

C语言与汇编语言的混合编程
单片机原理与应用
C语言与汇编语言的混合编程
C语言调用汇编语言程序时,被调用函数(汇编语言函数)要在调 用函数(C语言函数)所在文件中说明。对于汇编语言程序有以下 要求
(1) 要使用SEGMENT伪指令定义可重定位的CODE段 (2) 要根据不同情况对函数名进行转换 (3) 须使用PUBLIC伪指令将被调用函数说明为外部可用函数 (4) 若有参数传递,规则使用参数 (5) 若有返回值,按照则存入寄存器
编写汇编语言函数max,参数为两个8位无符号数,功能是求出 其中的大数返回
extern unsigned char max(unsigned, unsigned);
混合编程的例子
PUBLIC
_MAX
;声明
MIXED SEGMENT RSEG
CODE MIXED
;定义一个可重定位的段 ;选择MIXED为当前段
_MAX: MOV CLR SUBB JNC MOV MOV
_MAX_RET: RET
A, R7ቤተ መጻሕፍቲ ባይዱC A, R5 _MAX_RET A, R5 R7, A
;第一个参数
;减去第二个参数 ;无借位,第一个参数值大 ;有借位,第二个参数值大 ;返回值在R7
END
单片机原理与应用
函数名转换规则
函数首部
void func(void)
void func(char) void func(void) reentrant
符号名 FUNC _FUNC
说明
无参数传递或不含寄存器参数的函数 名不作改变
带寄存器参数的函数名加“_”前缀
_?FUNC 可重入函数前加“_?”前缀
混合编程的例子

(完整word版)keil C语言与汇编语言混合编程

(完整word版)keil C语言与汇编语言混合编程

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 与汇编语言的混合编程.

VC  与汇编语言的混合编程.

黄冈师范学院提高型实验报告实验课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语言及汇编语言混合编程_ARM嵌入式系统原理与开发_[共6页]

C语言及汇编语言混合编程_ARM嵌入式系统原理与开发_[共6页]
3.参数的传规则
根据参数个数是否固定,可以将子程序分为参数个数固定的子程序和参数个数可变的子 程序。这两种子程序的参数传递规则是不同的。
(1)参数个数可变的子程序参数传递规则 对于参数个数可变的子程序,当参数不超过 4 个时,可以使用寄存器 R0~R3 来进行参 数传递;当参数超过 4 个时,还可以使用数据栈来传递参数。在参数传递时,将所有参数看 做是存放在连续的内存单元中的字数据。然后,依次将各名字数据传送到寄存器 R0,R1, R2,R3;如果参数多于 4 个,将剩余的字数据传送到数据栈中,入栈的顺序与参数顺序相反, 即最后一个字数据先入栈。按照上面的规则,一个浮点数参数可以通过寄存器传递,也可以 通过数据栈传递,也可能一半通过寄存器传递,另一半通过数据栈传递。 (2)参数个数固定的子程序参数传递规则 对于参数个数固定的子程序,参数传递与参数个数可变的子程序参数传递规则不同, 如果系统包含浮点运算的硬件部件,浮点参数将按照下面的规则传递:各个浮点参数按顺 序处理;为每个浮点参数分配 FP 寄存器;分配的方法是,满足该浮点参数需要的且编号最 小的一组连续的 FP 寄存器。第 1 个整数参数通过寄存器 R0~R3 来传递,其他参数通过数 据栈传递。 (3)子程序结果返回规则 ① 结果为一个 32 位的整数时,可以通过寄存器 R0 返回。 ② 结果为一个 64 位整数时,可以通过 R0 和 R1 返回,依此类推。 ③ 结果为一个浮点数时,可以通过浮点运算部件的寄存器 f0、d0 或者 s0 来返回。 ④ 结果为一个复合的浮点数时,可以通过寄存器 f0~fN 或者 d0~dN 来返回。 ⑤ 对于位数更多的结果,需要通过调用内存来传递。
__asm { 指令 [;指令] … [指令] } asm("指令[;指令]");

C及汇编语言的混合编程

C及汇编语言的混合编程

不要使用寄存器代替变量.尽管有时寄存器明显对应某个 变量,但也不能直接使用寄存器代替变量. int bad_f(int x) //x 存放在R0 中 { _ _asm { ADD R0,R0,#1 //发生寄存器冲突,实际上x 的值没有变化 } return(x); } 尽管根据编译器的编译规则似乎可以确定R0 对应x,但 这样的代码会使内嵌汇编器认为发生了寄存器冲突. 6
11
ATPCS中各寄存器的使用规则 及其名称
12
ATPCS中各寄存器的使用规则 及其名称
参数传递规则
1.
2.
3.
参数不超过4个时,可以使用寄存器R0~R3来传 递参数,当参数超过4个时,还可以使用数据栈来 传递参数。 结果为一个32位整数时,可以通过寄存器R0返回 结果为一个64位整数时,可以通过寄存器R0和R1 返回,依次类推。
16
7.4 汇编程序、C程序及C++程序 相互调用
汇编程序调用C程序 汇编程序的设置要遵循ATPCS 规则,保证程 序调用时参数的正确传递. 在汇编程序中使用IMPORT 伪指令声明将要 调用的C 程序函数. 在调用C 程序时,要正确设置入口参数,然后 使用BL 调用.
17
7.4 汇编程序、C程序及C++程序 相互调用
#include <stdio.h> int globvar=3; //定义一个整型全局变量 int main() { return 0; }
9
7.3 从汇编程序中访问C程序变量
例如:汇编源文件hello.s: AREA globals,CODE,READONLY EXPORT asmsub IMPORT globvar ;声明外部变量globvar asmsub LDR R1,=globvar ;装载变量地址 LDR R0,[R1] ;读出数据 ADD R0,R0,#2 ;修改R0的值 STR R0,[R1] ;保存变量值 MOV PC, LR END
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验二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。

相关文档
最新文档