C语言和汇编语言混合编程的方法和实现
- 格式:pdf
- 大小:277.74 KB
- 文档页数:3
汇编语⾔与C语⾔混合编程技术汇编语⾔与C语⾔混合编程技术 ARM体系结构⽀持ARM的汇编语⾔与C与C++的混合编程。
在⼀个完整的程序设计的中,除了初始化部分⽤汇编语⾔完成外,其⼤部分的编程任务⼀般都⽤C或C++完成。
汇编程序中访问C程序变量1 在汇编的源程序中调⽤C语⾔风格的字符串需要使⽤IMPORT伪操作。
IMPORT相当于C语⾔中的extern关键字,告诉编译器引⽤的符号不是在本⽂件中定义的,⽽是在其他的源⽂件中定义的。
伪操作的格式: IMPORT symbol [,WEAK] symbol是声明的符号的名称; [,WEAK]指⽰编译器如果发现symbol在所有的源⽂件中都没有找到,那么它也不会产⽣任何的错误信息。
⽰例见下页。
汇编程序中访问C程序变量2 C语⾔代码⽂件str.c⾥⾯只有⼀个简单的字符串的定义: char *strhello="Hello world!\n\0"; 汇编代码⽂件hello.s 1 AREA ||.text||, CODE, READONLY 2 main PROC 3 STMFD sp!,{lr} 4 LDR r0,=strtemp 5 LDR r0,[r0] 6 BL _printf 7 LDMFD sp!,{pc} 8 strtemp 9 DCD strhello 10 ENDP 11 EXPORT main 12 IMPORT strhello 13 IMPORT _main 14 IMPORT _main 15 IMPORT _printf 16 IMPORT ||Lib$$Request$$armlib||, WEAK 17 END C程序中内嵌汇编指令1 在ARM的C语⾔程序中可以使⽤关键字__asm来加⼊⼀段汇编语⾔的程序。
格式: __asm { instruction/*comment*/ … } C程序中内嵌汇编指令2 在C语⾔中嵌⼊的ARM汇编需要注意⼀些问题:在汇编指令中,可以使⽤表达式,使⽤逗号“,”作为分隔符 ; 如果⼀条指令占⽤了多⾏,那么应该使⽤符号“\”续⾏,如果⼀⾏中有多个汇编指令,那么应该使⽤“;”将多个指令隔开。
实验二汇编语言与C语言混合编程
一、教学目的和要求
熟悉ADS1.2开发环境编译、下载、调试程序的基本过程;
掌握C和汇编语言混合编程方法。
掌握ATPCS中的寄存器及参数传递规则。
二、实验内容
1、分别编写C程序和汇编程序,要求在C程序中调用汇编程序实现字符串拷贝功能。
C程序中设定源字符串及目的字符串;汇编程序实现拷贝功能。
2、分别编写C程序和汇编程序,要求在汇编程序中调用C程序实现4个整型数的求和运算。
汇编程序实现变量的赋值及C函数的调用;C程序实现求和运算。
3、编写C程序内嵌汇编语句,对两个整型数a、b进行求和运算,和值存放到变量c中。
(1)要求main( ) 函数完成变量赋值及a、b、c数值信息输出;内嵌汇编语句实现求和计算。
(2)要求C程序中main( ) 函数完成变量赋值及a、b、c信息打印,add()函数实现加法运算;main( ) 函数中的内嵌汇编调用C函数add()进行求和运算。
三、思考题
1、什么是ATPCS?它有哪些规则?
2、C程序调用汇编程序需要进行哪些设置?参数如何传递?
3、汇编程序调用C程序需要进行哪些设置?参数如何传递?
4、C程序中内嵌的汇编语句有何限制?用什么关键字表示内嵌汇编?。
汇编语言与 C 语言的混合程序设计技术一、混合编程中如何进行参数传递汇编语言程序和 C 语言程序在调用时会涉及到参数传递 ,一般采用堆栈进行传递。
在汇编语言中将 BP 作为基址寄存器 , 调用程序先将来自于 C 语言程序中的参数依次压入堆栈中 , 然后当需要使用这些参数时 , 再用 BP加上不同的偏移量依次对堆栈中的数据进行存取操作不同类型数据的传送有着一些不同1、整数型常量的传递整数型常量的传递是将所传递整数从上到下按顺序存储在参数区中, 以字为单位按十六进制方式存放2、字符型常量的传递c语言规定字符型常量要用单引号括起,因此传递时应特别注意传递的方式是将字符以ASCII码的形式以字节为单位放在参数区中如遇多个字符的传递可直接将多个字符顺序连写在一起用单引号括起来3、字符串常量的传递,在C语言里,字符串要求用双引号括起来传递的方式不同于以上两常量它是将字符串存放在某个数据区域内将字符串的首址指针放存参数区中因此在参数区中我们不可能找到所传送的字符串,能见到的只有一个地址指针4、整数型变量传递整数型变量的传递类似于整数型常量的传递只是将整数型变量中的内容加以传递5、字符型数组的传递字符型数组的传递类似于字符串常量的传被传递数组中的字符被存放到某个数据区而将字符数组所在的首址指针放到参数区6、整型数组的传递由于整型数组的数据量一般较大 , 因此我们认为整型数组的传递以传递指针为好。
正是由于C语言有指针运算功能 ,数组的传递先进行指针运算 ,得到数组的首指针,再将指针传送到参数区中。
二、简述混合编程的常见形式C调用汇编有两种方法,一是直接在C中插入汇编语句,二是分别编写汇编子程序和C语言程序,由C调用汇编程序。
方法一适用只需一两句汇编就能完成的程序;方法二较通用,如用汇编编写延时子程序可以实现精确延时。
使用方法二的注意事项有以下几点:1、函数声明C中在函数前加extern声明此函数为外部函数,在汇编中要声明函数名为全局变量如extern void delay(void); / 定义函数 /globl delay ; / 声明全局变量 /_delay:; / 函数开始 /2、参数传递一般用寄存器传递参数,如果返回结果需要多个字节表示,最好用 SRAM 保存即在汇编中将结果存入SRAM在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累加器中传递的。
这个例子还说明了汇编器对被调用函数的局部帧的分配。
局部帧包括局部变量块和局部参数块两部分,其中局部参数块是局部帧中用来传递参数到其他函数的部分。
keil C语言与汇编语言混合编程1. C语言中嵌入汇编1、在C 文件中要嵌入汇编代码片以如下方式加入汇编代码:#pragma ASM;Assembler Code Here#pragma ENDASM2、在Project 窗口中包含汇编代码的C 文件上右键,选择“Options for ...”,点击右边的“Gen erate Assembler 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中调用即可。
C 语言和汇编语言混合编程方法发表时间:2015-01-09T14:53:39.630Z 来源:《价值工程》2014年第8月下旬供稿作者:庞新法[导读] C 语言是一种高级的面向过程的开发语言,汇编语言是一种低级的面向机器的编程语言。
庞新法PANG Xin-fa(陕西省委党校科技教研部,西安710061)(Research and Technology Department,Shaanxi Province Party School of the CPC,Xi'an 710061,China)摘要:C 语言是一种高级的面向过程的开发语言,汇编语言是一种低级的面向机器的编程语言。
两者在程序设计开发方面各有优劣,目前两者的混合编程得到了广泛的应用。
本文通过具体的实例,说明了混合编程的基本方法,为C 语言应用开发人员提供方便。
Abstract: C language is a high-level process oriented language and assembly language is a low-level machine oriented programminglanguage. Both in terms of program design and development have advantages and disadvantages and the current mix of both programminghas been widely used. This paper, through specific examples, illustrates the basic methods of hybrid programming which providesconvenience for the C language application developers.关键词:C 语言;汇编语言;混合编程Key words: C language;assembly language;mixed programming中图分类号:TP313 文献标识码院A 文章编号院1006-4311(2014)24-0231-020 引言汇编语言是一种面向机器的语言,其优点是运行速度快,占用存储空间小,可直接对硬件进行控制。
C语言与汇编语言相互结合的嵌套汇编语言
在单片机学习的过程中,掌握一点汇编语言是非常有必有的,作为低级语言汇编语言在单片机开发中有它不可取代的作用,比如每条指令可以精确的确定延时时间,便于理解非常适合硬件工程师学习。
但是要提高单片机技能,必须掌握 C 语言编程,因为 C 语言有强大的模块化管理思想。
我想在很多人学习的过程中即学了汇编语言,又学习了C 语言,那么一个问题便随之而产生,如果将C 语言与汇编语言相互结合,达到更好的编程效果,本次讲解就是基于这个问题而生成的。
大家可以看到,我的延时函数用的汇编。
然而编译后无法创建目标。
此时大家右键左边的工作组1:Source Group 1。
然后点击第一个OpTIons for Group Source Group 1。
将对话框右边红圈内两个选项各点两次,使对勾成为黑色。
点击OK后就可以编译了。
如果大家在编译时出现两个警告:
警告内容如下:
*** WARNING L1:UNRESOLVED EXTERNAL SYMBOL
SYMBOL:?C_START
MODULE:STARTUP.obj (?C_STARTUP)
*** WARNING L2:REFERENCE MADE TO UNRESOLVED EXTERNAL SYMBOL:?C_START
MODULE:STARTUP.obj (?C_STARTUP)
ADDRESS:0038H。
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中调用即可。
ARM汇编语言和C语言混合编程一. 在线汇编( in-line assembly)在C代码中插入一段汇编代码,比如while(1){...port=0x00aa55ff;__asm{mov r4,portstr r5,[r4]}...}具体格式为__asm{指令1;指令2;指令3;...指令n;指令n+1;......}其中指令的操作数可以是物理寄存器,也可以是C语言的变量、行号和表达式,这点是比纯汇编最大的的好处(窃以为如斯,比如上面的例子)说到这其实写在线汇编代码的思路就和纯汇编差不多了,但要注意几个问题:1.不能直接向PC赋值实现程序跳转,只能使用B和BL这两条指令2.在线汇编器会使用R0-R3,R12-R13计算表达式,因此复杂的表达式不能和以上寄存器出现在同一条指令中:mov r0,一个复杂的表达式 ----汇编器可能报错mov r5,一个复杂的表达式 ----汇编可以通过3.在线汇编中使用物理寄存器时,如果上下文的C代码也使用了同一个,则不必自己保存和恢复该物理寄存器,C代码会自己负责处理4.尽量不使用物理寄存器,因为a.影响代码效率,很有可能编译器为此把一个本应放在寄存器中的变量放在存储器中.就如同在C中定义局部变量哪个是register的,哪个是volatile的,编译器自己的优化才是最佳的。
b.发生错误:比如...mov r0,#0xaamov r1,x%ymov r2,r0...很可能r2的值不是0xaa,因为在计算表达式x%y时会用到r0,将r0的内容冲掉5.可以使用b指令b 标号; 实现跳转,标号可以时C的也可以是汇编的6.因为要计算表达式的值,所以一条虚拟指令要被展开为若干条真实指令(如上面的mov r1,x%y)因此实际上对标志为C.N.V.Z的影响是展开后最后一条作用的结果,但如果总指令(就是你程序中写的那条虚拟指令)是算术指令,那么能正确设置cv nz, 如果是逻辑指令,那么N.z是正确的,V不影响,C不可靠7.不支持除nop之外的其它伪指令(ADR,ADRL,LDR)8.不支持BX和BLX指令9.LDM和STM指令的寄存器列表只允许物理寄存器,不能用变量和表达式10.逗号表达式要用一个括号扩起来,使其为一个整体add x,y,(f(),z)11.不要干预堆栈当然还有更复杂的规则,比如子程序调用(BL指令),但我觉得过于繁琐,失去了在线汇编这种简便快捷的风格,如果以上介绍的不能满足你的要求,我建议使用A TPCS规则。