||
好久没来21IC了,突然发现这里还有自己的一亩三分地,呵呵,可惜已经荒芜的太久了。
前阵在中国电子论坛上应朋友之邀讨论了下混合编程的问题,今天挪到这里引引砖头吧。
环境:keil, C8051
1、直接嵌套
在C程序中嵌套ASM语句.一般来说我很少这样用,但有时考虑到执行速率及执行频率较高,直接对ACC,DPTR之类操作的时候,感觉还是
有一定的优势.但该类操作情况下风险系数较高,要充分考虑编译器对相应资源的占用情况.其常用格式如下:
*---------------------------------------------------------
*1、#pragma asm/endasm:
*---------------------------------------------------------
* 可以用#pragma asm 和 #pragma endasm 预处理指示器来在你的C语言程序中插入汇编指令。
* 将此源文件加入要编译的工程文件,
* 将光标指向此文件,选择右键菜单“option for file 'asm.c'”,
* 将属性单“properties”中的“Generate Assembler SRC File”“Assemble SRC File”
* 两项设置成黑体的“√”将“Link Public Only”的“√”去掉,再编译即可。
* 用此方法可以在c源代码的任意位置用#pragma asm和#pragma endasm嵌入汇编语句。
* 但要注意的是在直接使用形参时要小心,在不同的优化级别下产生的汇编代码有所不同,
* 可以察看对应的.lst文件看一看,得到正确的优化级别后,#pragma OT(x,speed)锁定
* 优化级别(这里的值是0-9)。
2、C中调用汇编函数
其次是我们常说的模块调用的问题了,其实跟C中函数调用无太大区别,不要被编译器自己编译的一大堆???PR,CO??之类的迷惑,关于这类问题可以先放一边.
注意:
* 1、指定代码及数据段(segment)
* 2、声明外部变量及相关定义(extrn)
* 3、带参数函数调用先对参数进行声明(?fun_name?parameter_byte)
* 汇编与C中实现数据传输可通过两种方式:
* 1、利用工作寄存器进行数据传送,这种方式安全,但根据传送数据的类型不同,只能传送1--3个参数。
*
* 利用寄存器传递参数的规则
* 参数数量 char int long,float 一般指针
* 1个参数 R7 R6,R7 R4--R7 R1,R2,R3 ;R6--high
* 2个参数 R5 R4,R5 R4--R7 R1,R2,R3 ;R4--high
* 3个参数 R3 R2,R3 ------ R1,R2,R3
* func1(int a):"a"在R6/R7中传递
* func2(int b, int c, int *d):"b"和"c"分别在R6/R7,R4/R5中传递,"d"在R1/R2/R3中传递
* func3(long e,long f):"e"在R4/R5/R6/R7中传递,"f"在参数段中传递
*
* 2、指定特定的数据区(存在危险性)
CASE:
asm模块定义:
;=========================================================
; 文件名: asm_MATH_module.asm
;=========================================================
#include "c8051F120.inc"
NAME asm_MATH_module ;函数名声明
;---------------------------------------------------------
extrn data (now_addr ) ;外部变量声明
extrn data (Col_Point)
extrn data (Rel_Point)
extrn bit (b_row )
extrn bit (b_idel )
public asm_Character_Find ;函数声明
;--------------------------------------------------
;代码及内存分配段声明
asm_MATH_rountines segment code ;函数代码段声名
;;========================================================
;代码段定义:占用CODE断
rseg asm_MATH_rountines ;函数代码段声名
;========================================================
asm_Character_Find:
nop
ret
end
2\函数调用
alien void asm_Character_Find(void); //外部声明
main()
{
asm_Character_Find();
}
3、关于带参数的场合
NAME ASM_SUB_PRO ;函数名声明
extrn data (xcont) ;外部变量声明
;extrn code (fun_name) ;外部汇编函数声明
public asm_sub
public asm_nop
;--------------------------------------------------
;代码及内存分配段声明
asm_sub_rountines segment code ;函数代码段声名
constvar segment code ;常量代码段声名
datavar segment data ;函数代码段声名
bitvar segment bit ;函数代码段声名
;========================================================
;C中带参数函数调用时:参数声明
fun_parameters segment data
public ?asm_sub?byte ;函数局部变量传送段声明
public ?asm_nop?byte
rseg fun_parameters
?asm_sub?byte:
?asm_nop?byte:
ds 2 ;单字节定义 DS
;========================================================
;代码段定义:占用CODE断
rseg asm_sub_rountines ;函数代码段声名
asm_sub:
mov a,xcont ;外部变量调用
mov a,?asm_sub?byte ;参数处理
mov dptr, #val_array
movc a,@a+dptr ;get a value from array
;mov r6, #0 ;return value hi byte
;mov r7, a ;return value lo byte
;if you return a uchar type value,
;the retruned value in ACC
;if you return a int type value,
;the returned value in R6,R7 reg pair
lcall asm_nop ;汇编内部函数调用
ret
val_array:
db 1,2,3,4,5,6,7,8,9,10
asm_nop:
nop
djnz ?asm_nop?byte,asm_nop
ret
;========================================================
;常量段定义:占用CODE断
rseg constvar
context:db 'test program',00h
;========================================================
;数据段定义:占用RAM断(由DATA,IDATA,XDATA指定)
rseg datavar
dummy: ds 1 ;单字节定义 DS
;========================================================
;位地址定义:占用BIT内存断
rseg bitvar
txtbit: dbit 1
;========================================================
end
alien unsigned char asm_sub(void);
main()
{
asm_sub(4);
}
4、中断场合
在C程序中使用汇编中断,必须在头文件中给予相应的函数中断入口,其次,在C中要防止入口冲突.
首先掉出启动文件,指定对应的中断入口地址,然后就可以着手了
/************************************************************************
* 2006-7-22 17:18
* 汇编语言中断服务程序
*---------------------------------------------------------
* 文件名: ASM_INT_PRO
* C语言和汇编语言混合编程,汇编语言中断源程序
************************************************************************/
NAME ASM_INT_PRO
public asm_int ;interrupt profession
public dummy_int ;dummy_interrupt profession
dummy_int_rountines segment code
asm_int_rountines segment code
;========================================================
;dummy-interrupt response
;========================================================
rseg dummy_int_rountines
dummy_int:
setb TR0
nop
nop
reti
;========================================================
;interrupt response
;========================================================
rseg asm_int_rountines
asm_int: ;interrupt_rountine entry
nop
nop
reti
end
============================================================
先到这吧,在外漂了几年了,人也变的浮躁了。坐不住,静不下来了。
还是怀念读大学的时光,至少那时能让自己静下来。但现在。。。难啊。
曾经想重温下校园生涯,蒙头蒙脑又跑回去呆了三年,才发觉一切都变了,一切是
那么让人陌生与恍然。。。
三年后又蒙头蒙脑的跑了出来,又发觉一切也变了。。。
有时总在纳闷,到底是世界变化太快,还是我自己跟不上呢。。。