MDK中函数绝对地址定位

合集下载

STC单片机Keil中C语言函数定位的方法

STC单片机Keil中C语言函数定位的方法

STC单片机Keil中C语言函数定位的方法
下面以演示程序进行说明
演示程序中有ReadIAP、ProgramIAP和EraseIAP三个函数
最终目的是将这三个函数都定位到0x8000之后
第一步:新建一个项目“Demo”,并将源文件“Demo.C”添加到项目中
第二步:直接编译,并打开编译后生成的“Demo.M51”文件
从M51文件的“CODE MEMORY”信息中,可以看到3个函数的链接名称、链接地址和函数长度ReadIAP的链接名称为“?PR?_READIAP?DEMO”,链接地址为“0003H”,长度为16H字节ProgramIAP的链接名称为“?PR?_PROGRAMIAP?DEMO”,链接地址为“0019H”,长度为16H字节EraseIAP的链接名称为“?PR?_ERASEIAP?DEMO”,链接地址为“0044H”,长度为14H字节
第三步:根据M51中函数的长度信息计算出各个函数重定位的地址,ReadIAP的重定位的地址为0x8000
ProgramIAP的重定位的地址为0x8016
EraseIAP的重定位的地址为0x802C
第四步:打开项目选项中的“BL51 Locate”属性页
在上图的“Code”域中输入下列语句
“?PR?_READIAP?DEMO(0x8000), ?PR?_PROGRAMIAP?DEMO(0x8016), ?PR?_ERASEIAP?DEMO(0x802C)”
第五步:点击确定按钮,并重新编译即可,此时可以重新打开“Demo.M51”文件,便可发现3个函数已被重定位到我们所指定的地址了,如下图。

如何将函数和变量定义到指定位置

如何将函数和变量定义到指定位置

嵌入式编程第一篇:51单片机如何将函数定义到指定程序地址在单片机编程使用中,会涉及到将某些函数定义到指定的code区。

此时需要对工程文件进行配置修改才可完成。

本期针对单片机平台做出说明介绍1、测试目标将函数testaddr定义到0x6000地址2、测试环境LKT4106加密芯片算法工程、KEIL-C51编译软件、3、实现步骤3.1 使用KEIL软件导入LKT4106算法工程(KEIL软件基本操作不再敷述,如不清楚请自行百度)3.2 在App_Main.c文件中声明测试函数testaddr:extern void testaddr(u8 xdata *in,u8 xdata *out,u8 len);3.3 在App_fun.c文件中实现测试函数testaddr:void testaddr(u8 xdata *in,u8 xdata *out,u8 len){u8 i;for(i=0;i < len;i++)out[i]= in[i]+1;}3.4 在App_Main.c文件中调用测试函数testaddr,此处省略3.5 编译算法工程后,在\LKT4106_AppDemo\Out\Bin\路径下找到LKT4106_AppDemo.M51,打开该文件。

3.6 找到* * C O D E M E M O R Y * * 部分,寻找到testaddr编译后存储的地址,注意:根据编译规则,testaddr函数会转换为大写格式,并加上函数所在文件的名称。

本例中,编译后的默认地址如图1所示。

图1. 默认编译链接地址3.7 回到算法工程,选择Project->Options for Target ...->BL51 Misc,点击Edit按钮调出lin文件,如图2所示图2. 打开lin文件3.8 在LKT4106_App.lin文件中,按照下图所示,将testaddr函数指定到程序区的目标地址,本例将其由默认的0x48B0地址更改到0x6000地址,如图3所示。

MDK(KEIL)中设定变量或数组到指定的位置

MDK(KEIL)中设定变量或数组到指定的位置

MDK(KEIL)中设定变量或数组到指定的位置MDK(KEIL)中设定变量或数组到指定的位置分类:【嵌入式开发】2013-05-20 14:51 239人阅读评论(0) 收藏举报转自zyboy2000定位变量到指定的位置使用定义在头文件absacc.h中的 __at宏,可以将变量以如下方式定位到绝对地址处:C 例子:#include <absacc.h>const char MyText[] __at (0x1F00) = "TEXT AT ADDRESS 0x1F00";int x __at (0x40003000); // variable at address 0x40003000unsigned char xArray[128] __at (0x68000000); // Array start at address 0x68000000汇编例子:在汇编文件中可以使用段名,由|.ARM.__AT_<addr>|组成来定义位置。

下面的例子是将一个段定义到地址0xFFE0处:AREA |.ARM.__AT_0xFFE0|, CODE, READONLYu8 a[10] __attribute__ ((at(0x2000002c)));编译说..\List\ALL.axf: Error: L6971E: Section .data from objectusart.o with type RW incompatible withSection .ARM.__AT_0x2000002C from object hal.o with type ZI in er RW_IRAM1.似乎是定位了这个绝对地址后,其他变量不会为它让位~NONO,这个方法不行的,因为编译器并没有真正开辟一个变量,你仅仅是强行操作某个地址而已,但这个地址是否被其他数据利用了,你管不到也不知道~(0字)电子白菜[8次]2009-9-5 2:08:47编译器里面应该有设置,比如系统总共有多少内存,你可以故意设置的少一些,这样在编译的时候他就会避开你没有指定的了。

