Итак, я знаю, какими должны быть следующие регистры и их использование:
CS = сегмент кода (используется для IP)
DS = сегмент данных (используется для MOV)
ES = целевой сегмент (используется для MOVS и т. Д.)
SS = сегмент стека (используется для SP)
Но для чего предназначены следующие регистры?
FS = "Сегмент файла"?
GS = ???
Примечание: я не спрашиваю о какой-либо конкретной операционной системе - я спрашиваю о том, для чего они предназначены для использования процессором, если что-то еще.
assembly
x86
cpu-architecture
cpu-registers
memory-segmentation
пользователь541686
источник
источник
Ответы:
Вот для чего они предназначены и для чего используются Windows и Linux.
Первоначальная цель регистров сегмента состояла в том, чтобы позволить программе получить доступ ко многим различным (большим) сегментам памяти, которые должны были быть независимыми и являться частью постоянного виртуального хранилища. Идея была взята из операционной системы Multics 1966 года , которая рассматривала файлы как просто адресуемые сегменты памяти. Нет BS «Открыть файл, записать запись, закрыть файл», просто «Сохранить это значение в этот виртуальный сегмент данных» с очисткой грязной страницы.
Наши текущие операционные системы 2010 года - это гигантский шаг назад, поэтому их называют «евнухами». Вы можете адресовать только один сегмент вашего пространства процессов, давая так называемое «плоское (ИМХО тупое) адресное пространство». Сегментные регистры на машине x86-32 все еще можно использовать для реальных сегментных регистров, но это никого не беспокоило (Энди Гроув, бывший президент Intel, в прошлом веке имел довольно известную общественную поддержку, когда понял, что все эти инженеры Intel потратили энергию и его деньги на реализацию этой функции, что никто не собирался ее использовать. Вперед, Энди!)
AMD, перейдя на 64-битную версию, решила, что им все равно, исключат ли они Multics в качестве выбора (это благотворительная интерпретация; недоброжелательная - они ничего не знали о Multics) и поэтому отключили общую возможность сегментных регистров в 64-битном режиме. По-прежнему существовала потребность в потоках для доступа к локальному хранилищу потока, и каждому потоку требовался указатель ... где-то в немедленно доступном состоянии потока (например, в регистрах) ... на локальное хранилище потока. Поскольку Windows и Linux использовали для этой цели FS и GS (спасибо Нику за разъяснения) в 32-битной версии, AMD решила разрешить использование 64-битных сегментных регистров (GS и FS) только для этой цели (я думаю, вы можете сделать так, чтобы они указывали в любом месте вашего процесса; не знаю, может ли код приложения их загружать или нет).
Было бы архитектурно красивее IMHO, чтобы карта памяти каждого потока имела абсолютный виртуальный адрес (например, 0-FFF), который был его локальным хранилищем потока (не нужен указатель на регистр [сегмент]!); Я сделал это в 8-битной ОС еще в 1970-х годах, и это было чрезвычайно удобно, например, иметь еще один большой стек регистров для работы.
Итак, сегментные регистры теперь похожи на ваше приложение. Они служат рудиментарной цели. К нашей коллективной потере.
Те, кто не знает истории, не обречены ее повторять; они обречены на глупые поступки.
источник
Регистры
FS
иGS
являются сегментными регистрами. У них нет цели, определяемой процессором, но вместо этого цель задается операционной системой, в которой они запущены. В 64-разрядной версии WindowsGS
регистр используется для указания структур, определенных операционной системой.FS
иGS
обычно используются ядрами ОС для доступа к памяти, зависящей от потока. В WindowsGS
регистр используется для управления памятью, зависящей от потока. Ядро linux используетGS
для доступа к памяти, зависящей от процессора.источник
*dest++ = lookup[*src++];
что в противном случае было бы довольно неудобным, если бы dest, lookup и src находились в трех несвязанных местах.FS используется для указания на блок информации о потоках (TIB) в процессах Windows.
одним из типичных примеров является ( SEH ), который хранит указатель на функцию обратного вызова в
FS:[0x00]
.GS обычно используется как указатель на локальное хранилище потока (TLS). и один пример, который вы, возможно, видели раньше, - это защита стека канареек (stackguard), в gcc вы можете увидеть что-то вроде этого:
источник
Согласно руководству Intel, в 64-битном режиме эти регистры предназначены для использования в качестве дополнительных базовых регистров в некоторых вычислениях линейных адресов. Я взял это из раздела 3.7.4.1 (стр. 86 в наборе из 4 томов). Обычно, когда ЦП находится в этом режиме, линейный адрес совпадает с эффективным адресом, потому что сегментация часто не используется в этом режиме.
Таким образом, в этом плоском адресном пространстве FS и GS играют роль в адресации не только локальных данных, но и определенных структур данных операционной системы (стр. 2793, раздел 3.2.4), таким образом, эти регистры предназначались для использования операционной системой, однако эти конкретные конструкторы определить.
При использовании переопределений как в 32-битном, так и в 64-битном режимах есть некоторые интересные уловки, но это касается привилегированного программного обеспечения.
С точки зрения «первоначальных намерений» сложно сказать, кроме того, что это просто дополнительные регистры. Когда ЦП находится в режиме реального адреса , это похоже на то, что процессор работает как высокоскоростной 8086, и эти регистры должны быть явно доступны программе. Ради настоящей эмуляции 8086 вы должны запустить ЦП в режиме виртуального 8086, и эти регистры не будут использоваться.
источник
TL; DR;
Просто для доступа к данным за пределами сегмента данных по умолчанию (DS). Точно как ES.
Долгое чтение:
Ну, почти, но DS - это не «какой-то» сегмент данных, а сегмент по умолчанию. Все ли операции выполняются по умолчанию (* 1). Здесь расположены все переменные по умолчанию - по сути
data
иbss
. В некотором роде это одна из причин, по которой код x86 довольно компактен. Все важные данные, к которым чаще всего обращаются (плюс код и стек), находятся в пределах 16-битного сокращенного расстояния.ES используется для доступа ко всему остальному (* 2), за пределами 64 KiB DS. Как текст текстового редактора, ячейки электронной таблицы или графические данные графической программы и так далее. В отличие от часто предполагаемого, к этим данным не так часто обращаются, поэтому необходимость в префиксе вредит меньше, чем использование более длинных полей адреса.
Похоже, это лишь незначительное раздражение, что DS и ES, возможно, придется загружать (и перезагружать) при выполнении строковых операций - это, по крайней мере, компенсируется одним из лучших наборов инструкций по обработке символов того времени.
Что действительно больно, так это когда пользовательские данные превышают 64 КиБ и нужно начинать операции. Хотя некоторые операции просто выполняются с одним элементом данных за раз (подумайте
A=A*2
), для большинства требуется два (A=A*B
) или три элемента данных (A=B*C
). Если эти элементы находятся в разных сегментах, ES будет перезагружен несколько раз за операцию, что приведет к значительным накладным расходам.Вначале, с небольшими программами из 8-битного мира (* 3) и такими же небольшими наборами данных, это не было большой проблемой, но вскоре стало основным узким местом в производительности - и, тем более, настоящей головной болью для программисты (и компиляторы). В 386 Intel наконец-то облегчила задачу, добавив еще два сегмента, так что любая последовательная унарная , двоичная или троичная операция с элементами, распределенными в памяти, могла выполняться без постоянной перезагрузки ES.
Для программирования (по крайней мере, в сборке) и проектирования компилятора это было большим преимуществом. Конечно, могло быть и больше, но с тремя горлышками бутылки практически не было, так что не нужно перебарщивать.
В названии буквы F / G - это просто буквенные продолжения после E. По крайней мере, с точки зрения дизайна процессора ничего не связано.
* 1 - Использование ES для назначения строки является исключением, поскольку необходимы просто два сегментных регистра. Без них не было бы много пользы - или всегда нужен префикс сегмента. Это могло убить одну из удивительных особенностей - использование (неповторяющихся) строковых инструкций, что привело бы к экстремальной производительности из-за их однобайтовой кодировки.
* 2 - Итак, оглядываясь назад, «Сегмент всего остального» было бы лучше, чем «Дополнительный сегмент».
* 3 - Всегда важно помнить, что 8086 предназначалась только как временная мера, пока 8800 не была закончена, и в основном предназначалась для мира встраиваемых систем, чтобы поддерживать клиентов 8080/85.
источник