请不要给我以下或任何类似的答案:
“The only difference between a far pointer and a huge pointer is that a huge pointer is normalized by the compiler. A normalized pointer is one that has as much of the address as possible in the segment,meaning that the offset is never larger than 15. A huge pointer is normalized only when pointer arithmetic is performed on it. It is not normalized when an assignment is made. You can cause it to be normalized without changing the value by incrementing and then decrementing it. The offset must be less than 16 because the segment can represent any value greater than or equal to 16 (e.g. Absolute address
0x17
in a normalized form would be0001:0001
. While a far pointer could address the absolute address0x17
with0000:0017
,this is not a valid huge (normalized) pointer because the offset is greater than0000F
.). Huge pointers can also be incremented and decremented using arithmetic operators,but since they are normalized they will not wrap like far pointers.”
这里的归一化概念没有得到很好的解释,或者我可能无法理解它.
任何人都可以从初学者的角度尝试解释这个概念.
谢谢,
Rahamath
解决方法
Example: Segment 0x1234 Offset 0x5678 will give the real address 0x 1234 +0x 5678 --------- =0x 179B8
正如您将注意到的,此操作不是双射的,这意味着您可以使用其他段和偏移的组合生成实际地址.
0x 1264 0x 1111 +0x 5378 +0x 68A8 --------- --------- etc. =0x 179B8 =0x 179B8
实际上有4096种不同的组合,因为3个重叠的半字节(3 * 4 = 12位,2 ^ 12 = 4096).
归一化组合是4096个可能值中唯一一个将偏移的3个高半字节归零的组合.在我们的例子中,它将是:
0x 179B +0x 0008 --------- =0x 179B8
far和big指针之间的差异不在规范化中,你可以有非规范化的巨大指针,它是绝对允许的.不同之处在于执行指针运算时生成的代码.使用far指针向指针递增或添加值时,将不会有溢出处理,您将只能处理64K的内存.
char far *p = (char far *)0x1000FFFF; p++; printf("p=%p\n");
将打印1000:0000
对于巨大的指针,编译器将生成处理转移所需的代码.
char huge *p = (char huge *)0x1000FFFF; p++; printf("p=%p\n");
将打印2000:0000
这意味着在使用远或大指针时必须要小心,因为使用它们的算术成本是不同的.
人们也不应该忘记,大多数16位编译器都有没有正确处理这些情况的库,有时会提供有缺陷的软件.微软实模式编译器没有处理其所有字符串函数的巨大指针. Borland甚至更糟糕,即使mem函数(memcpy,memset等)也没有处理偏移溢出.这就是为什么使用带有这些库函数的规范化指针是个好主意的原因,偏移溢出的可能性随之降低.