Использование регистров сегментации

Я пытаюсь понять, как управление памятью идет на низком уровне и у меня есть пара вопросов.

1) В книге о языке ассемблера, написанной Кипом Р. Ирвином, говорится, что в реальном режиме первые три сегментных регистра загружаются с базовыми адресами кода, данных и сегмента стека при запуске программы. Это немного двусмысленно для меня. Указаны ли эти значения вручную или ассемблер генерирует инструкции для записи значений в регистры? Если это происходит автоматически, как он узнает, каков размер этих сегментов?

2) Я знаю, что в Linux используется плоская линейная модель, то есть сегментация очень ограниченным образом. Кроме того, в соответствии с разделом «Понимание ядра Linux». Дэниел П. Бове и Марко Чезати выделяют четыре основных сегмента: пользовательские данные, пользовательский код, данные ядра и код ядра в GDT. Все четыре сегмента имеют одинаковый размер и базовый адрес. Я не понимаю, зачем нужны четыре из них, если они отличаются только типом и правами доступа (все они выдают один и тот же линейный адрес, верно?). Почему бы не использовать только один из них и записать его дескриптор во все регистры сегментов?

3) Как операционные системы, которые не используют сегментацию, делят программы на логические сегменты? Например, как они отличают стек от кода без дескрипторов сегментов. Я читал, что пейджинг может быть использован для обработки таких вещей, но я не понимаю, как.

Ответы на вопрос(3)

Ваш ответ на вопрос