stm32分段管理代码

stm32分段管理代码

编译大型的程序时,可能某一段代码固定之后不再改变(比如BSP),而应用部分经常修改。

在这种情况下,如果使用在线升级或是Bootloader的方式升级程序时,你就觉得每次升级的代码有一部分是重复的(BSP),如果把这部分代码固定在一个区里面,升级的时候只选择APP区的代码升级,这样提高效率,也节省时间。

MDK或是早前的ADS提供的分散加载方式对代码分区提供了较好的支持,但是我总觉得代码之外再管理一个文件,会比较费劲。

所以一直在寻找更好的方式。

今天仔细研究了MDK的帮助文档,同时简单尝试了一下,有一点体会。

先和大家一起分享:///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////MDK下有两种方式给函数定位(均在代码中控制):1. 给函数声明__attribute__比如声明函数:void task(void) __attribute((section(".ARM.__at_0x8100000")));这样函数task 会被连接到0x8100000 地址处.不同的函数可以使用同一个地址,链接的时候会自动处理.每个函数都需要声明一次.2. 使用#pagaram 控制如下定义:#pragma arm section code=".ARM.__at_0x8100000"void task(void){}#pragma arm section这样函数task 会被链接到0x8100000 地址.这样做的优点是声明区内的函数都会包含在指定的地址范围内.以上两种方式均在代码文件中实现, 不需要修改分散加载文件, 对代码的分区比较方便.///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////特别注意的是:比如你选择BSP代码固化,一定要保证你的代码的稳定性, 如果经常修改的话,该方法不实用!。

keil中函数变量定位方法

keil中函数变量定位方法

keil中函数变量定位⽅法keil中函数变量定位⽅法(2010-09-14 16:02:58)转载标签:杂谈分类:技术函数绝对定位⽅法:将链接⽅式从LX51改回BL51,然后再BL51 Locate中的Code框中写⼊:PR?_DELAY?DELAY(0x8000)其中,前⾯那个_DELAY是指函数名叫做delay,前⾯为什么要加_还不清楚,⽽且原来⽆论是什么这⾥都是⼤写;后⾯那个DELAY是指⽂件名叫做delay,也就是说这个函数要到delay.c中去找;括号⾥⾯的当然就是要定位到的地址了。

如果不强制定位,连接器⼀般都会把程序从0开始安排,有多⼤安排多⼤。

ouravr⽹友总结(⽐较全):使⽤KeilC51软件,可以很⽅便地将代码或者数据绝对定位到某个地址。

1、代码定位:⽅法1:使⽤伪指令CSEG。

⽐如要将MyFunc1定位到代码区C:0x1000,则新建⼀个A51⽂件,添加以下内容:PUBLIC MYFUNC1CSEG AT 1000HMYFUNC1:;其它代码RET在其它源⽂件中,就可以调⽤MyFunc()函数了。

需要注意的是,编译器不检测传递参数的数⽬,仅检测函数是否有返回值。

⽅法2:使⽤BL51 Locate选项。

⽐如在main.c中定义了⼀个MyFunc2函数,并且要将该函数定位到代码区C:0x2000,则从菜单中选择Project->Options for Target 'Target1',在弹出的对话框中选择BL51 Locate页,在下⾯的code栏中写上?PR?MYFUNC2?MAIN(0x2000)即可。

如果想定位多个函数,也可以使⽤*通配符。

2、变量定位:只有全局变量可以绝对定位,局部变量⽆法实现绝对定位。

⽅法1:使⽤_at_关键字。

声明⼀个全局变量unsigned char data MyBuf1[8] _at_ 0x20;⽅法2:使⽤BL51 Locate选项。

KEIL C51之绝对地址定位详解

KEIL C51之绝对地址定位详解
然后在:
Project->Options for Target ...->BL51 Locate:Xdata
中填入:
?XD?INITVARS(0x200)
再次编译即可。相应地,若定义的是data/idata等变量,则相应处理即可。
3、若有多个变量或函数要进行绝对地址定位,则应按地址从低到高的顺序
使用KeilC51软件,可以很方便地将代码或者数据绝对定位到某个地址。
相应地,如为xdata变量,则InitVars.c中写:
char xdata myVer = {COPYRIGHT 2001-11};
然后将该文件加入工程,编译,打开M51文件,在
* * * X D A T A M E M O R Y * * *
下可找到:
XDATA xxxxH xxxxH UNIT ?XD?INITVARS
KEIL C51之绝对地址定位详解
单片机空间分配看*.M51文件,ARM,DSP空间分配看*.map文件
1、函数定位:
假如要把C源文件tools.c中的函数
int X(int xx)
{
...
}
放在CODEMEMORY的0x1000处,先编译该工程,然后打开该工程的
M51文件,在
* * * C O D E M E M O R Y * * *
行下找出要定位的函数的名称,应该形如:
CODE xxxxH xxxxH UNIT ?PR?_BCD2HEX?TOOLS
然后在:
Project->Options for Target ...->BL51 Locate:Code
中填写如下内容:
?PR?_BCD2HEX?TOOLS(0x1000)

