Какова хитрость в pAddress & ~ (PAGE_SIZE - 1), чтобы получить базовый адрес страницы - PullRequest
1 голос
/ 11 июня 2010

Следующая функция используется для получения базового адреса страницы адреса, находящегося внутри этой страницы:

void* GetPageAddress(void* pAddress)
{
    return (void*)((ULONG_PTR)pAddress & ~(PAGE_SIZE - 1));
}

Но я не совсем понял, в чем тут трюк?

Заключение:
Лично я думаю, что объяснение Амардипа плюс пример Алекса Б. - лучшие ответы.Поскольку за ответ Алекса Б уже проголосовали, я хотел бы принять ответ Амардипа в качестве официального, чтобы выделить его!Спасибо вам всем.

Ответы [ 4 ]

14 голосов
/ 11 июня 2010

Функция очищает младшие биты данного адреса, что дает адрес ее страницы.

Например, если PAGE_SIZE равно 4096, то в 32-разрядном двоичном формате:

   PAGE_SIZE      = 00000000000000000001000000000000b
   PAGE_SIZE - 1  = 00000000000000000000111111111111b
 ~(PAGE_SIZE - 1) = 11111111111111111111000000000000b

Если вы поразрядно - и это с 32-битным адресом, он превратит младшие биты в нули, округляя адрес до ближайшего 4096-байтового адреса страницы. ~(PAGE_SIZE - 1) = 11111111111111111111000000000000b pAddress = 11010010100101110110110100100100b ~(PAGE_SIZE - 1) & pAddress = 11010010100101110110000000000000b Таким образом, в десятичном виде исходный адрес равен 3533139236, адрес страницы (адрес с удаленными младшими битами) равен 3533135872 = 862582 x 4096, кратен 4096.

6 голосов
/ 11 июня 2010

То, что он делает, очищает биты адреса, которые соответствуют маске, созданной размером страницы. Фактически он получает первый действительный адрес блока.

PAGE_SIZE должен быть степенью 2 и представлен одним битом, установленным в адресе.

Маска создается путем вычитания одного из PAGE_SIZE. Это эффективно устанавливает все биты, которые имеют более низкий порядок, чем бит размера страницы. Затем ~ дополняет все эти биты до нуля и устанавливает все биты, которые имеют более высокий порядок, чем маска. Затем & эффективно удаляет все младшие биты, оставляя фактический базовый адрес страницы, содержащей исходный адрес.

4 голосов
/ 11 июня 2010

Когда PAGE_SIZE имеет некоторую степень 2 (скажем, 4096, например), это очищает все биты ниже тех, которые указывают страницу.

1 голос
/ 11 июня 2010

Это просто хитрый способ очистки битов младшего разряда.

Другим способом реализации может быть

void* GetPageAddress(void* pAddress)
{
    return pAddress - pAddress%PAGE_SIZE;
}

Это, вероятно, не скомпилируется, так как вам нужно немного привести типы, бит показывает алгоритм.

Фактически он получает наибольшее кратное PAGE_SIZE, которое меньше pAddress.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...