c语言之far指针(转)

1、64K限制的困扰

 

我们考虑下面一段16位C语言代码片断:

char g_c;

void func (char *p)

{

 char c;

 

 p = &c;

 p = &g_c;

 p = (char *)malloc(10 * sizeof(char));

 free(p);

 

 return;

}

显然,g_c是全局变量,按照教科书的说法,它应该放在全局变量区,c是局部变量,因此c放在栈区,而malloc所申请的空间应该是在堆区。上面的代码从语义上讲没有半点错误,一个指针p可以指向全局变量区的内存,也可以指向堆区或栈区的内存。

大家知道,16Bit C语言的指针是16位的,因此只能访问64K大小的空间,然而我们使用指针对全局变量,堆,栈进行寻址的时候,都没有指定一个数据段。那么也就是说,全局变量,堆以及栈都是在同一个段中的,这三部分的大小加起来不可能大于64K,这也是malloc的参数int类型的最大表示范围。

按照我的理解这64K应该是这样的:

64K最顶端是栈区(因为栈总是从上往下的),一般我们在程序的开始会设置SS的内容和DS一样,SP的值为0,如果有进栈操作的话,SP会减少2,而变成从FFFE,然后往下减。

64K最底端是数据区(这部分是固定的,堆和栈是可变的),我们声明了Data Segment之后,一般会将Data Segment的段起始地址给DS,然而,Data Segment中的变量是按顺序从低往高排的,一旦编译连接成可执行文件之后,这部分内容的大小(或称为长度)是不会变的。我们可以更改的是堆和栈的大小。

堆区位于数据区以上部分,也就是如果堆区的不断增长,或者栈区的不断进栈,最终可能造成堆区和栈区交叉,也就是我们俗称的堆栈溢出。

或许会有些疑问,认为我将局部变量放在栈区是不对的,这里就这部分内容再展开讨论一下,对于函数的参数是放在栈区的,大家不会有所怀疑,因为函数调用除了使用寄存器传递参数之外只能使用堆栈传递了(当然使用全局变量也可以,不过这里只讨论形参与实参的传递),因此调用Func的过程伪代码如下所示:

 lea bx, p

 push bx

 call func

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值