difference in far and huge pointer

C, C++, Visual C++, C++.Net Topics
Post Reply
SukhdeepMankoo
Lieutenant
Lieutenant
Posts: 92
Joined: Tue Oct 27, 2009 7:50 pm

difference in far and huge pointer

Post by SukhdeepMankoo » Fri Apr 09, 2010 5:04 pm

Hi,
I have a doubt in far and huge pointer. when i am trying to search the difference on google. i have found that
far pointer: it contains the address, which points to both segment number and its offset(within that segment number). thus it can access any location within the memory. suppose i am running my code on 1MB of memory, where size of segment is 64kb(16bit address) and offset value from 0 to 15(4 bit address).

Huge pointer is too same as far pointer. but it is normalized pointer as far is not normalized pointer.
what is the normalized pointer and what will be its benefit?

Thanks & Regards
Sukhdeep Singh
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

Re: difference in far and huge pointer

Post by Neo » Sun Apr 11, 2010 7:12 am

This is based on x86. But you can get the meaning...

It may happen that far pointers holding different addresses may refer to the same memory location. This deduces from the method of obtaining the 20-bit physical address from the segment:offset pair. This is shown below for three different addresses:

Consider the three addresses: 0×00000120, 0×00100020 and 0×00120000

00000 segment address left shifted by 4 bits
0120 offset address
———-
00120 resultant 20-bit address

00100 segment address left shifted by 4 bits
0020 offset address
———-
00120 resultant 20-bit address

00120 segment address left shifted by 4 bits
0000 offset address
———-
00120 resultant 20-bit address

Unlike far pointers huge pointers are ‘normalized’ to avoid these problems. A normalized pointer is a 32- bit pointer, which has as much of its value in the segment address as possible. Since a segment can start every 16 bytes, this means that the offset will only have a value from 0 to F.

To normalize a pointer, first it is converted to its 20-bit address then the left 16 bits are used for the segment address and the right 4 bits for the offset address. For example, given the pointer 500D:9407, converting it to a 20-bit absolute address gives 594D7, which is then normalized to 594D:0007.

huge pointers are always kept normalized. As a result for any given memory address there is only one possible huge address—segment:offset pair—for it. This is more logical than the result obtained while using far pointers.

But then there is a price to be paid for using huge pointers. Huge pointer arithmetic is done with calls to special subroutines. Because of this, huge pointer arithmetic is significantly slower than that of far or near pointers.
SukhdeepMankoo
Lieutenant
Lieutenant
Posts: 92
Joined: Tue Oct 27, 2009 7:50 pm

Re: difference in far and huge pointer

Post by SukhdeepMankoo » Wed Apr 14, 2010 3:17 pm

Thanks Neo,
As offset can have its value from 0 to f. how is it possible as you have given example that offset address is holding value more than f like 0120. second thing, why shifting the data left by 4 bits.

One more thing, given the pointer 500D:9407, converting it to a 20-bit absolute address gives 594D7, which is then normalized to 594D:0007. how can tell that which is segment and offset address.

i am completely in doubtful about that address calculations. kindly elaborate this, i will be grateful.........
Thanks.
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

Re: difference in far and huge pointer

Post by Neo » Thu Apr 15, 2010 1:53 am

As offset can have its value from 0 to f. how is it possible as you have given example that offset address is holding value more than f like 0120.
If 0120 is the 20-bit address, when it is normalized, the segment would be 0012 and the offset would be 0.
i.e.: 0012:0000.
Note that last 4-bits are take as the offset. Correct me if you see any problem.
second thing, why shifting the data left by 4 bits.
There is no shift operation involved for normalized address form.
If you are talking about far pointers, yes, that's how the segment is calculated. That's how the linker is going to do it.
One more thing, given the pointer 500D:9407, converting it to a 20-bit absolute address gives 594D7, which is then normalized to 594D:0007. how can tell that which is segment and offset address.
594D7 is a 20-bit absolute address that we use to normalize. We first take the left 16-bits (not left shifting...you may consider it as a 4-bit right shift if you want)..i.e.: 594D7. This is the segment in the normalized form. The right 4-bits (again no shift operation here...you may think of it as ADDRESS & 0x0000F) i.e.: 0x7 is considered as the offset. So the normalized address can be written as 594D:0007.

