关键词不能为空

当前您在: 主页 > 英语 >

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

作者:高考题库网
来源:https://www.bjmy2z.cn/gaokao
2021-03-03 12:52
tags:

-

2021年3月3日发(作者:finance是什么意思)


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)


在程序中编写一函数


myTest


void myTest(void)


{


// Add your code here


}


2)


使用


KeilC


编译器定位绝对地址的函数


,


打开


Project -> Options for


Target


菜单


,



选中


BL51 Locate


选项卡


,



Code:


中输入


:


?PR?myTest?MAIN(0x4000)



把函数


myTest


定位到程序区的


0x4000



,



再次编译就可以了


.


3)


一次定位多个函数的方法




同样地


,


在程序中再编写另外一个函数


myTest1


void 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


文件中可以找到下面的内容


:



>> 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?MAIN


4)


函数的调用


:



程序中直接调用函数的方式就不说明了


,

这里重点讲使用函数指针调用


绝对地址处的函数的方法


.


(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


绝对地址访问



< p>
在利用


keil


进行


80 51


单片机


编程的时


,


常常需要进行绝对地址进行访问


.


特别是


对硬件操作


,



DA AD


采样


,LCD


液晶操作

< p>
,


打印操作


.


等等


.


C51


提供了三种访问绝对地址的方法:



1.


绝对宏:



在程序中,





include


即可使用其中定义的宏来访问绝对地址,



括:



CBYTE

< br>、


XBYTE



PWORD



DBYTE



C WORD



XWORD



PBYTE



DWORD


具体使用可看一看


absacc.h


便知



例如:



rval=CBYTE[0x0002];


指向程序存贮器的

< br>0002h


地址



rval=XWORD [0x0002];


指向外

< p>
RAM



0004h


地址



2. _at_


关键字



直接在数据定义后加上


_at_ const


即可,但是注意:



(1)


绝对变量不能被初使化;


< /p>


(2)bit


型函数及变量不能用


_at _


指定。




例如:




idata struct link list _at_ 0x40;


指定


list


结构从


40h


开始。



xdata char text[25b] _at_0xE000


;指定


text< /p>


数组从


0E000H


开始



提示:如果外部绝对变量是


I/O


端口等可自行变化数据,需要使用


volatile


关 键


字进行描述,请参考


absacc.h





3.


连接定位控制



此法是利用连接控制指令


code xdata pdata data bdata






地址进行,如要


指定某具体变量地址,则很有 局限性,不作详细讨论。





:(c51)




/*------------------------- ------------------------------------------

< br>-------



ABSACC.H




Direct access to 8051, extended 8051 and Philips 80C51MX memory areas.



Copyright (c) 1988-2002 Keil Elektronik GmbH and Keil Software, Inc.



All


rights


reserved.



----- -------------------------------------------------- --------------


-----*/




#ifndef


__ABSACC_H__



#define




#define



#define



#define



#define




#define



#define



#define



__ABSACC_H__


CBYTE


DBYTE


PBYTE


XBYTE


((unsigned


((unsigned


((unsigned


((unsigned


char


char


char


char


volatile


volatile


volatile


volatile


code


data


pdata


xdata


*)


*)


*)


*)


0)


0)


0)


0)


CWORD


DWORD


PWORD


((unsigned


((unsigned


((unsigned


int


int


int


volatile


volatile


volatile


code


data


pdata


*)


*)


*)


0)


0)


0)


#define


XWORD


((unsigned


int


volatile


xdata


*)


0)





#ifdef


__CX51__



#define


FVAR(object,


addr)


(*((object


volatile


far


*)


(addr)))



#define


FARRAY(object,


base)


((object


volatile


far


*)


(base))



#define


FCVAR(object,


addr)


(*((object


const


far


*)


(addr)))



#define


FCARRAY(object,


base)


((object


const


far


*)


(base))



#else



#define


FVAR(object,


addr)


(*((object


volatile


far


*)


((addr)+0x10000L)))



#define


FCVAR(object,


addr)


(*((object


const


far


*)


((addr)+0x810000L)))



#define


FARRAY(object,


base)


((object


volatile


far


*)


((base)+0x10000L))



#define


FCARRAY(object,


base)


((object


const


far


*)


((base)+0x810000L))



#endif




#endif




:(c166)




/*------------------------- ------------------------------------------

< br>-------



ABSACC.H




Direct


access


to


166


memory


areas


for


C166/EC++


Version


5.



Copyright (c) 1992-2004 Keil Elektronik GmbH and Keil Software, Inc.



All


rights


reserved.



--------------------------- ------------------------------------------

< br>-----*/




#ifndef



#define




#if



#define



#define



#else



#define



#define




#define



#define



#define



#define



#endif


__ABSACC_H__


__ABSACC_H__


(__MODEL__


==


0)


MVAR(object,


addr)


(*((object


volatile


*)


(addr)))


MARRAY(object,


base)


((object


volatile


*)


(base))


MVAR(object,


addr)


(*((object


volatile


far


*)


(addr)))


MARRAY(object,


base)


((object


volatile


far


*)


(base))


HVAR(object,


addr)


(*((object


volatile


huge


*)


(addr)))


HARRAY(object,


base)


((object


volatile


huge


*)


(base))


XVAR(object,


addr)


(*((object


volatile


xhuge


*)


(addr)))


XARRAY(object,


base)


((object


volatile


xhuge


*)


(base))


#endif



以下来自转载:



使用


KeilC51


软件,可以很方便地将代码或者数据绝对定位到某个地址。



1


、代码定位:



方法


1



使用 伪指令


CSEG



比如要将

< p>
MyFunc1


定位到代码区


C:0x1000< /p>



则新


建一个


A 51


文件,添加以下内容:



PUBLIC MYFUNC1


CSEG AT 1000H


MYFUNC1:


;


其它代码



RET


在其它源文件中,就可以调用


MyFunc()


函数了。需要注意的是,编译器不检测


传递参 数的数目,仅检测函数是否有返回值。



方法

< br>2


:使用


BL51 Locate


选项。比如在


main.c


中定义了一个

MyFunc2


函数,


并且要将该函数定位到代码区


C:0x2000


,则从菜单中选择


Proj ect->Options for


Target 'Target1'


,在弹出的对话框中选择


BL51 Loc ate


页,在下面的


code


栏中


写上


?PR?MYFUNC2?MAIN(0x2000)


即可。



如果想定位多个函数,也可以使用


*


通配符。



2


、变量定位:



只有全局变量可以绝对定位,局部变量无法实现绝对定位。


< /p>


方法


1



使用< /p>


_at_


关键字。


声明一个全局变量


unsigned char data MyBuf1[8] _at_


0x20;


方法


2

< br>:使用


BL51 Locate


选项。比如将

< p>
main.c


中定义的所有


data


型的全局变


量定位到数据区


D:0x28

< p>
开始的空间,则从菜单中



选择


Project->Options for Target 'Target1'



在弹出的对话框中选择< /p>


BL51 Locate


页,在下面的


d ata


栏中写上


?DT?MAIN(0x28)


即可。



如果是


idata< /p>



则使用


?ID?MAIN(0x28)



如果是


xdata

< br>,


则使用


?XD?MAIN(0x28)



如果是


pdata


,则使用


?PD?MAIN(0x28)


3


、堆栈定位:



STARTUP.A51


文件中定义了堆栈区

< p>
?STACK


,其起始地址同样可以在


BL51


Locate


页中设置,在


Stack


栏写上


?STACK(0x80)



BL51 locate


选项卡中




code range



xdata range


如果不填 写,


编译默认将程序中相应代码和变量从空


间前面取起




网上看到有人提到在


keil


中使用


_at_


进行绝对地 址定位问题,


我简单介绍一下它


的用法。




使用


_at_


关键字对存储器进行绝对地址定位程序如下





i nclude



char xdata LED_Data[50] _at_ 0x8000;



main()



{



LED_Data[0] = 0x23;



}




ke il


中运行以上程序可以在存储器窗口中输入


x



0x8000


可以看到


0x8000


地址中的值为


0x23.



值得指出的几点是




1.


在给变量


LED_Data[50]


定位绝对地址空间时,不能对其赋初值。

< br>



xdata LED_Data[50] _at_ 0x8000;


这条语句不能主函数中。有些网友提


到在按着


keil


说明中用


_at_< /p>


进行绝对地址定位时,


编译会出现错误


2 74



就是将


这条语句放在主函数中的 原因。





中 地址是自动分配的,所以除非特殊情况否则不提倡使用绝对地址定位。


初学者因帖别注意 。不要把


c


当作汇编使用。




对需要


/RST

复位后要保持变量不变,防止意外改变(比如升级到新程序,变量


地址可能被编译器 优化到其他地方),比较有用!!!!





STARTUP.A51


这个文件有什么用,有必要添加到工程吗?




如果不添加



文件,编译器就会自动加入一段初始化内存以及堆栈等


的代码,


这时的内存初始化部分你就无法去控制了,


当然这在大部分情况下没什

< br>么关系。


但是如果你想你的程序在复位后,


内存里面的信 息依然还保存着


(所说



< p>
热复位




< p>
那么你就需要添加该启动文件,


并且去里面修改内存初始化部分,


不要初始化你需要保留的部分内存。




请问如何在


keil


编译器里,编程时指定 函数的绝对地址



(


无内容


)



不好意思啊,


我还从来没有接触过有这样要求情况,

< p>
不过从网上其他地方找了一


篇你参考一下吧,、函数定位:



假如要把


C


源文件



tools.c


中的函数



int BIN2HEX(int xx)


{




...


}


放在


CODE MEMORY



0x1000


处,先编译该工程,然后打开该工程的

< br>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)


再 次


Build


,在


M51


中会发现该函数已放在


CODE MEMORY


的< /p>


0x1000


处了



2


、赋初值的变量定位:


< p>
要将某变量定位在一绝对位置且要赋初值,


此时用



_at_


不能完成,


则如下操


作:



在工程中建立一个新的文件,



InitVars.c


在其中对要处理的变量赋初值


(假


设是

code




量):



char code myVer = {


然后将该文件加入工程,编译,打开


M51


文件,若定义的是


code


型,则在< /p>



* * *



C O D E



M E M O R Y



* * *


下可找到:



CODE



xxxxH





xxxxH





UNIT







?CO?INITVARS


然后在:



Project->Options for Target ...->BL51 Locate



Code


中填入:



?CO?INITVARS(0x200)


再次编译即可。



相应地,如为


xdata


变量,则


InitVars.c< /p>


中写:



char xdata myVer = {


然后将该文件加入工程,编译,打开


M51


文件,在



* * *



X D A T A



M E M O R Y



* * *


下可找到:



XDATA



xxxxH





xxxxH





UNIT







?XD?INITVARS


然后在:



Project->Options for Target ...->BL51 Locate



Xdata


中填入:



?XD?INITVARS(0x200)


再次编译即可。相 应地,若定义的是


data/idata


等变量,则相应处理即 可。



3



若 有


多个变量或函数要进行绝对地址定位,


则应按地址从低到高的 顺序排列




**********************************


PIC 51


混编


C18


指定数据绝对地址




51:



RSEG


是段选择指令,要想明白它的意思就要了解段的意思。



段是程序代码或数据对象的存储单位。


程序代码放到代码段,


数据对象放到数据


段。段分两种,一是绝对段,一是再定位段。绝对段在汇编语言中指定 ,在用


L51


联接的时候,地址不会改变。用于如访问一个固定 存储器的


i/o,


或提供中断


向量的入 口地址。而再定位段的地址是浮动的。它的地址有


L51


对程序 模块连


接时决定


,C51


对源程序编译 所产生的段都是再定位段,


它都有段名和存储类型。


绝对段没有 段名。



说了这么多,大家可能还是不明白段是什么意思。别急 ,接着往下看。



例如,你写用


C


写了一个函数


void test_fun(void) {



} ,


存在


test.c


中,用编译


器编译以后


. SRC FILE


中看到


:



?PR?test_fun?TEST SEGMENT CODE //(


函数放到代码段中


)




写这个函数体的时候


: RSEG ?PR?test_fun?TEST //


选择已定位的代码段为


当前段


test_fun:




……


//


代码



所以函数的表达模式是这样:


?PR?


函数名


?


文件名



而函数名又分


: 1:


无参函数


?PR?


函数名


?


文件名



2:


有参函数


?PR?_

< p>
函数名


?


文件名



3:


再入函数


?PR?_?


函数名


?


文件名



又例如



你定义了全局变量


unsigned char data temp1,temp2; unsigned char


xdata temp3;



test.c


文件中,编译器会为每 个文件分


0


到多个全局数据段,相


同类 型的全局变量被存到同一段中。所以上面会编译成如下


:


RSEG ? DT? TEST


. temp1: DS 1


. temp2: DS 1


;


RSEG ?XD? TEST


. temp3: DS 1


//


下面是各个类型的数据全局段的表示



?CO?


文件名


//


常数段



?XD? FILE_NAME //XDATA


数据段



?DT? FILE_NAME //DATA


数据段



?ID? FILE_NAME //IDATA…..



?BI? FILE_NAME // BIT …..



?BA? FILE_NAME //BDATA….



?PD? FILE_NAME //PDATA…..



看到这里大家应 该明白段的意思了吧。


也许你会问,


这有什么作用哪?它就是用


在当你需要用汇编语言写一部份程序的时候,把汇编写的函数放在这个问件中,


改名


xxx.a51,


按上面的规则写。



编译就好。



既然 知道了段的意思,现在我们回到


SEG


的用法上来。

< p>


A51


中有两种段选择指令





再定位段选择指令





绝对段选择指令


.


它们用来选


择当前段是再定位段还是绝对段。


使用不同的段选择指令,

< p>
将使程序定位在不同


的地址空间之内。




1:


再定位段的选择指令是:


RSEG


段名



它用来选择一个在前面已经定义过的再定位段作为当前段。


< /p>


用法就像我们上面的例子,先申明了一个函数段,后面写这个函数段。


2:


绝对段选择指令



CSEG [AT


绝对地址表达式


] //


绝对代码段



DSEG [AT


绝对地址表达式


] //


内部绝对数据段



XSEG [AT


绝对地址表达式


] //


外部绝对数据段



ISEG [AT


绝对地址表达式


] //


内部间接寻址绝对数据段



BSEG [AT


绝对地址表达式


] //


绝对位寻址段



它们的用法我举一个例子


:


例如我们 写串口中断程序,起始地址是


0x23.


就这样写



CSEG AT 0X23


LJMP serialISR


RSEG ?PR?serialISR?TEST


. serialISR:




PIC:



汇编函数使用同一个工 程


C


文件中的变量


,

< br>例如


ICFLAG



C


文件中定义


,


则汇


编文 件中定义方式为




;


定义外部变量



EXTERN ICFLAG



定义函数




例如



CARDATR:

-


-


-


-


-


-


-


-



C51中变量和函数的绝对地址定位问题要点的相关文章

  • 余华爱情经典语录,余华爱情句子

    余华的经典语录——余华《第七天》40、我不怕死,一点都不怕,只怕再也不能看见你——余华《第七天》4可是我再也没遇到一个像福贵这样令我难忘的人了,对自己的经历如此清楚,

    语文
  • 心情低落的图片压抑,心情低落的图片发朋友圈

    心情压抑的图片(心太累没人理解的说说带图片)1、有时候很想找个人倾诉一下,却又不知从何说起,最终是什么也不说,只想快点睡过去,告诉自己,明天就好了。有时候,突然会觉得

    语文
  • 经典古训100句图片大全,古训名言警句

    古代经典励志名言100句译:好的药物味苦但对治病有利;忠言劝诫的话听起来不顺耳却对人的行为有利。3良言一句三冬暖,恶语伤人六月寒。喷泉的高度不会超过它的源头;一个人的事

    语文
  • 关于青春奋斗的名人名言鲁迅,关于青年奋斗的名言鲁迅

    鲁迅名言名句大全励志1、世上本没有路,走的人多了自然便成了路。下面是我整理的鲁迅先生的名言名句大全,希望对你有所帮助!当生存时,还是将遭践踏,将遭删刈,直至于死亡而

    语文
  • 三国群英单机版手游礼包码,三国群英手机单机版攻略

    三国群英传7五神兽洞有什么用那是多一个武将技能。青龙飞升召唤出东方的守护兽,神兽之一的青龙。玄武怒流召唤出北方的守护兽,神兽之一的玄武。白虎傲啸召唤出西方的守护兽,

    语文
  • 不收费的情感挽回专家电话,情感挽回免费咨询

    免费的情感挽回机构(揭秘情感挽回机构骗局)1、牛牛(化名)向上海市公安局金山分局报案,称自己为了挽回与女友的感情,被一家名为“实花教育咨询”的情感咨询机构诈骗4万余元。

    语文