keilC语⾔与汇编语⾔混合编程
keil C语⾔与汇编语⾔混合编程
1. C语⾔中嵌⼊汇编
1、在 C ⽂件中要嵌⼊汇编代码⽚以如下⽅式加⼊汇编代码:
#pragma ASM
; Assembler Code Here
#pragma ENDASM
2、在 Project 窗⼝中包含汇编代码的 C ⽂件上右键,选择“Options for ...”,点击右边的“Generate Assembler SRC File”
和“Assemble SRC File”,使检查框由灰⾊变成⿊⾊(有效)状态;
3、根据选择的编译模式,把相应的库⽂件(如 Small 模式时,是 Keil/C51/Lib/C51S.Lib)加⼊⼯程中, 该⽂件必须作为⼯程的最后⽂件;
4、编译,即可⽣成⽬标代码。
来个实例吧:
#i nclude <reg51.h>
void main(void)
{
P2=1;
#pragma asm
MOV R7,#10
DEL:MOV R6,#20
DJNZ R6,$
DJNZ R7,DELc语言中文网汇编语言
#pragma endasm
P2=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,#10
DEL:
MOV R6,#20
DJNZ R6,$
DJNZ R7,DEL
RET
END
在example.c⽂件中,先声明外部函数,然后直接在main中调⽤即可。
在example.a51中,
PRDELAY100 SEGMENT CODE;        作⽤是在程序存储区中定义段,DELAY100为段名,PR表⽰段位于程序存储区内
PUBLIC DELAY100;          作⽤是声明函数为公共函数
RSEG ?PR?DELAY100;          表⽰函数可被连接器放置在任何地⽅,RSEG是段名的属性
段名的开头为PR,是为了和C51内部命名转换兼容,命名转换规律如下:
CODE -?PR?
XDATA-?XD
DATA-?DT
BIT-?BI
PDATA-?PD
3. 有参数传递的函数调⽤
记住哦,c⽂件和A51⽂件不能使⽤同⼀个⽂件名,不过我还不知道为什么会这样,有⾼⼿知道得话请告知。
今天说说带参数传递的函数调⽤,在C51和汇编之间传递参数的⽅式有两种,⼀种是通过寄存器传递参数,C51中不同类型的实参会存⼊相应的寄存器,在汇编中只需对相应寄存器进⾏操作,即达到传递参数的⽬的。
不同类型的数据及其传递参数的寄存器如下表所⽰:
 在C和汇编混合编程的时候存在C语⾔和汇编语⾔的变量以及函数的接⼝问题。
在C程序中定义的变量,编译为.asm⽂件后,都被放进了.bss区,⽽且变量名的前⾯都带了⼀个下划线。在C程序中定义的函数,编译后在函数名前也带了⼀个下划线。例如:
extern int num就会变成 .bss _num, 1
extern float nums[5]就会变成.bss _nums, 5
extern void func ( )就会变成 _func,
⼀  汇编和C的相互调⽤可以分以下⼏种情况:
(1) 汇编程序中访问c程序中的变量和函数。
在汇编程序中,⽤_XX就可以访问C中的变量XX了。访问数组时,可以⽤_XX+偏移量来访问,如_XX+3访问了数组中的XX[3]。
在汇编程序调⽤C函数时,如果没有参数传递,直接⽤_funcname 就可以了。如果有参数传递, 则函数中最左边的⼀个参数由寄存器A给出,其他的参数按顺序由堆栈给出。返回值是返回到A寄存器或者由A寄存器给出的地址。同时注意,为了能够让汇编语⾔ 能访问到C 语⾔中定义的变量和函数,他们必须声明为外部变量,即加extern 前缀。
(2) c程序中访问汇编程序中的变量
如果需要在c程序中访问汇编程序中的变量,则汇编程序中的变量名必须以下划线为⾸字符,并⽤global使之成为全局变量。
如果需要在c程序中调⽤汇编程序中的过程,则过程名必须以下划线为⾸字符,并且,要根据c程序编
译时使⽤的模式是stack-based model还是register argument model来正确地编写该过程,使之能正确地取得调⽤参数。
(3) 在线汇编
在C程序中直接插⼊ asm(“ *** ”),内嵌汇编语句需要注意的是这种⽤法要慎⽤,在线汇编提供了能直接读写硬件的能⼒,如读写中断控制允许寄存器等,但编译器并不检查和分析在线汇编语⾔,插⼊在线汇编语⾔改变汇编环境或可能改变C变量的值可能导致严重的错误。
⼆ 汇编和C接⼝中寻址⽅式的改变:
需 要注意的是,在C语⾔中,对于局部变量的建⽴和访问,是通过堆栈实现的,它的寻址是通过堆栈寄存器SP实现的。⽽在汇编语⾔中,为了使程序代码变得更为精 简,TI在直接寻址⽅式中,地址的低7位直接包含在指令中,这低7位所能寻址的具体位置可由DP寄存器或SP寄存器决定。具体实现可通过设置ST1寄存器 的CPL位实现,CPL=0,DP寻址,CPL=1,SP寻址。在DP寻址的时候,由DP提供⾼9位地址,与低7位组成16位地址;在SP寻址的时候, 16位地址是由SP(16位)与低7位直接相加得来。
由于在C语⾔的环境下,局部变量的寻址必须通过SP寄存器实现,在混合编程的时候,为了使汇编语
⾔不影响堆栈寄存器SP,通常的⽅式是在汇编环境中使⽤DP⽅式寻址,这样可以使⼆者互不⼲扰。编程中只要注意对CPL位正确设置即可
1 .word 的意思就相当与C语⾔⾥的int,char等定义⼀个变两的宽度
2. 编译错误原因有2:
a.如果在汇编⾥⾯定义.global(全局符号),那么在C语⾔⾥⾯应该⽤extern声明,以引⽤该符号。
b.在汇编⾥⾯声明的时候,符号前应加下划线,如 FIQ_Addr: .word EXTint_FIQ 应为: FIQ_Addr: .word _EXTint_FIQ 在C语⾔⾥⾯应⽤extern声明。 另外,⼀中⽅法是,⽤.ref 代替.global 来声明符号,这样就不⽤在C源程序⾥⾯⽤extern声明了。 两种⽅法结果相同。 我讲的是⽤C和汇编混编程⽤法,⾄于C++变量如何翻译成汇编符号可以⽤仿真器,⾃⼰去看,原则类似.

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。