电子说
偏移地址就是计算机里的内存分段后,在段内某一地址相对于段首地址(段地址)的偏移量。偏移地址也称为偏移量,由于8086/8088CPU内部的ALU只能进行16位的运算,而8086/8088有20条地址线,直接寻址能力1MB。因此,8086/8088所使用的20位物理地址,是由相应的段地址加上偏移地址组成的。
8086/8088有20条地址线,它的直接寻址能力为1MB。也就是在一个系统中可以有多达1MB的存储器,地址从00000H—FFFFFH。给定任意一个20位物理地址,就可以从中取出需要的指令和操作数。但是8086/8088CPU只能进行16位运算。与地址有关的寄存器SP、IP、BP、SI、DI也都是16位的,所以对地址的运算也只能是16位的。对于8086/8088来说,无论采用哪种寻址方式,寻找操作数的范围最大是2^16,也就是64K。如何才能形成20位的物理地址呢。系统先将1MB存储器以64KB为范围分成若干段。在寻址一个具体物理地址时,由一个基本地址再加上由SP或IP等可由CPU处理的16位偏移量来形成20位物理地址。
当系统需要产生一个20位地址的时候,一个段寄存器会自动被选择。且自动左移4位再与一个16位地址偏移量相加产生所需的20位地址。
例如:数据段DS寄存器的值=0088H
偏移地址=22H
那么生成的20位物理地址等于00880H+22H=008A2H
左移4位就是16进制后面补一个0.
段地址=1F00H,偏移地址=1000H,
线型地址=1F000h+1000H=20000H
段地址=1F00H,偏移地址=1000H,
线型地址=1F000h+1000H=20000H
经常有人问怎么获取类中的成员变量的地址偏移量,这个应该是很多初学C++的人很好奇的问题。以前我在学校的时候,也有过这种需求。忘了当时是要写什么“奇怪的程序”了,反正需要获取一个类的成员变量的地址偏移量。
其实这个问题很简单,如果你了解C++的类对象内存分布的话,这个根本不是问题。我给他举了个例子:
structA
{
inti;
};
&((A*)0)-》i;//这样就可以获取到偏移量了。他表示不理解,OK,我们来具体说说。
假如定义个变量Aa;我们都知道&a表示变量a的首地址,&(a.i)表示变量i的地址,那么&(a.i)减去&a不就得到i的偏移量了吗?
是的,就是这么简单。那么这个例子&((A*)0)-》i;有什么关系呢?
&((A*)0)的地地址就是0,所以&((A*)0)-》i等于&((A*)0)-》i减去0。
有个网友更好奇了,为什么&((A*)0)-》i不会出问题?这个例子里并没有为A的对象分配内存,那怎么可以得到它的地址呢?
是的,这里确实没有分配内存,但是这个例子里我们并没有要求有内存,我们也不对内存进行操作,所以不会引来崩溃。
&((A*)0)-》i只是借助编译器为我们计算出它的地址。当编译器要用要一个成员变量的时候,它会根据对象的首地址加上成员的偏移量得到成员变量的地址。当对象的首地址为0时,得到的成员变量地址就是它的偏移量。
全部0条评论
快来发表一下你的评论吧 !