keil c语言嵌入汇编实例,KEIL编程_C语言嵌入汇编.pdf

keil 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 加入工程中 该文件必须作为工程的最后文件 在默认 安装盘 KEIL C51 LIB C51S Lib 4 编译 即可生成目标代码 来个实例吧 include define uchar unsigned char sbit LED1 P1 0 C 嵌入汇编例程 void delay ms void pragma asm MOVR0 0FFH MOVR1 0FFH D LOOP1 DJNZR0 D LOOP1 MOVR0 0FFH DJNZR1 D LOOP1 pragma endasm void main void uchar i P1 0 xFF while 1 i delay ms if i 7 LED1 LED1 i 0 2 无参数传递的函数调用 C51调用汇编函数 1 无参数传递的函数调用 先来个例子 其中 C ASM c 和 DELAY a 为项目中的两个文件 C ASM c include define uchar unsigned char extern void delay100 sbit LED1 P1 1 C 嵌入汇编例程 void main void uchar i P1 0 xFF while 1 i delay100 if i 7 LED1 LED1 i 0 DELAY100 a PR DELAY100 SEGMENT CODE 在程序存储区中定义段 PUBLIC DELAY100 声明函数 RSEG PR DELAY100 函数可被连接器放置在任何地方 DELAY100 MOVR0 0FFH MOVR1 0FFH D LOOP1 DJNZR0 D LOOP1 MOVR0 0FFH DJNZR1 D LOOP1 RET END 在 C ASM c 文件中 先声明外部函数 然后直接在 main 中调用即可 在 DELAY100 a 中 PR DELAY100 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 变量如何翻译成汇编符号可以用仿真器 自己去看 原则类似 汇编与 C 语言混合编程的关键问题 1 C 程序变量与汇编程序变量的共用 为了使程序更易于接口和维护 可以在汇编程序中引用与 C 程序共享的变量 ref to dce num to dte num to dce buff to dte buff 在汇编程序中引用而在 C 程序可直接定义的变量 unsigned char to dte buff BUFF SIZE DSP 发向 PC 机的数据 int to dte num 缓冲区中存放的有效字节数 int to dte store 缓冲区的存放指针 int to dte read 缓冲区的读取指针 这样经过链接就可以完成对应 2 程序入口问题 在 C 程序中 程序的入口是 main 函数 而在汇编程序中其入口由 cmd 文件 中的命令决定 如 e main start 程序入口地址为 main start 这样 混 合汇编出来的程序得不到正确结果 因为 C 到 ASM 的汇编有默认的入口 c int00 从这开始的一段程序为 C 程序的运行做准备工作 这些工作包括初始化变量 设 置栈指针等 相当于系统壳不能跨越 这时可在 cmd 文件中去掉语句 e main start 如仍想执行某些汇编程序 可以 C 函数的形式执行 如 main start 其中含有其他汇编程序 但前提是在汇编程序中把 main start 作为首地址 程序以 rete 结尾 作为可 调用的函数 的程序段 并在汇编程序中引用 main start 即 ref main start 3 移位问题 在 C 语言中把变量设为 char 型时 它是8位的 但在 DSP 汇编中此变量仍被作 为16位处理 所以会出现在 C 程序中的移位结果与汇编程序移位结果不同的问 题 解决的办法是在 C 程序中 把移位结果再用0X00FF 去 与 一下即可 4 堆栈问题 在汇编程序中对堆栈的依赖很小 但在 C 程序中分配局部变量 变量初始化 传递函数变量 保存函数返回地址 保护临时结果功能都是靠堆栈完成 而 C 编译器无法检查程序运行时堆栈能否溢出 5 程序跑飞问题 编译后的 C 程序跑飞一般是对不存在的存储区访问造成的 首先要查 MAP 文件 与 memory map 图对比 看是否超出范围 如果在有中断的程序中跑飞 应重点 查在中断程序中是否对所用到的寄存器进行了压栈保护 如果在中断程序中调用 了 C 程序 则要查汇编后的 C 程序中是否用到了没有被保护的寄存器并提供保护 在 C 程序的编译中是不对 A B 等寄存器进行保护的

展开阅读全文

你可能感兴趣的:(keil,c语言嵌入汇编实例)