c语言相对路径转绝对路径 -回复

c语言相对路径转绝对路径 -回复

c语言相对路径转绝对路径-回复C语言是一种通用的编程语言,被广泛应用于系统软件开发和嵌入式系统的编程。

在C语言编程中,文件路径是一个重要的概念。

相对路径和绝对路径都可以用来指定文件的位置。

本文将探讨相对路径与绝对路径之间的转换,并提供一步一步的指南。

一、什么是相对路径和绝对路径?在计算机中,文件路径是指文件在文件系统中的位置。

相对路径是从当前工作目录开始寻找文件的路径。

当前工作目录是指执行程序时所在的目录。

相对路径的路径不包含完整的文件系统路径,而是基于当前工作目录的相对位置。

相对路径通常以"../" 或"./"开头,以指示上级目录或当前目录。

例如,假设当前工作目录是一个名为"myproject"的文件夹。

要访问该文件夹中的另一个文件夹中的文件,我们可以使用相对路径"../anotherfolder/file.txt"。

这个路径中的".."表示上级目录。

绝对路径是一个完整的文件系统路径,从根目录开始到文件的路径。

绝对路径可以唯一地指定一个文件的位置,不依赖于当前工作目录。

绝对路径通常以根目录(如"/"或"C:\")开头。

例如,要访问Windows系统中C盘下的文件,可以使用绝对路径"C:\folder\file.txt"。

这个路径中的"C:\"表示C盘根目录。

二、相对路径转绝对路径的方法在C语言中,我们可以使用函数来处理路径,以实现相对路径转绝对路径的功能。

下面是一种实现相对路径转绝对路径的方法:1. 获取当前工作目录C语言提供了函数`getcwd(char *buffer, size_t size)`来获取当前工作目录。

这个函数将当前工作目录的路径存储在`buffer`中,最多存储`size`个字符。

2. 连接相对路径和当前工作目录将相对路径与当前工作目录连接起来,形成一个完整的路径。

C语言绝对地址跳转

C语言绝对地址跳转

C语言使用函数指针跳转到程序固定地址(0x8000)执行程序的方法使用函数指针,把一个纯数据强制转换为函数指针类型。

int main(void){void (* my_function)(void);//int *my_address = 0x8000;my_function = (void (*)()) (0x8000);my_function();}其实更简单,不适用中间变量,直接一步到位:(*(void(*)())0x8000)();转成汇编就占两条指令.在IAP的bootloader中经常使用到地址跳转,指定程序跳转到某一地址运行,例如强制跳转到0x2c去执行,则可使用(*((void(*)(void))0x2c)))();实际上这是运用的函数指针,可以这样分解:1,函数指针的定义为void (* fd) (void); 省略参数的函数原型为void (*)(void).2,0x2c, 这里的0x2c为地址,可以认为是变量(个人理解),可以理解为将变量0x2c进行强制类型转换,转换成函数指针类型,即( void(*)(void) )0x2c.3,调用函数。

(* (func) ) (); func 为函数指针(void(*)(void) )0x2c,合起来就是(* ((void(*)(void) )0x2c) )();嵌入式笔试题:想让程序跳转到绝对地址0x100000处执行,该如何做?网上看到有如下答案:*((void(*)(void))0x100000)();经过在VC++6.0和Linux gcc4.4.3下测试,均不能通过编译。

VC++6.0报错:error C2100: illegal indirectionGCC报错:error: void value not ignored as it ought to be应该是怎么写呢?经过测试,有两种方法:答案1. (*(void(*)(void))0x100000)();答案2. ((void(*)(void))0x100000)();仔细观察,第一种写法只是第一个*的位置不同,第二种写法少了一个*,但是都能正确编译通过,且正确执行。

[MSP430_SN] IAR变量,函数定位方法

[MSP430_SN] IAR变量,函数定位方法

IAR开发环境中的数据、函数定位方法一、在IAR的集成开发环境中实现数据变量定位方法如下三种1、__no_init char alpha @ 0x0200;2、#pragma location = 0x0202const int beta;3、const int gamma @ 0x0204 = 3;或:1)__no_init int alpha @ "MYSEGMENT"; //MYSEGMENT段可在XCL中开辟2)#pragma location="MYSEGMENT"const int beta;3)const int gamma @ "MYSEGMENT" = 3;二、如何实现函数定位在IAR中函数定位有两种写法1. void g(void) @ "MYSEGMENT" // MYSEGMENT段可在XCL中编辑开辟{}2、#pragma location = "MYSEGMENT"void h(void){}三、如何更改XCL文件注意:在实现过程中可能涉及到.XCL连接文件的更改,请保存好原来的.XCL文件!1. 打开相应的*c.xcl文件,用"-Z(CONST)段名=程序定位的目标段-FFDF"定义段的起始地址.2. 在自己的C程序中用#pragma constseg(段名)定位自己的程序3. 结束后恢复编译器的默认定位#pragma default例:IAR 1.26b环境下:1、将常量数组放在FLASH段自定议的MYSEG段中原来的MSP430F149 XCL文件如下:// Constant data-Z(CONST)DATA16_C,DA TA16_ID,DIFUNCT,CHECKSUM=1100-FFDF如果想从中分出一部分做数据存储区,做如下修改:-Z(CONST)DATA16_C,DA TA16_ID,DIFUNCT,CHECKSUM=1500-FFDF //将1100-14FF从ROM中分出存储arry数组-Z(CONST)MYSEG=1100-14FF区间大小可自行决定在程序中描写如下即可:#pragma memory = constseg(MYSEG) //在.XCL文件中修改char arry[]={1,2,3,4,5,6,7};#pragma memory = default2、将变量放入所命名的段在XCL文件中开辟一段MYSEG段,如上所述#pragma memory = dataseg(MYSEG)char i;char j;int k;#pragma memory = default。

嵌入式绝对地址操作

嵌入式绝对地址操作

嵌入式编程里的绝对地址操作要对绝对地址0x100000赋值,我们可以用(unsigned int*)0x100000 = 1234;那么要是想让程序跳转到绝对地址是0x100000去执行,应该怎么做?*((void (*)( ))0x100000 ) ( );首先要将0x100000强制转换成函数指针,即:(void (*)())0x100000然后再调用它:*((void (*)())0x100000)();用typedef可以看得更直观些:typedef void(*)() voidFuncPtr;*((voidFuncPtr)0x100000)();下面是一本关于驱动开发的书上的一段关于绝对地址操作的描述。

目前,大多数嵌入式微控制器如Arm、PowerPC等并不提供I/O空间,而仅存在内存空间。

内存空间可以直接通过地址、指针来访问,程序和程序运行中使用的变量和其他数据都存在于内存空间中。

内存地址可以直接有C语言指针操作,例如在186处理器中执行如下代码:unsigned char *p = (unsigned char*)0xf000ff00;*p = 11;以上程序的意义为在绝对地址0xf000+0xff00(186使用16位段地址和16位偏移地址)写入11。

而在Arm、PowerPC等未采用段地址的处理器中,p指向的内存空间就是0xf000ff00,而*p=11就是在该地址写入11。

再如,186处理器启动后会在绝对地址0xffff0(对应C语言指针是0xf000ff00,0xf000为段地址,0xfff0为段内偏移)执行,请看下面的代码:typedef void (*lpFunction)(); /*定义一个无参数、无返回类型的函数指针类型*/lpFunction lpReset = (lpFunction)0xf000fff0; /*定义一个函数指针,指向CPU启动后所执行第一条指令的位置*/lpReset(); /*函数调用*/在以上程序中,没有定义任何一个函数实体,但是程序中却执行了这样的函数调用:lpReset(),它实际上起到了“软重启”的作用,跳转到CPU 启动后第一条要执行的指令的位置。

C51编程 为变量与函数指定地址

C51编程 为变量与函数指定地址

Keil C51中变量和函数的绝对地址定位问题:1. 变量绝对地址定位1) 在定义变量时使用 _at_ 关键字加上地址就可.e.g.unsigned char idata myvar _at_ 0x40;把变量 myvar 定义在 idata 的 0x40 处, 在 M51 文件中可以找到这麽一行IDATA 0040H 0001H ABSOLUTE表示有变量在 idata 的 0x0040 处绝对地址定位.2) 使用 KeilC 编译器定义绝对地址的变量只有全局变量可以绝对定位,局部变量无法实现绝对定位。

