(В целях иллюстрации этот ответ предполагает, что адреса являются 32-битными, что, по-видимому, соответствует коду в вопросе.)
pageNumber = logicalAddress & pageNumberMask;
pageNumber = pageNumber >> 8;
offsetNumber = logicalAddress & offsetMask;
Логический адрес разделен на три набора битов : 16 старших битов, которые игнорируются в этом коде, 8 битов, используемых для номера страницы, и 8 младших битов, которые используются для смещения внутри страницы.
pageNumberMask
- это значение, которое было подготовлено для имеют 1 в битах номера страницы и 0 в других местах. Затем операция logicalAddress & pageNumberMask
выполняет побитовое И, которое выдает значение, в котором установлены только те биты, которые были установлены в битах номера страницы logicalAddress
. Другими словами, он создает значение, при котором верхние биты и биты смещения очищаются, эффективно изолируя биты номера страницы.
Затем pageNumber >> 8
сдвигает эти биты номера страницы до младших битов, поэтому Результатом является номер страницы. Этот номер страницы можно затем использовать для индексации массивов.
Аналогично, offsetMask
- это подготовленное значение с 1 с в битах смещения и 0 с в другом месте, а logicalAddress & offsetMask
извлекает только биты смещения.
Обратите внимание, что logicalAddress & pageNumberMask
служит цели, только если могут быть установлены биты над битами номера страницы. Это связано с тем, что pageNumber >> 8
все равно удаляет младшие биты, поэтому нет смысла очищать их с помощью операции &
. Таким образом, этот код отделяет биты номера страницы от старших бит, но не использует эти старшие биты. Это может быть связано с тем, что это упрощенный пример обучения, а в реальном коде для развертывания используются верхние биты.
И почему использование memset опасно.
memset
- это мощная процедура, которую легко использовать неправильно. При неправильных аргументах он изменит любую доступную память, и компилятор часто не может обнаружить, что он использовался неправильно, поэтому он не может выдавать предупреждение или сообщение об ошибке.
Дефекты в коде
Код в вопросе имеет ряд недостатков, поэтому он не является хорошим примером для обучения:
struct tlbTable tlb[TLB_SIZE];
, за которым следует memset(pageTable, -1, 16*sizeof(char));
, выглядит как ошибка. pageTable
был инициализирован ранее, и это, вероятно, предназначалось для инициализации tlb
. И размер неправильный; tlb
имеет 16 элементов (TLB_SIZE
равно 16), каждый из которых состоит из нескольких байтов. Эта строка, вероятно, должна быть memset(tlb, -1, sizeof tlb);
, а предыдущая memset
должна быть memset(pageTable, -1, sizeof pageTable);
. - Макросы препроцессора определены для различных параметров, таких как 256 для
PAGE_SIZE
, но затем части кода игнорируются они и используют жестко закодированные константы, как в Frame*256 + Index
. Это рецепт для ошибок.