What is the trick in pAddress & ~(PAGE_SIZE - 1) to get the page's base address
Following function is used to get the page's base address of an address which is inside this page:
void* GetPageAddress(void* pAddress)
{
return (void*)((ULONG_PTR)pAddress & ~(PAGE_SIZE - 1));
}
But I couldn't quite get it, what is the trick it plays here?
Conclusion:开发者_JAVA百科
Personally, I think Amardeep's explanation plus Alex B's example are best answers. As Alex B's answer has already been voted up, I would like to accept Amardeep's answer as the official one to highlight it! Thanks you all.The function clears low bits of a given address, which yields the address of its page.
For example, if PAGE_SIZE
is 4096, then in 32-bit binary:
PAGE_SIZE = 00000000000000000001000000000000b
PAGE_SIZE - 1 = 00000000000000000000111111111111b
~(PAGE_SIZE - 1) = 11111111111111111111000000000000b
If you bitwise-and it with a 32-bit address, it will turn lower bits into zeros, rounding the address to the nearest 4096-byte page address.
~(PAGE_SIZE - 1) = 11111111111111111111000000000000b
pAddress = 11010010100101110110110100100100b
~(PAGE_SIZE - 1) & pAddress = 11010010100101110110000000000000b
So, in decimal, original address is 3533139236
, page address (address with lower bits stripped) is 3533135872 = 862582 x 4096
, is a multiple of 4096
.
What it does is clears the bits of the address that fit within the mask created by the page size. Effectively it gets the first valid address of a block.
PAGE_SIZE must be a power of 2 and is represented by a single bit set in the address.
The mask is created by subtracting one from PAGE_SIZE. That effectively sets all the bits that are a lower order than the page size bit. The ~ then complements all those bits to zero and sets all the bits that are a higher order than the mask. The & then effectively strips all the lower bits away, leaving the actual base address of the page containing the original address.
When PAGE_SIZE is some power of 2 (say 4096 for example), this clears all the bits below those that specify the page.
This is just a tricky way of clearing the low order bits.
Another way to implement it might be
void* GetPageAddress(void* pAddress)
{
return pAddress - pAddress%PAGE_SIZE;
}
That probably won't compile, as you need to cast the types a bit, bit it shows the algorithm.
Effectively it is getting the largest multiple of PAGE_SIZE that is less than pAddress.
精彩评论