It is good to know how these addresses are handled at the linker stage of compilation process. BTW: You don't have much control over it as the linker is 100% responsible in making addresses and compile them to the final executable file.

For most of the DSP applications (which has SDRAM or DDR on its EMIF), far is used with large memory model.

Read some notes about it.
Data Access
The C compiler creates a default section in which it places all global and static data. This section is called .bss. With the creation of this section, the C compiler also generates a pointer to the beginning of this section. This pointer is called the Data Page Pointer (DP).

When you build your application for the default compiler memory model (the small memory model), the compiler will by default place all global and static data in the .bss section and will access that data using the near access method. The near access method will access this data relative to the Data Page Pointer, and each access will take one assembly instruction. This is the most efficient form of data access.

With the small (default) memory model, there is a requirement that the size of the .bss section is less than 32Kbytes. This is because for the small memory model, a near data access uses an offset from the Data Page Pointer, where this offset is limited to 32Kbytes in size.

An alternative method of data access is the far access method. The far access method can be used by compiling with one of the large memory model options or by using the far keyword when declaring data. By accessing data as far, that data is now no longer placed in the .bss section, and there is now no 32Kbyte limit on the size of all that data.

However, unlike near accesses, far accesses are less efficient as each access will take three assembly instructions to perform. The extra instructions will increase the time the access takes to complete, and will also increase the size of the program code.

So there is a trade-off between the use of near data and far data. Near data offers the best performance but a program is limited to having 32Kbytes of near data at most.

Far data does not have this 32Kbyte limit, but offers slower performance than near data.

Code Access
When a function is called, the program must perform a branch from the function that is currently executing to the new function that has been called. This branch can be performed in one of two ways.

The first method is generated by the compiler adding a relative offset to the current program counter in order to perform the branch. This method is the near access method, and takes one assembly instruction to perform. It is the most efficient form of function call, and hence offers the best performance.

The second method is generated by the compiler forming an absolute address to which the program counter will branch. This method is the far access method. It is not as efficient as a near function call as three assembly instructions are required. The extra instructions will increase the time the function call takes to complete, and will increase the size of the program code.

When using a near function call, there is a requirement that the relative offset for the branch is less than +/-1Mword from the current program counter position. If this requirement is not met, a far function call is required.

When building with the small (default) memory model, all function calls are treated as near. By compiling with one of the large memory model options or by using the far keyword when declaring functions, a far call will be used.

As a general rule, far function calls should be used where the total code size is greater than 1Mword (or 4Mbytes), or if code sections are being placed in separate memory segments. Where code is placed in more than one memory segment, this will usually result in an address span between the code in one segment and the code in another exceeding 1Mword. In this case, far function calls must be used.
SukhdeepMankoo
Lieutenant
Lieutenant
Posts: 92
Joined: Tue Oct 27, 2009 7:50 pm

Re: difference in far and huge pointer

Post by SukhdeepMankoo » Thu Apr 15, 2010 3:59 pm

Thanks Neo.
SukhdeepMankoo
Lieutenant
Lieutenant
Posts: 92
Joined: Tue Oct 27, 2009 7:50 pm

Re: difference in far and huge pointer

Post by SukhdeepMankoo » Sat May 22, 2010 12:14 pm

in this program

int main()
{ char far *fp=0x8f290ef;
char huge *hp=0x8f290ef;
for(char loop=0;loop<20;loop++)
{ cout<<"far"<<(long *)fp<<'\t'<<"huge"<<(long *)hp<<endl;
}
getch();
}

i have seen the in case of huge pointer its offset value(i.e. first LSB of 4 byte address) is between 0 to 0xf. and after 0xf roll over to 0. while in case of far its offset value(i.e. first four LSB of 4 byte address) is between 0x0000 to 0xffff and after 0xffff roll over to 0.
Then how can huge and far pointer will point to next segment after the offset has reached its max. value.
Thanks
User avatar
Neo
Site Admin
Site Admin
Posts: 2642
Joined: Wed Jul 15, 2009 2:07 am
Location: Colombo

Re: difference in far and huge pointer

Post by Neo » Tue May 25, 2010 9:36 pm

This is completely a platform dependant topic. Read following article to whether it answered your question.
http://www.digitalmars.com/ctg/ctgMemoryModel.html
Post Reply

Return to “C/C++ Programming”