不同位数单片机的学习总结

发布时间:2015-01-06 18:08:11   来源:文档文库   
字号:

不同位数单片机的学习总结

1.单片机位数的概念

参与运算的寄存器的数据长度,另一种说法是CPU一次处理的数据宽度,并不是指总线宽度CPU能同时处理二进制数的位数是多少位,就称其是多少位的计算机。也有数据总线的位数是CPU位数的一半的情况,就称其是准多少位的计算机。比如CPU16位,数据总线也是16位,则是16位计算机;CPU16位,数据总线也是8位,则是准16位计算机。51单片机的地址总线是16位的,但是它是8位机。像ARM的存储器也有八位的,但是它是32位机。而是指CPU处理的数据的宽度,也就是CPU一次数据的吞吐量。比如同一条指令:MOV R0 R251单片机里面,R0R2都是8位的,所以51CPU一次只能处理8位数据。在ARM里面,R0R232位的,所以ARMCPU一次能处理32位数据。这就是区别。

2.不同位数单片机的区别

速度上有区别,取决于CPU、寄存器的字长。8位单片机不能直接处理16位数据,要按照8位数据来处理,要分几个过程来完成。而16位单片机,可直接处理16们数据,因为其ALU,寄存器等都是16位的,可一次完成8位单片机要多步完成的动作,特别是对于数据处理,16位单片机有它的优势。而且16位单片机大多数据接口都为16位。

3.不同位数单片机之间程序的移植

原来是16位单片机想改用8位的替代是可以的,但电路及程序都要做相应改变,并且改为8位机后,在功能和速度上要能够满足你工作的需要才行。

1一些基本类型位宽变化了,还有一些类型位宽不确定,比如说int,相信99%32位编译器(未作统计)都将int视为32位有符号型,但在64位编译器上,这点是不确定的,ms的编译器,int型都还是32位有符号整型,但印象中存在某个平台的gcc编译器将int位宽增加到64位。诸如此类,需要特别注意

2强制类型转换代码需特别注意,特别是c开发人员,对于指针和整型的理解已炉火纯青,借由整型空间存储指针的方法是很常用的(也是很方便的),由于强制转换代码的存在,编译器并不会提示诸如64位到32位转换中可能的信息损失,这也就导致了运行时可能的问题爆发。这一点需要特别注意,严查代码各处的强制转换。

3模块间调用,严格说这一点还是由位宽变化导致的,做法还是需要筛查类型是否匹配的问题

432位程序移植到64位需要考虑的问题

留心intpointer

因为integerpointer大小相同,所以32位代码中常常把pointer转换为int或者unsigned int,以便算术运算。为了移植,你可以把pointer转换为unsigned long,因为longpointer都是等长的,无论是在ILP32亦或LP64,但是,为了使代码更清晰,推荐用uintptr_tuintptr_tintptr_t都需要包含头文件inttypes.h
例如:下面代码在64位环境下编译出错:
char *p;

p = (char *) ((int)p & PAGEOFFSET);
% cc ..
warning: conversion of pointer loses bits

改用uintptr_t后,无论是32位或者64位都没问题:
char *p;
p = (char *) ((uintptr_t)p & PAGEOFFSET);

 

留心intlong
ILP32中,可能从未对intlong加以区分,因此,混用的情况非常多,看下面代码:
int waiting;
long w_io;
long w_swap;
...
waiting = w_io + w_swap;

% cc
warning: assignment of 64-bit integer to 32-bit integer

 

留心对齐
出于访问的效率,结构中通常会有所谓的hole,用来保证其中的所有数据成员,起始地址都是对齐模数的倍数。
例如:
struct bar {
  int i;  
  long j; 
  int k; 
  char *p;
};
ILP32中,sizeof(bar)应该是16字节;在LP64中,应该是32!因为此时long/char *的对齐模数都变为8,为了保证满足对齐要求,i/k都被扩展为8字节了。

又例如:
struct bar {
  char *p;
  long j;
  int i;
  int k;
}
此时,无需扩展,sizeof(bar)=8+8+4+4=24.

 

留心union
union中的成员,必须保持平衡,也就是说,必须保证大小相等才有意义,所以移植时也要注意。
例如:
typedef union {
  double _d;
  long _l[2];
} llx_
ILP32中,两者大小相同,都是8字节;移植到LP64,前者不变,后者为16字节,此时union已无意义,应改为:
typedef union {
  double _d;
  int _l[2];
} llx_

 

留心常量类型
在常量表达式中,精度的缺失会导致数据截断,例如:
int i = 32;
long j = 1 << i;
warning: left shift count >= width of type
什么意思?编译器抱怨左移的位数超过了数据类型的长度,结果就是j0

怎么修改呢?
int i = 32;
long j = 1L << i
即可。

 

留心printf系列函数
在格式化串中,要注意:
%p兼容ILP32L64
如果有long型参数,必须加上l前缀;
另外就是作为目标的buffer必须够长。

 

留心sizeof
sizeof返回类型为unsigned long,如果返回给int型变量,可能发生截断。

 

留心derived data types
例如,这些定义在sys/types.h中的数据类型,其大小会随ILP32或者LP64而变化:
    * clock_t, which represents the system time in clock ticks
    * dev_t, which is used for device numbers
    * off_t, which is used for file sizes and offsets
    * ptrdiff_t, which is the signed integral type for the result of subtracting two pointers
    * size_t, which reflects the size, in bytes, of objects in memory
    * ssize_t, which is used by functions that return a count of bytes or an error indication
    * time_t, which counts time in seconds

 

留心边缘效应
局部代码发生类型改变,可能导致其他代码发生64位转换,例如函数的返回值由Int变为sszie_t,则所有调用该函数并获取其返回值的地方,都有可能发生意想不到的64位转换。

 

留心long array 对效率的影响
大型Long/unsigned long数组,在LP64下,相比ILP32,效率非常低,所以,如果int就足够,尽量不要使用Long,这一点,对于pointer arrary同样适用。

本文来源:https://www.2haoxitong.net/k/doc/c0ea8d41b90d6c85ed3ac669.html

《不同位数单片机的学习总结.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式