C 存贮模式 near far huge

转自: http://www.cnblogs.com/draeag/archive/2007/09/20/899587.html


在DOS下(实模式)地址是分段的,每一段的长度为64K字节,刚好是16位(二进制的十六位)。

near指针的长度是16位的,所以可指向的地址范围是64K字节,通常说near指针的寻址范围是64K。
far指针的长度是32位,含有一个16位的基地址和16位的偏移量,将基地址乘以16后再与偏移量相加,(所以实际上far指针是20位的长度。)即可得到far指针的1M字节的偏移量。所以far指针的寻址范围是1M字节,超过了一个段64K的容量。例如一个far指针的段地址为0x7000,偏移量为0x1244,则该指针指向地址0x71224.如果一个far指针的段地址是0x7122,偏移量为0x0004,则该指针也指向地址0x71224。
    如果没有指定一个指针是near或far,那么默认是near。所以far指针要显式指定。far指针工作起来要慢一些,因为每次访问一个far指针时,都要将
数据 段或程序段的数据交换出来。另外,far指针的运算也比较反常,例如上面讲到的far指针指向同一个地址,但是比较的结果却不相同。

  什么时候使用far指针
当使用小代码或小数据存储模式时,不能编译一个有很多代码或数据的程序。因为在64K的一个段中,不能放下所有的代码与数据。为了解决这个问题,需要指定以far函数或far指针来使用这部分的空间(64K以外的空间)。许多库函数就是显式地指定为far函数的形式。far指针通常和farmalloc()这样的内存分配函数一起使用。


char near *p; /*定义一个字符型“近”指针*/
char far *p; /*定义一个字符型“远”指针*/
char huge *p; /*定义一个字符型“巨”指针*/

首先要从8086处理器体系结构和汇编渊源学起。8086是一个16位处理器,它设定了四个段寄存器,
专门用来保存段地址:CS(Code Segment):代码段寄存器;DS(Data Segment):数据段寄存器;
SS(Stack Segment):堆栈段寄存器;ES(Extra Segment):附加段寄存器。8086采用段式访问,
访问本段(64K范围内)的数据或指令时,不需要变更段地址(意味着段地址寄存器不需修改),
而访问本段范围以外的数据或指令时,则需要变更段地址(意味着段地址寄存器需要修改)。
因此,在16位处理器环境下,如果访问本段内地址的值,用一个16位的指针(表示段内偏移)就可以访问到;
而要访问本段以外地址的值,则需要用16位的段内偏移+16位的段地址,总共32位的指针。

这样,就可以知道远、近指针的区别:

近指针是只能访问本段、只包含本段偏移的、位宽为16位的指针;
远指针是能访问非本段、包含段偏移和段地址的、位宽为32位的指针。

近指针只能对64k字节数据段内的地址进行存取,如:
char near *p;
p=(char near *)0xffff;

远指针是32位指针,它表示段地址:偏移地址,远指针可以进行跨段寻址,可以访问整个内存的地址。
如定义远程指针p指向0x1000段的0x2号地址,即1000:0002,则可写作:
char far *p;
p=(char far *)0x10000002;

除了远指针和近指针外,还有一个巨指针的概念。
和远指针一样,巨指针也是32位的指针,指针也表示为16位段:16位偏移,也可以寻址任何地址。
它和远指针的区别在于进行了规格化处理。远指针没有规格化,可能存在两个远指针实际指向同一个物理地址,
但是它们的段地址和偏移地址不一样,如23B0:0004和23A1:00F4都指向同一个物理地址23604!
巨指针通过特定的例程保证:每次操作完成后其偏移量均小于10h,即只有最低4位有数值,其余数值都被进位到段地址上去了,
这样就可以避免Far指针在64K边界时出乎意料的回绕的行为。当然,一次操作必须小于64K。下面的函数可以将远指针转换为巨指针:
void normalize(void far ** p)
{
  *p=(void far *)(((long)*p&0xffff000f)+(((long)*p&0x0000fff00<<12));
}

从上面的函数中 可以看到指针之指针的使用,这个函数要修改指针的值,因此必须传给它的指针的指针作为参数。

看到最后。。。。学习到了一点。。让人很郁闷的事实。。。

近指针、远指针、巨指针是段寻址的16bit处理器的产物
(如果处理器是16位的,但是不采用段寻址的话,也不存在近指针、远指针、巨指针的概念),
当前普通PC所使用的32bit处理器(80386以上)一般运行在保护模式下的,
指针都是32位的,可平滑地址,已经不分远、近指针了。
但是在嵌入式系统领域下,8086的处理器仍然有比较广泛的市场,
如AMD公司的AM186ED、AM186ER等处理器,开发这些系统的程序时,我们还是有必要弄清楚指针的寻址范围。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值