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 ...
随机推荐
- DDUI For Delphi Seattle Directui界面组件
http://www.delphigear.cn/0/11258/go.aspx http://bbs.csdn.net/topics/390285613
- 在WPF中使用AForge.net控制摄像头拍照
原文:在WPF中使用AForge.net控制摄像头拍照 利用AForge.net控制摄像头拍照最方便的方法就是利用PictureBox显示摄像头画面,但在WPF中不能直接使用PictureBox.必须 ...
- 2015第23周四HTML特殊字符显示问题
1.项目中常采用EL表达式来输出后台内容,但测试发现它并不能完美处理要输出内容包含有<>或&等HTML特殊字符问题.先直接给出此问题JSTL的解决方案: 1.引入标签:<%@ ...
- Ext.window的close的问题
以前每次都是用的hide,关闭后隐藏窗体,下一次点击再打开,这种方法在我的随笔里面有,可是现在遇到一个问题,我的窗体里面有个formpanel,formpanel每一项都有一个默认值,意思就是修改的时 ...
- centerOS安装chkrootkit
Chkrootkit是一个在本地系统检查rootkit痕迹的工具,它是检查系统二进制文件是否被rootkit病毒修改的一个shell脚本. (1)centerOS安装chkrootkit 安装gcc编 ...
- python数据类型—列表(增改删查,统计,取值,排序)
列表是最常用的数据类型之一,通过列表可以对数据实现方便的存储,修改等操作. 先声明一个空列表: >>> names = [] >>> names [] 可以存多个值 ...
- FileZilla简单介绍及运用
一.FileZilla简介 FileZilla是一款免费开源的FTP客户端软件,并且还提供了服务器版本.虽然它是免费软件,可性能却一点也不含糊,比起那些共享软件来有过之而无不及,具备大多数的FTP软件 ...
- vb将窗体中的控件或某种颜色透明
Option Explicit ' ******************** 窗体透明 ******************** '***Module.bas '**** Public Declare ...
- silverlight 生成图表 WCF 解析XML代码.svc.cs 文件
silverlight 调用wcf 文件代码 private ListItem AnalyzeXML(string XMLCode, string Reportdate, string ChartNa ...
- mysql查询分组归类函数-group_concat,通常与group_by一起使用
select a.`name`,group_concat(b.name SEPARATOR'.') as persons from `group` as a,`person` as b,`person ...