KEIL 程序定位
用Keil做51的开发也4年多了,代码量基本上维持在5~10K左右,说大不大,说小也不小,也就是个中等货色。这段期间工作上难得有稍许的空间,潜心研究了一下keil中如何在 CODE中定位C程序的方法。
在汇编中数据段和程序段都比较容易定位,例如程序1:
cseg at 0x0000
ljmp main
dseg at 0x20
iseg at 0xC0
xseg at 0x0010
cseg at 0x1000
main:
sjmp main
END
这段代码就把main定位到0x1000的位置。aa 定位在data(0x20)中,bb定位在idata(0xc0)中,CC定位到xdata(0x0010)当然,cc在不超过256字节的时候还可以用 page方式访问。
在C语言程序里面定位比较复杂。
常见的数组定位有如下几个方式:
1、使用 _at_ ,例如程序2:
#include <reg51.h>
unsigned ] _at_ 0x20; //在data段中0x20开始的地方定义一个20字节的数组
unsigned ] _at_ 0x80; //在idata段中0x80开始的地方定义一个20字节的数组
unsigned ] _at_ 0x0000; //在pdata段中0x00开始的地方定义一个20字节的数组
unsigned ] _at_ 0x0100; //在xdata段中0x0100开始的地方定义一个20字节的数组
void main()
{
sysTemp_aa[] = 0x55;
sysTemp_bb[] = 0x55;
sysTemp_cc[] = 0x55;
sysTemp_dd[] = 0x55;
)
{
;
}
}
编译后生成的汇编代码如下:
C:0x0000 020015 LJMP C:0015
11: void main()
12: {
13: sysTemp_aa[0] = 0x55;
C:0x0003 752055 MOV sysTemp_aa(0x20),#0x55
14: sysTemp_bb[0] = 0x55;
C:0x0006 7880 MOV R0,#sysTemp_bb(0x80)
C:0x0008 7655 MOV @R0,#0x55
15: sysTemp_cc[0] = 0x55;
C:0x000A 7800 MOV R0,#sysTemp_cc(0x00)
C:0x000C 7455 MOV A,#0x55
C:0x000E F2 MOVX @R0,A
16: sysTemp_dd[0] = 0x55;
17:
C:0x000F 900100 MOV DPTR,#sysTemp_dd(0x0100)
C:0x0012 F0 MOVX @DPTR,A
18: while(1)
C:0x0013 80FE SJMP C:0013
C:0x0015 787F MOV R0,#0x7F
C:0x0017 E4 CLR A
C:0x0018 F6 MOV @R0,A
C:0x0019 D8FD DJNZ R0,C:0018
C:0x001B 758193 MOV SP(0x81),#0x93
C:0x001E 020003 LJMP main(C:0003)
请注意加横线的是汇编代码对应的C程序。
函数定位
更深入一 点,如果我想把main函数定位呢?上面的汇编代码是由keil自动定位的一个地址,添加或者删除程序后,main的地址是不确定的,能否在也使用 _at_呢?答案是否定的。要想把程序段绝对定位需要在keil里面采用一定的设置。例如程序3:
#include <reg51.h>
unsigned ] _at_ 0x20;
unsigned ] _at_ 0x80;
unsigned ] _at_ 0x0000;
unsigned ] _at_ 0x0100;
extern void test1();
void main()
{
sysTemp_aa[] = 0x55;
sysTemp_bb[] = 0x55;
sysTemp_cc[] = 0x55;
sysTemp_dd[] = 0x55;
)
{
test1();
}
}
void test1()
{
unsigned char i;
;i<;i++)
{
;
}
}
我想把main函数定位到0x1000开始的地放,test1定位到0x2000开始的地方,怎么设置呢?点击“project”->”option for target ..."弹出如下窗口:
选择BL51 MISC,在Misc controls的框中填入code (?PR?MAIN?TEST (0x1000),?PR?TEST1?TEST (0x2000))。这里我解释一下,
code 表示程序段
?PR?各位可参考一下keil的帮助文件
?PR? 表示program 意思是 Executable program code(可执行程序段)
MAIN 和 TEST1 就是你要定位的程序名称
?TEST是main和test1所在的文件名,我这里只是示例一下,命名不是很明确,在实际应用中需要看情况而定。
好,我们编译一下,看看实际的效果。
再看看test1汇编程序
o(∩_∩)o...,正如自己所期望的那样,main和test1均定位到了所需的地址。下班了,明天再来更深入的介绍。
如何定位整个文件,和keil创建工程文件中的group。
继续昨天讲解的如何定位子程序的话题。当程序变大,子程序很多,我想把整个文件定位到一个固定地址怎么办呢?难不成每一个文件都在BL51 MISC中设置吗?那手脖子都累掉了,有那功夫还不如仔细研究研究keil的帮助文件,看看它里面是如何说明的。我仔细研究了一下keil的帮助文件,发现文件定位的方式有如下3种,且听我一一道来:
方法1:这是最基本的方法,和昨天定位子程序的方法差不多,示例代码如下:
//test.c
#include <reg51.h>
unsigned ] _at_ 0x20;
unsigned ] _at_ 0x80;
unsigned ] _at_ 0x0000;
unsigned ] _at_ 0x0100;
extern void test1();
extern void test2();
void main()
{
sysTemp_aa[] = 0x55;
sysTemp_bb[] = 0x55;
sysTemp_cc[] = 0x55;
sysTemp_dd[] = 0x55;
)
{
test1();
test2();
}
}
void test1()
{
unsigned char i;
;i<;i++)
{
;
}
}
void test2()
{
unsigned char i;
;i<;i++)
{
;
}
}
现在我想把整个test.c的程序定位到0x1200开始的地方,还使用昨天的那个方法,点击“project”->”option for target ..."弹出如下窗口:
在Misc controls中填入code(?PR?*?TEST (0x1200)),什么意思呢,就是test文件中所有的程序就定位到0x1200,呵呵,和昨天子程序定位相似吧,用一个*字符代替了所有的子程序名称。好看一下实际的结果。
MAIN函数已经定位到了0x1200了,再看下面两个调用的函数test1和test2分别定位到了0x1218和0x121f,完全符合要求。如果想定位其他文件怎么办?假设现在有一个test2.c文件我想把test2定位到0x2200开始的地方,只要稍微修改一下 code(?PR?*?TEST (0x1200),?PR?*?TEST2(0x2200)), 各位看官是否注意到那个逗号',',用‘,’把各个文件隔开。实际效果请自行实践,我就不再 一一列举。
方法2:使用USERCLASS。USERCLASS官方解释是The USERCLASS directive assigns a user defined class name to a compiler generated segment. By default, the C51 Compiler uses the basic class name for segment definitions.呵呵我的E文不是很好,只能看懂个大概,各位自己理解吧,想了解更多请参考keil的帮助文件。
不在废话了,进入正题。首先定义USRCLASS,不过第一步要设置一下编译器,点击“project”->”option for target ..."弹出如下窗口:勾选LX51和AX51,其实AX51不是必须的,本帖只是讲C的定位,汇编程序不谈。
选择好了以后选择“LX51 Locate",如图:
在"User classes"中填写" CODE_TEST (C:0x1500 - C:0x2000)",如果你对程序的大小不确定那么只要写一个" CODE_TEST (C:0x1500 )"就可以,其他的交给KEIL自动分配。点击”确定“回到程序编辑区,在程序添加如下代码:
#pragma userclass (code = test) //code的含义应该不用我说吧
使用#pragma参数,在文件头部定位整个文件,刚刚填写的(CODE_TEST ...)到了程序中就需要写 code = test,为什么这么写,我也不知道keil的规定。总结了一下,比如说我再定一个userClass,名称为 CODE_TEST1(C:0x2000),那么到了程序中我就要这么写:
#pragma userclass (code = test1)
引申一下,同理可以使用userclass来限制一个文件使用的RAM区域,稍许修改一下那个CODE,怎么改各位参照KEIL帮助文档自己思考。实际修改后的源码:
//test.c
#include <reg51.h>
#pragma userclass (code = test)
unsigned ] _at_ 0x20;
unsigned ] _at_ 0x80;
unsigned ] _at_ 0x0000;
unsigned ] _at_ 0x0100;
extern void test1();
extern void test2();
void main()
{
sysTemp_aa[] = 0x55;
sysTemp_bb[] = 0x55;
sysTemp_cc[] = 0x55;
sysTemp_dd[] = 0x55;
)
{
test1();
test2();
}
}
void test1()
{
unsigned char i;
;i<;i++)
{
;
}
}
void test2()
{
unsigned char i;
;i<;i++)
{
;
}
}
看看实际的效果:
main、test1和test2都已经定位到了1500开始的地方。
方法3:和方法2差不多,也是使用userclass不过方法稍许有点差别,同样定义一个userclass
回到程序编辑区,右键test.c选择”Option for file test.c",弹出如下窗口:
在Misc Controls中填写:userclass (code = test),确定后回到程序编辑区。此时test.c文件的图标会有一个变化,如图:
编译源程序:
//test.c
#include <reg51.h>
unsigned ] _at_ 0x20;
unsigned ] _at_ 0x80;
unsigned ] _at_ 0x0000;
unsigned ] _at_ 0x0100;
extern void test1();
extern void test2();
void main()
{
sysTemp_aa[] = 0x55;
sysTemp_bb[] = 0x55;
sysTemp_cc[] = 0x55;
sysTemp_dd[] = 0x55;
)
{
test1();
test2();
}
}
void test1()
{
unsigned char i;
;i<;i++)
{
;
}
}
void test2()
{
unsigned char i;
;i<;i++)
{
;
}
}
调试一下,看看结果是否和方法二相同?结果我就不展示了。
篇幅太长,GROUP定位的下一篇再介绍吧!
GROUP定位的方法和文件定位的方法3类似,详情各位请等我整理上来。
KEIL 程序定位的更多相关文章
- keil程序在外部RAM中调试的问题总结(个人的一点经验总结)
keil程序在内部RAM调试的基本步骤网上已经有非常多了,我就不再赘述,大家能够在网上搜到非常多. 可是有些时候内部RAM并不够用,这就须要将程序装入外部RAM中调试,而在这个过程中可能会出现各种各样 ...
- 微信小程序 - 定位功能
(1) 查看微信小程序文档 大家可以从我截图中可以看到,API中的返回值有纬度和经度,所以我们接下来就是要用到纬度和经度逆地址解析出地址的一些信息. (2)注册腾讯地图开放平台 注册完之后选择WebS ...
- Keil 程序调试窗口
上一讲中我们学习了几种常用的程序调试方法,这一讲中将介绍Keil提供各种窗口如输出窗口.观察窗口.存储器窗口.反汇编窗口.串行窗口等的用途,以及这些窗口的使用方法,并通过实例介绍这些窗口在调试中的使用 ...
- 谈谈在keil下的代码定位
关于C语言,我们一般都知道对于RAM定位可以用关键字 _at_,但对于程序代码定位往往感到很迷惑, 其实keil中的程序代码定位功能极为强大 Menu: Options for Target 'Tar ...
- 如何通过Keil将程序正确的下载进flash中
前面介绍了一些创建工程和调试的基本步骤,在这里准备介绍一下如何正确的将Keil程序在仿真调试中下载到flash.这里再次涉及到了debug的窗口. 工具/原料 Keil uVision 4/5 ...
- tiny4412 裸机程序 八、重定位到DRAM及LCD实验【转】
本文转载自:http://blog.csdn.net/eshing/article/details/37407423 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] 一 ...
- dll文件:关于MFC程序不能定位输入点
问题:无法定位程序输入点到动态链接库上...... 过程:找完整个工程文件夹: APS为资源文件: resource.h为定义文件: 完全复制 除主文件以外的所有文件,程序可用: 在主程序框Cpp文件 ...
- keil教程
KEIL C51标准C编译器为8051微控制器的软件开发提供了C语言环境,但是界面是英文的好多初学者看很多教程都是一头雾水,这个相对简单的教程.KEIL C51编译器的功能不断增强,使你可以更加贴近C ...
- 微信小程序的应用及信息整合,都放到这里了
微信小程序终于开始公测了,这篇文章也终于可以发布了. 这篇文章可以说是微信小程序系列三部曲最后一篇.8 月份,小程序推出前,我写了<别开发 app 了>详细阐述了为什么创业应该放弃原生 a ...
随机推荐
- 【转】Android 定时器实现的几种方式和removeCallbacks失效问题详解--不错
原文网址:http://blog.csdn.net/xiaanming/article/details/9011193 实现定时器有很多种方式,在这里我简单的介绍几种方式 (1)使用Handler + ...
- 【转】android service 之二(IntentService)
原文网址:http://rainbow702.iteye.com/blog/1143286 不管是何种Service,它默认都是在应用程序的主线程(亦即UI线程)中运行的.所以,如果你的Service ...
- paip.hadoop的应用研究总结
paip.hadoop的应用研究总结 作者Attilax , EMAIL:1466519819@qq.com 来源:attilax的专栏 地址:http://blog.csdn.net/attil ...
- 浅谈c语言代码段 数据段 bss段
代码段.数据段.bss段 (1)编译器在编译程序的时候,将程序中的所有的元素分成了一些组成部分,各部分构成一个段,所以说段是可执行程序的组成部分. (2)代码段:代码段就是程序中的可执行部分,直观理解 ...
- Day56
今天干啦啥呢 早上七点起来 天气冷了真起不来啊 再坚持坚持就好了 今天上午九点开始考数据库 我去 大学四年第一次感觉到这样的爽 作弊的爽啊 也没有完全的作弊啦 是开卷考试,反正做的很顺利了. 我和胡 ...
- C#使用WebKitBrowser.dll填坑记
.Net 自带的 Webbrowser 有着太多的平台限制.对于用户体验之上的今天,这无疑是一个噩梦, 然后就开始找 .Net下的WebKitBrowser.dll (后面提供下载) 从开源网站下到程 ...
- Django之Cookie与Session
一.cookie 1.cookie使用 def cookie(request): print(request.COOKIES) # 获取所有的COOKIES obj = render(request, ...
- c++ 依据输入动态声明数组(一维,二维)
较早的编译器是不同意这样做的,所以一些书籍比方以Tc解说的书本都说数组的下标不能是变量.在vc6.0下亦是如此. 只是在一些较新的编译器如dev c++已经支持了,例如以下代码不会报错 #includ ...
- tomcat线程数查看
获取tomcat进程pid ps -ef|grep tomcat 统计该tomcat进程内的线程个数 ps -Lf 29295 |wc -l
- vsftp虚拟用户登录配置详解
一.安装:1.安装Vsftpd服务:# yum install vsftpd 2.安装DB4部件包:这里要特别安装一个db4的包,用来支持文件数据库.# yum install db4-utils 二 ...