方法1:使用_at_关键字。

声明一个全局变量unsigned char data MyBuf1[8] _at_ 0x20;方法2:使用BL51 Locate选项。

比如将main.c中定义的所有data型的全局变量定位到数据区D:0x28开始的空间,则从菜单中选择Project->Options for Target 'Target1',在弹出的对话框中选择BL51 Locate 页,在下面的data栏中写上?DT?MAIN(0x28)即可。

如果是idata,则使用?ID?MAIN(0x28),如果是xdata,则使用?XD?MAIN(0x28),如果是pdata,则使用?PD?MAIN(0x28)如果是Code,刚在code栏中写?CO?MAIN(0x28)2. 函数绝对地址定位1) 在程序中编写一函数 myTestvoid myTest(void){// Add your code here}2) 使用 KeilC 编译器定位绝对地址的函数, 打开 Project -> Options for Target 菜单,选中 BL51 Locate 选项卡, 在 Code: 中输入:?PR?myTest?MAIN(0x4000)把函数 myTest 定位到程序区的 0x4000 处,再次编译就可以了.3) 一次定位多个函数的方法同样地, 在程序中再编写另外一个函数 myTest1void myTest1(void){// Add your code here}在 Options for Target 菜单的 BL51 Locate 选项卡的 Code: 中输入:?PR?myTest1?MAIN(0x3900), ?PR?myTest?MAIN(0x4000)把函数 myTest1 定位在程序区的 0x3900 处, 把函数 myTest 定义在程序区的 0x4000 处,重新编译就可以了.在 M51 文件中可以找到下面的内容:>> 3.obj TO Reader RAMSIZE (256) CODE (?PR?MYTEST1?MAIN (0X3900), ?PR?MYTEST?MAIN (0X4000))3665H 029BH *** GAP ***CODE 3900H 0014H UNIT ?PR?MYTEST1?MAIN3914H 06ECH *** GAP ***CODE 4000H 0014H UNIT ?PR?MYTEST?MAIN4) 函数的调用:程序中直接调用函数的方式就不说明了, 这里重点讲使用函数指针调用绝对地址处的函数的方法.(1) 定义调用的函数原形typedef void (*CALL_MYTEST)(void);这是一个回调函数的原形, 参数为空.(2) 定义相应的函数指针变量CALL_MYTEST myTestCall = NULL;(3) 函数指针变量赋值, 指向我们定位的绝对地址的函数myTestCall = 0x3900;指向函数 myTest1(4) 函数指针调用if (myTestCall != NULL){myTestCall(); // 调用函数指针处的函数myTest1, 置 PC 指针为 0x3900}检查编译生成的 bin 文件, 到 0x3900 处可以看到 myTest1 的内容, 在0x4000 处可以看到 myTest 的内容,(5) 其它说明:如果在 0x3000 到 0x3900 的程序空间没有内容时, 把 myTestCall的地址指针指到 0x3800(在 0x3000 到 0x3900 之间) 时, 会从 0x3900 处开始执行.至於在 Load 中调用 AP 中的函数的方法与此类似, 但是相应的参数传递可能要另寻方法.************************************keil C51绝对地址访问在利用keil进行8051单片机编程的时,常常需要进行绝对地址进行访问.特别是对硬件操作,如DA AD 采样 ,LCD 液晶操作,打印操作.等等.C51提供了三种访问绝对地址的方法:1. 绝对宏:在程序中,用“#include<absacc.h>”即可使用其中定义的宏来访问绝对地址,包括:CBYTE、XBYTE、PWORD、DBYTE、CWORD、XWORD、PBYTE、DWORD具体使用可看一看absacc.h便知例如:rval=CBYTE[0x0002];指向程序存贮器的0002h地址rval=XWORD [0x0002];指向外RAM的0004h地址2. _at_关键字直接在数据定义后加上_at_ const即可,但是注意:(1)绝对变量不能被初使化;(2)bit型函数及变量不能用_at_指定。

C语言中“_at()”特殊地址定位详解

C语言中“_at()”特殊地址定位详解

C语⾔中“_at()”特殊地址定位详解
C语⾔中 “_at()” 特殊地址定位详解
在keil⾥⾯,有⼀个特殊地址定位的指令,就是将⼀个变量或常量定位到⼀个指定的地址上⾯
指令为 __at ,使⽤⽅法如下
int variable __at(0x8000) = 100;
意为将variable变量定位到0x8000这个地址。

指令的⽬的是告诉链接器将指定地址定位到某个地址⾥⾯,在使⽤该功能的时候需要注意⼀点的是,地址的范围需要符合单⽚机的datasheet给出的地址映射表,
注意,如果地址超出了flash的最⼤范围,程序将⽆法得到这个值,例如⼀个256Kflash的芯⽚,在使⽤功能__at指令的时候,地址就不要超过256*1024了,否则你是找不到这个变量的。

下⾯以MB9AF310系列芯⽚为例,讲⼀下关于芯⽚的flash在内存中的映射,
如图,flash被映射到了0x00000000这个地址上,以0x00100000结束,但是仍然需要看具体芯⽚的flash是多⼤的,这个地址只是310系列芯⽚的地址映射,如果超出了实际的地址,仍然不能找到变量。

keil的链接器最后会把变量放到⽣成⽂件的相应地址中去,在烧录的时候,如果是BIN⽂件,⽂件的字节地址会和flash的地址⼀⼀对应。

⽤户定义的变量将被烧录到相应的flash的物理地址中。

以上都是在没有MMU的情况的关于地址映射的解释,如果启⽤了MMU,情况也许会不⼀样,毕竟多了⼀层虚拟地址,实际上还能不能使⽤__at指令,我也不知道,后续笔者会继续钻研,更多关于__at指令的说明,可以直接在keil的帮助⽂件中找到。

感谢阅读,希望能帮助到⼤家,谢谢⼤家对本站的⽀持!。

c语言 绝对路径和相对路径使用

c语言 绝对路径和相对路径使用

c语言绝对路径和相对路径使用绝对路径和相对路径是在编写程序时经常用到的概念,它们用于指定文件或目录的位置。

下面我将为大家详细介绍绝对路径和相对路径的使用方法、区别以及在实际开发中的指导意义。

首先,我们来了解绝对路径。

绝对路径是指从文件系统的根目录开始,一直到目标文件或目录的完整路径。

在不同的操作系统中,根目录的表示方式是不同的。

在Windows系统中,根目录通常是以盘符(如C、D等)表示,例如"C:\Program Files\Java";而在Unix或Linux系统中,根目录用斜杠“/”表示,例如"/home/user/Documents"。

使用绝对路径可以确切地指定文件或目录的位置,不会受到当前工作目录的影响。

接下来,让我们了解相对路径。

相对路径是相对于当前工作目录来指定文件或目录的位置。

当前工作目录是指在运行程序时所处的目录。

相对路径可以简化文件或目录的路径表示,使得代码更加易读、易于维护。

相对路径可以包括两个符号:点(.)和点点(..)。

点表示当前目录,点点表示上一级目录。

例如,如果当前工作目录是"C:\Users\Jason",而我们需要访问"C:\Users\Jason\Documents\file.txt",则可以使用相对路径"Documents\file.txt"。

绝对路径和相对路径在使用上有着一些区别。

首先,绝对路径是一个完整的文件或目录路径,不受当前工作目录的影响。

而相对路径则是相对于当前工作目录的路径,可以简化路径表示。

其次,在不同的操作系统中,根目录的表示方式不同,因此绝对路径也会有所差异。

而相对路径在不同操作系统中通常是一致的,可以跨平台使用。

在实际开发中,正确使用绝对路径和相对路径对于程序的运行和文件的读写至关重要。

首先,在引用外部文件时,如果文件位于程序的同一目录下,可以使用相对路径简化路径表示,提高代码的可读性;如果文件位于其他目录下,使用绝对路径可以确保文件的准确访问。

KeilC51中变量和函数的绝对地址定位问题:

KeilC51中变量和函数的绝对地址定位问题:

KeilC51中变量和函数的绝对地址定位问题:Keil C51中变量和函数的绝对地址定位问题:1. 变量绝对地址定位1) 在定义变量时使用 _at_ 关键字加上地址就可.e.g.unsigned char idata myvar _at_ 0x40;把变量 myvar 定义在 idata 的 0x40 处, 在 M51 文件中可以找到这麽一行IDATA 0040H 0001H ABSOLUTE表示有变量在 idata 的 0x0040 处绝对地址定位.2) 使用 KeilC 编译器定义绝对地址的变量, 方法待查.2. 函数绝对地址定位1) 在程序中编写一函数 myTestvoid myTest(void){// Add your code here}2) 使用KeilC 编译器定位绝对地址的函数, 打开Project -> Options for Target 菜单,选中 BL51 Locate 选项卡, 在 Code: 中输入:PR?myT est?MAIN(0x4000)把函数 myTest 定位到程序区的 0x4000 处,再次编译就可以了.3) 一次定位多个函数的方法同样地, 在程序中再编写另外一个函数 myTest1void myTest1(void){// Add your code here}在 Options for Target 菜单的 BL51 Locate 选项卡的 Code: 中输入:PR?myT est1?MAIN(0x3900), ?PR?myTest?MAIN(0x4000)把函数 myTest1 定位在程序区的 0x3900 处, 把函数 myTest 定义在程序区的 0x4000 处,重新编译就可以了.在 M51 文件中可以找到下面的内容:>> 3.obj TO Reader RAMSIZE (256) CODE (?PR?MYTEST1?MAIN (0X3900), ?PR?MYTEST?MAIN (0X4000))3665H 029BH *** GAP ***CODE 3900H 0014H UNIT PR?MYTEST1?MAIN 3914H 06ECH *** GAP ***CODE 4000H 0014H UNIT PR?MYTEST?MAIN4) 函数的调用:程序中直接调用函数的方式就不说明了, 这里重点讲使用函数指针调用绝对地址处的函数的方法.(1) 定义调用的函数原形typedef void (*CALL_MYTEST)(void);这是一个回调函数的原形, 参数为空.(2) 定义相应的函数指针变量CALL_MYTEST myTestCall = NULL;(3) 函数指针变量赋值, 指向我们定位的绝对地址的函数myTestCall = 0x3900;指向函数 myTest1(4) 函数指针调用if (myTestCall != NULL){myTestCall(); // 调用函数指针处的函数 myTest1, 置 PC 指针为 0x3900}检查编译生成的 bin 文件, 到 0x3900 处可以看到 myTest1 的内容, 在 0x4000 处可以看到 myTest 的内容,(5) 其它说明:如果在 0x3000 到 0x3900 的程序空间没有内容时, 把 myT estCall 的地址指针指到 0x3800(在 0x3000 到 0x3900 之间) 时, 会从 0x3900 处开始执行.至於在 Load 中调用 AP 中的函数的方法与此类似, 但是相应的参数传递可能要另寻方法.************************************keil C51绝对地址访问在利用keil进行8051单片机编程的时,常常需要进行绝对地址进行访问.特别是对硬件操作,如DA AD 采样 ,LCD 液晶操作,打印操作.等等.C51提供了三种访问绝对地址的方法:1. 绝对宏:在程序中,用“#include<absacc.h>”即可使用其中定义的宏来访问绝对地址,包括:CBYTE、XBYTE、PWORD、DBYTE、CWORD、XWORD、PBYTE、DWORD具体使用可看一看absacc.h便知例如:rval=CBYTE[0x0002];指向程序存贮器的0002h地址rval=XWORD [0x0002];指向外RAM的0004h地址2. _at_关键字直接在数据定义后加上_at_ const即可,但是注意:(1)绝对变量不能被初使化;(2)bit型函数及变量不能用_at_指定。

C51中变量和函数的绝对地址定位问题..

C51中变量和函数的绝对地址定位问题..

C51中变量和函数的绝对地址定位问题: 1. 变量绝对地址定位1) 在定义变量时使用 _at_ 关键字加上地址就可.e.g.unsigned char idata myvar _at_ 0x40;把变量 myvar 定义在 idata 的 0x40 处, 在 M51 文件中可以找到这麽一行IDATA 0040H 0001H ABSOLUTE表示有变量在 idata 的 0x0040 处绝对地址定位.2) 使用 KeilC 编译器定义绝对地址的变量, 方法待查.2. 函数绝对地址定位1) 在程序中编写一函数 myTestvoid myTest(void){// Add your code here}2) 使用 KeilC 编译器定位绝对地址的函数, 打开 Project -> Options for Target 菜单,选中 BL51 Locate 选项卡, 在 Code: 中输入:PRmyTestMAIN(0x4000)把函数 myTest 定位到程序区的 0x4000 处,再次编译就可以了.3) 一次定位多个函数的方法同样地, 在程序中再编写另外一个函数 myTest1void myTest1(void){// Add your code here}在 Options for Target 菜单的 BL51 Locate 选项卡的 Code: 中输入: PRmyTest1MAIN(0x3900), PRmyTestMAIN(0x4000)把函数 myTest1 定位在程序区的 0x3900 处, 把函数 myTest 定义在程序区的 0x4000处,重新编译就可以了.在 M51 文件中可以找到下面的内容:>> 3.obj TO Reader RAMSIZE (256) CODE (?PR?MYTEST1?MAIN (0X3900), ?PR?MYTEST?MAIN (0X4000))3665H 029BH *** GAP ***CODE 3900H 0014H UNIT ?PR?MYTEST1?MAIN3914H 06ECH *** GAP ***CODE 4000H 0014H UNIT ?PR?MYTEST?MAIN4) 函数的调用:程序中直接调用函数的方式就不说明了, 这里重点讲使用函数指针调用绝对地址处的函数的方法.(1) 定义调用的函数原形typedef void (*CALL_MYTEST)(void);这是一个回调函数的原形, 参数为空.(2) 定义相应的函数指针变量CALL_MYTEST myTestCall = NULL;(3) 函数指针变量赋值, 指向我们定位的绝对地址的函数myTestCall = 0x3900;指向函数 myTest1(4) 函数指针调用if (myTestCall != NULL){myTestCall(); // 调用函数指针处的函数 myTest1, 置 PC 指针为 0x3900}检查编译生成的 bin 文件, 到 0x3900 处可以看到 myTest1 的内容, 在 0x4000 处可以看到 myTest 的内容,(5) 其它说明:如果在 0x3000 到 0x3900 的程序空间没有内容时, 把 myTestCall 的地址指针指到0x3800(在 0x3000 到 0x3900 之间) 时, 会从 0x3900 处开始执行.至於在 Load 中调用 AP 中的函数的方法与此类似, 但是相应的参数传递可能要另寻方法.************************************keil C51绝对地址访问在利用keil进行8051单片机编程的时,常常需要进行绝对地址进行访问.特别是对硬件操作,如DA AD 采样 ,LCD 液晶操作,打印操作.等等.C51提供了三种访问绝对地址的方法:1. 绝对宏:在程序中,用“#include<absacc.h>”即可使用其中定义的宏来访问绝对地址,包括:CBYTE、XBYTE、PWORD、DBYTE、CWORD、XWORD、PBYTE、DWORD 具体使用可看一看absacc.h便知例如:rval=CBYTE[0x0002];指向程序存贮器的0002h地址rval=XWORD [0x0002];指向外RAM的0004h地址2. _at_关键字直接在数据定义后加上_at_ const即可,但是注意:(1)绝对变量不能被初使化;(2)bit型函数及变量不能用_at_指定。

KeilC函数库

KeilC函数库
Keil C 函数库
一、绝对地址宏指令: 绝对地址宏指令:使用#include <absacc.h> 1、CBYTE [ address ] 说明:在程序内存里,读取一个字节的内容。 自变量:程序内存的地址。 定义:#define CBYTE (( unsigned char volatile code *) 0) 例 1: # include <absacc .h> void main ( void ) {
*index = value ; index ++ ; } } 5、PBYTE [ address ] 说明:在外部数据存储器 ( 0~ 0xff )里,读取一个字节的内容。
自变量:外部数据存储器的地址 ( 0~ 0xff ) 。 定义:#define PBYTE (( unsigned char volatile pdata *) 0) 例 5: # include <adsacc .h> void PRamSet ( unsigned char value ) ; void main ( void ) {
char va1=0 ; // read program memory at address 0x0002
va1= CBYTE [ 0x0002 ] ; } 2、CWORD [ address ] 说明:在程序内存里,读取一个字节的内容。 自变量:程序内存的地址。 定义:#define CWORD (( unsigned int volatile code *) 0) 例 2: # include <adsacc .h> void main ( void ) {
float x ; float y ; float x ; for ( y=-10.0 ; y<=10.0 ; y+=0.1 ) z = atan2 ( y,x ) ; } 6、char cabs ( char va1 ) 说明:计算自变量 val 的绝对值。 返回值:返回 val 的绝对值。 例 6: #include <math.h> void main ( void ) { unsigned char x ; unsigned char y ; x =-23 ; y = cabs ( x ) ; } 7、flaot ceil ( float va1 ) 说明:计算出大于或等于自变量 val 的最小整数。 返回值:返回大于或等于 val 的最小整数。 例 7: #include <math.h> void main ( void ) { float x ; flaot y ; x =-45.92 ; y = ceil ( x ) ; } 8、float acos ( float x )

