手机站
网通分站
电信主站
密 码:
用户名:
当前位置 : 主页>程序设计>C/C++>列表

C语言嵌入式系统编程修炼之内存操作

来源:互联网 作者:west263.com 时间:2008-02-23
西部数码-全国虚拟主机10强!40余项虚拟主机管理功能,全国领先!双线多线虚拟主机南北访问畅通无阻!免费赠送企业邮局,.CN域名,自助建站480元起,免费试用7天,满意再付款! P4主机租用799元/月.月付免压金!
数据指针

   在嵌入式系统的编程中,常常需要在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C 以外的其他编程语言基本没有直接访问绝对地址的能力。在嵌入式系统的实际调试中,多借助C语言指针所具备的对绝对地址单元内容的读写能力。以指针直接操作内存多发生在如下几种情况:

   (1) 某I/O芯片被定位在CPU的存储空间而非I/O空间,而且寄存器对应于某特定地址;

   (2) 两个CPU之间以双端口RAM通信,CPU需要在双端口RAM的特定单元(称为mail box)书写内容以在对方CPU产生中断;

   (3) 读取在ROM或FLASH的特定单元所刻录的汉字和英文字模。

   譬如:

unsigned char *p = (unsigned char *)0xF000FF00;
*p=11;

   以上程式的意义为在绝对地址0xF0000 0xFF00(80186使用16位段地址和16位偏移地址)写入11。

   在使用绝对地址指针时,要注意指针自增自减操作的结果取决于指针指向的数据类别。上例中p 后的结果是p= 0xF000FF01,若p指向int,即:

int *p = (int *)0xF000FF00;

   p (或 p)的结果等同于:p = p sizeof(int),而p-(或-p)的结果是p = p-sizeof(int)。

   同理,若执行:

long int *p = (long int *)0xF000FF00;

   则p (或 p)的结果等同于:p = p sizeof(long int) ,而p-(或-p)的结果是p = p-sizeof(long int)。

   记住:CPU以字节为单位编址,而C语言指针以指向的数据类型长度作自增和自减。理解这一点对于以指针直接操作内存是相当重要的。

  函数指针

   首先要理解以下三个问题:

   (1)C语言中函数名直接对应于函数生成的指令代码在内存中的地址,因此函数名能够直接赋给指向函数的指针;

   (2)调用函数实际上等同于"调转指令+参数传递处理+回归位置入栈",本质上最核心的操作是将函数生成的目标代码的首地址赋给CPU的PC寄存器;

   (3)因为函数调用的本质是跳转到某一个地址单元的code去执行,所以能够"调用"一个根本就不存在的函数实体,晕?请往下看:

   请拿出您能够获得的任何一本大学《微型电脑原理》教材,书中讲到,186 CPU启动后跳转至绝对地址0xFFFF0(对应C语言指针是0xF000FFF0,0xF000为段地址,0xFFF0为段内偏移)执行,请看下面的代码:

typedef void (*lpFunction) ( ); /* 定义一个无参数、无返回类型的 */
/* 函数指针类型 */
lpFunction lpReset = (lpFunction)0xF000FFF0; /* 定义一个函数指针,指向*/
/* CPU启动后所执行第一条指令的位置 */
lpReset(); /* 调用函数 */

   在以上的程式中,我们根本没有看到任何一个函数实体,但是我们却执行了这样的函数调用:lpReset(),他实际上起到了"软重启"的作用,跳转到CPU启动后第一条要执行的指令的位置。

   记住:函数无他,唯指令集合耳;您能够调用一个没有函数体的函数,本质上只是换一个地址开始执行指令!

  数组vs.动态申请

   在嵌入式系统中动态内存申请存在比一般系统编程时更严格的需要,这是因为嵌入式系统的内存空间往往是十分有限的,不经意的内存泄露会很快导致系统的崩溃。

   所以一定要确保您的malloc和free成对出现,假如您写出这样的一段程式:

char * function(void)
{
  char *p;
  p = (char *)malloc(…);
  if(p==NULL)
   …;
   … /* 一系列针对p的操作 */
  return p;
}

   在某处调用function(),用完function中动态申请的内存后将其free,如下:

char *q = function();

free(q);

   上述代码明显是不合理的,因为违反了malloc和free成对出现的原则,即"谁申请,就由谁释放"原则。不满足这个原则,会导致代码的耦合度增大,因为用户在调用function函数时需要知道其内部细节!

   正确的做法是在调用处申请内存,并传入function函数,如下:

char *p=malloc(…);
if(p==NULL)
…;
function(p);

free(p);
p=NULL;

   而函数function则接收参数p,如下:

void function(char *p)
{
  … /* 一系列针对p的操作 */
}


   基本上,动态申请内存方式能够用较大的数组替换。对于编程新手,笔者推荐您尽量采用数组!嵌入式系统能够以博大的胸襟接收瑕疵,而无法"海纳"错误。毕竟,以最笨的方式苦练神功的郭靖赛过机智聪明却范政治错误走反革命道路的杨康。

   给出原则:

   (1)尽可能的选用数组,数组不能越界访问(真理越过一步就是谬误,数组越过界限就光荣地成全了一个混乱的嵌入式系统);

   (2)假如使用动态申请,则申请后一定要判断是否申请成功了,并且malloc和free应成对出现!



[1] [2] 下一页

文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

热点关注
IDC资讯 虚拟主机 域名注册 托管租用 vps主机 智能建站
网站运营 建站经验 策划盈利 搜索优化 网站推广 免费资源
网站联盟 联盟新闻 联盟介绍 联盟点评 网赚技巧
行业资讯 业界动态 搜索引擎 网络游戏 门户动态 电子商务 广告传媒
网络编程 Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术 Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷 Internet Explorer
网页制作 FrontPages Dreamweaver Javascript css photoshop fireworks Flash
程序设计 Java技术 C/C++ VB delphi
网络知识 网络协议 网络安全 网络管理 组网方案 Cisco技术
操作系统 Win2000 WinXP Win2003 Mac OS Linux FreeBSD
返回首页 |关于我们 | 联系我们 | 付款方式 | 创业联盟 | 价格总览 | 资讯中心 | 友情链接 | 网站地图 | 招贤纳士 | RSS