В архитектуре компьютеров адресация слов означает, что адреса памяти на компьютере однозначно идентифицируют слова памяти. Обычно она используется в отличие от адресации байтов , где адреса однозначно идентифицируют байты . Почти все современные архитектуры компьютеров используют адресацию байтов, а адресация слов в значительной степени представляет только исторический интерес. Компьютер, использующий адресацию слов, иногда называют машиной слов .
Рассмотрим компьютер, который предоставляет 524 288 (2 19 ) бит памяти. Если эта память организована в адресном плоском адресном пространстве с байтовой адресацией, используя 8-битные байты, то есть 65 536 (2 16 ) допустимых адресов, от 0 до 65 535, каждый из которых обозначает независимые 8 бит памяти. Если вместо этого она организована в адресном плоском адресном пространстве с словарной адресацией, используя 32-битные слова, то есть 16 384 (2 14 ) допустимых адресов, от 0 до 16 383, каждый из которых обозначает независимые 32 бита.
В более общем смысле, минимальная адресуемая единица (MAU) является свойством определенной абстракции памяти. Различные абстракции в компьютере могут использовать разные MAU, даже если они представляют одну и ту же базовую память. Например, компьютер может использовать 32-битные адреса с байтовой адресацией в своем наборе инструкций , но система когерентности кэша ЦП может работать с памятью только с гранулярностью 64-байтовых строк кэша , позволяя идентифицировать любую конкретную строку кэша только с 26-битным адресом и уменьшая накладные расходы кэша.
Трансляция адресов, выполняемая виртуальной памятью, часто влияет на структуру и ширину адресного пространства, но не изменяет MAU.
Размер минимальной адресуемой единицы памяти может иметь сложные компромиссы. Использование большего MAU позволяет покрыть тот же объем памяти меньшим адресом, что может существенно снизить требования к памяти программы. Однако использование меньшего MAU облегчает эффективную работу с небольшими элементами данных.
Предположим, что программа хочет сохранить один из 12 традиционных знаков западной астрологии . Один знак может храниться в 4 битах. Если знак хранится в своем собственном MAU, то 4 бита будут потрачены впустую при адресации байтов (эффективность 50%), в то время как 28 бит будут потрачены впустую при адресации 32-битных слов (эффективность 12,5%). Если знак «упакован» в MAU с другими данными, то его чтение и запись могут быть относительно более затратными. Например, чтобы записать новый знак в MAU, в который были упакованы другие данные, компьютер должен прочитать текущее значение MAU, перезаписать только соответствующие биты, а затем сохранить новое значение обратно. Это будет особенно затратно, если программе необходимо разрешить другим потокам одновременно изменять другие данные в MAU.
Более распространенным примером является строка текста . Распространенные форматы строк, такие как UTF-8 и ASCII, хранят строки как последовательность 8-битных кодовых точек. При байтовой адресации каждая кодовая точка может быть помещена в свой собственный независимо адресуемый MAU без накладных расходов. При 32-битной адресации слов размещение каждой кодовой точки в отдельном MAU увеличит использование памяти на 300%, что нецелесообразно для программ, работающих с большими объемами текста. Упаковка смежных кодовых точек в одно слово позволяет избежать этих затрат. Однако многие алгоритмы для работы с текстом предпочитают иметь возможность независимо адресовать кодовые точки; чтобы сделать это с упакованными кодовыми точками, алгоритм должен использовать «широкий» адрес, который также хранит смещение символа внутри слова. Если этот широкий адрес необходимо сохранить в другом месте памяти программы, он может потребовать больше памяти, чем обычный адрес.
Чтобы оценить эти эффекты в полной программе, рассмотрим веб-браузер, отображающий большую и сложную страницу. Часть памяти браузера будет использоваться для хранения простых данных, таких как изображения и текст; браузер, скорее всего, выберет хранение этих данных максимально эффективно, и они будут занимать примерно тот же объем памяти независимо от размера MAU. Другая память будет представлять модель браузера различных объектов на странице, и эти объекты будут включать множество ссылок: друг на друга, на данные изображения и текста и т. д. Объем памяти, необходимый для хранения этих объектов, будет в значительной степени зависеть от ширины адреса компьютера.
Предположим, что если бы все адреса в программе были 32-битными, эта веб-страница занимала бы около 10 гигабайт памяти.
Таким образом, адресация слов позволяет компьютеру адресовать значительно больше памяти без увеличения ширины адреса и соответствующего увеличения использования памяти. Однако это имеет ценность только в относительно узком диапазоне размеров рабочего набора и может привести к существенным накладным расходам времени выполнения в зависимости от приложения. Программы, которые относительно мало работают с байт-ориентированными данными, такими как изображения, текст, файлы и сетевой трафик, могут получить наибольшую выгоду.
Программа, работающая на компьютере, использующем адресацию слов, может работать с меньшими блоками памяти, эмулируя доступ к меньшему блоку. Для загрузки требуется загрузить охватывающее слово и затем извлечь нужные биты. Для сохранения требуется загрузить охватывающее слово, сместить новое значение на место, перезаписать нужные биты и затем сохранить охватывающее слово.
Предположим, что четыре последовательных кодовых точки из строки UTF-8 необходимо упаковать в 32-битное слово. Первая кодовая точка может занимать биты 0–7, вторая 8–15, третья 16–23 и четвертая 24–31. (Если бы память была адресуемой по байтам, это был бы порядок байтов little endian .)
Чтобы четко прояснить код, необходимый для доступа к подсловам, не привязывая пример слишком тесно к какой-либо конкретной архитектуре с адресацией по словам, в следующих примерах используется сборка MIPS . На самом деле MIPS — это архитектура с байтовой адресацией с прямой поддержкой загрузки и сохранения 8-битных и 16-битных значений, но пример будет делать вид, что он обеспечивает только 32-битные загрузки и сохранения и что смещения в 32-битном слове должны храниться отдельно от адреса. MIPS был выбран, потому что это простой язык ассемблера без специализированных средств, которые сделали бы эти операции более удобными.
Предположим, что программа хочет прочитать третью кодовую точку в регистр r1
из слова по адресу в регистре r2
. При отсутствии какой-либо другой поддержки со стороны набора инструкций программа должна загрузить полное слово, выполнить сдвиг вправо на 16, чтобы отбросить первые две кодовые точки, а затем замаскировать четвертую кодовую точку:
ldw $r1, 0($r2) # Загрузить полное слово srl $r1, $r1, 16 # Сдвиг вправо на 16 andi $r1, $r1, 0xFF # Скрыть другие кодовые точки
Если смещение статически неизвестно, а вместо этого в регистре хранится битовое смещение r3
, требуется немного более сложный подход:
ldw $r1, 0($r2) # Загрузить полное слово srlv $r1, $r1, $r3 # Сдвиг вправо на смещение бита andi $r1, $r1, 0xFF # Скрыть другие кодовые точки
Предположим вместо этого, что программа хочет назначить кодовую точку в регистре r1
третьей кодовой точке в слове по адресу в r2
. При отсутствии какой-либо другой поддержки со стороны набора инструкций программа должна загрузить полное слово, замаскировать старое значение этой кодовой точки, сместить новое значение на место, объединить значения и сохранить полное слово обратно:
sll $r1, $r1, 16 # Сдвиг нового значения влево на 16 lhi $r5, 0x00FF # Построить постоянную маску для выбора третьего байта nor $r5, $r5, $zero # Перевернуть маску так, чтобы она очистила третий байт ldw $r4, 0($r2) # Загрузить полное слово и $r4, $r5, $r4 # Очистить третий байт из слова или $r4, $r4, $r1 # Объединить новое значение со словом stw $r4, 0($r2) # Сохраняем результат как полное слово
Опять же, если смещение вместо этого хранится в r3
, требуется более сложный подход:
sllv $r1, $r1, $r3 # Сдвигаем новое значение влево на смещение бита llo $r5, 0x00FF # Построить постоянную маску для выбора байта sllv $r5, $r5, $r3 # Сдвиг маски влево на смещение бита nor $r5, $r5, $zero # Перевернуть маску так, чтобы она очистила выбранный байт ldw $r4, 0($r2) # Загрузить полное слово и $r4, $r5, $r4 # Очистить выбранный байт из слова или $r4, $r4, $r1 # Объединить новое значение со словом stw $r4, 0($r2) # Сохраняем результат как полное слово
Эта последовательность кода предполагает, что другой поток не может модифицировать другие байты в слове одновременно. Если возможна параллельная модификация, то одна из модификаций может быть потеряна. Чтобы решить эту проблему, последние несколько инструкций должны быть превращены в атомарный цикл сравнения-обмена, так что параллельная модификация просто заставит его повторить операцию с новым значением. В этом случае барьеры памяти не требуются.
Пара адреса слова и смещения внутри слова называется широким адресом (также известным как толстый адрес или толстый указатель ). (Это не следует путать с другими вариантами использования широких адресов для хранения других видов дополнительных данных, таких как границы массива.) Сохраненное смещение может быть либо битовым смещением, либо байтовым смещением. Последовательности кода выше выигрывают от смещения, выраженного в битах, поскольку они используют его в качестве счетчика сдвига; архитектура с прямой поддержкой выбора байтов может предпочесть просто хранить байтовое смещение.
В этих последовательностях кода дополнительное смещение должно храниться рядом с базовым адресом, что фактически удваивает общие требования к хранению адреса. Это не всегда верно для текстовых машин, в первую очередь потому, что сами адреса часто не упакованы с другими данными, чтобы сделать доступ более эффективным. Например, Cray X1 использует 64-битные слова, но адреса составляют всего 32 бита; когда адрес хранится в памяти, он хранится в своем собственном слове, и поэтому смещение байта может быть помещено в верхние 32 бита слова. Неэффективность использования широких адресов в этой системе заключается только во всей дополнительной логике для манипулирования этим смещением и извлечения и вставки байтов в слова; это не оказывает влияния на использование памяти.
Минимальная адресуемая единица компьютера не обязательно совпадает с минимальным размером доступа к памяти набора инструкций компьютера. Например, компьютер может использовать байтовую адресацию, не предоставляя никаких инструкций для прямого чтения или записи одного байта. Ожидается, что программы будут эмулировать эти операции в программном обеспечении с помощью битовых манипуляций, как это делают приведенные выше примеры последовательностей кода. Это довольно распространено в 64-битных компьютерных архитектурах, разработанных в качестве преемников 32-битных суперкомпьютеров или миникомпьютеров, таких как DEC Alpha и Cray X1 .
Стандарт C гласит, что указатель должен иметь обычное представление адреса. C также позволяет формировать указатель на любой объект, кроме битового поля; это включает в себя каждый отдельный элемент массива байтов. Компиляторы C для компьютеров, использующих адресацию слов, часто используют разные представления для указателей на разные типы в зависимости от их размера. Указатель на тип, который достаточно велик, чтобы заполнить слово, будет простым адресом, в то время как указатель, такой как char*
или void*
будет широким указателем: парой адреса слова и смещения байта внутри этого слова. Таким образом, преобразование между типами указателей не обязательно является тривиальной операцией и может привести к потере информации, если выполнено неправильно.
Поскольку размер C struct
не всегда известен при принятии решения о представлении указателя на тот struct
, невозможно надежно применить правило выше. Компиляторам может потребоваться выровнять начало a, struct
чтобы он мог использовать более эффективное представление указателя.
ldq_u
и stq_u
), которые игнорируют эти биты и просто загружают и сохраняют содержащее выровненное слово. [2] Более поздние расширения байтовых слов в архитектуре (BWX) добавили 8-битные и 16-битные загрузки и сохранения, начиная с Alpha 21164a. [3] Опять же, это расширение было возможно без серьезных программных несовместимостей, поскольку Alpha всегда использовала байтовую адресацию.