C语言相对定位和绝对定位

C语言相对定位和绝对定位
相对定位和绝对定位
内容提要
定位属性position及其取值 相对定位
相对定位的应用-偏移的导航条 网页居中的相对定位法
绝对定位 绝对定位的应用
缺角的导航条 小提示窗口 下拉菜单
2
使用定位属性position
利用浮动属性定位只能使元素浮动形成图文混 排或块级元素水平排列的效果,其定位功能仍 不够灵活强大。 本节介绍的在定位属性下的定位能使元素通过 设置偏移量定位到页面或其包含框的任何一个 地方,定位功能非常灵活。
14
ቤተ መጻሕፍቲ ባይዱ 绝对定位
绝对定位
绝对定位,盒子的位置以他的包含框为基准进行定 位。绝对定位的盒子从标准流中脱离。这意味着它 们对其他元素的盒子的定位没有影响,其他的盒子 就好像这个盒子不存在一样。 注意:绝对定位是以他的包含框的边框内侧为基准 进行定位,因此改变包含框的填充值不会对绝对定 位元素的位置造成影响。 绝对定位的偏移值是指从它的包含框边框内侧到元 素的外边界之间的距离,如果修改元素的margin值 会影响元素内容的显示位置。如果不设置绝对定位 元素的偏移值,那么它位于未设置绝对定位属性时 在标准流中的初始位置
18
绝对定位-设置包含框
p{ background-color: #dbfdba; padding: 25px; position:relative; border: 2px solid #6c4788; } em { background-color: #0099FF; position:absolute; left: 60px; top: 40px;}
12
相对定位制作简单的阴影效果
img { padding: 6px; border: 1px solid #465B68; background-color: #fff; position: relative; left: -5px; top: -5px; } div.shadow { background-color: #CCCCCC; float:left; } <div class="shadow"><img src="works.jpg" width="150" height="140" /></div>

KEIL段重定位

KEIL段重定位

KEIL段重定位2010-03-13 00:01对于一个大的文件,为了便于管理,一个好的办法时把一个大文件分为若干个小文件,每个小文件包含一部分相关的功能,这样功能将显得很整洁,而且移植到其它工程的时候也很方便,把文件copy过去即可。

对于汇编,我们也许知道,可以使用orgxxxx来指定函数的地址(org是一个段内指定偏移的伪指令),但是当指定这个地址时,是否与其它函数冲突呢?有可能其它函数过长已经占用了这个地址。

难道要数手指计算函数的长度吗?另一个问题是主函数怎样调用被调函数呢?在回答这些问题之前,先来看看使用的开发工具是怎样工作的。

首先A51汇编器汇编文件后会生成.obj文件,这并不是最终需要的文件。

通常还要使用一个叫链接器(如BL51)的工具,把多个obj文件组合起来,生成最终的二进制代码文件(或其它格式的文件)。

虽然传递给链接器的参数是一个或多个obj文件,但是链接器在链接时却是按段来计算的。

每个obj文件里包含的都是一些绝对地址段或/和可重定位段。

链接器必须为可重定位段重新计算及分配地址。

并计算绝对地址段是否重叠。

因此:可得定位段可以保证多目标文件链接时不发生目标地址重叠,故绝对地址段只适用用某些特殊场合,如固定I/O 口或中断向量的入口地址绝对地址段就是这个段的地址在传入链接器的时候已经固定,链接器不能改变这个段的地址。

可重定位段就是这个段的地址需要链接器分配,如是代码段的段内的跳转等指令的偏移也需要重新进算。

段的另一种分法可分为代码段,数据段。

数据段又分为以初始化数据段和未初始化数据段。

这里不细说。

通过上面可知,如果一个函数是一个段,而这个段是可重定位的,那么就可以不用考虑代码的地址问题了,把这个问题留给了链接器。

剩下来的问题就是怎样把一个函数变为一个段的问题,(当然一个段可包括很多函数,在汇编中,函数只是一个说法而已)。

大部分的汇编器都会提供伪指令来定义绝对段及可重定位段(写法上有可能有区别而已)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档