Дальний прыжок в ГДТ в загрузчика



flush_gdt:
lgdt [gdtr]
jmp 0x08:complete_flush

complete_flush:
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
ret


Я не могу понять, что делает этот код . flush_gdt - это метка, затем lgdt [gdtr] загружает указатель 48-bit в регистр gdtr, а затем из jmp 0x08:complet_flush.

Что делает инструкция jmp ? и тогда почему мы перемещаем 0x10 в ax, а затем в другие регистры

550   1  

1 ответ:

X86 поддерживает две схемы виртуальной памяти (читайте об этом здесь):

  • сегментация, должна управляться с помощью таблицы сегментов, GDT.
  • подкачка, необязательно, управляется с помощью таблицы страниц, PDT.
Большинство операционных систем хотят использовать подкачку и не хотят сегментации, но ее необходимо и нельзя просто отключить. Таким образом, фокус в том, чтобы отключить его эффект, поскольку его там не было. Обычно это можно сделать, создав 4 больших перекрывающиеся дескрипторы сегментов (рядом с нулевым сегментом):
  • индекс сегмента 0: нулевой дескриптор сегмента
  • индекс сегмента 1: дескриптор сегмента кода для привилегированного режима (ядра)
  • индекс сегмента 2: дескриптор сегмента данных для привилегированного режима (ядра)
  • индекс сегмента 3: дескриптор сегмента кода для непривилегированного (пользовательского) режима
  • индекс сегмента 4: дескриптор сегмента данных для непривилегированного (пользователя) режим

Все эти сегменты начинаются с 0x00000000 до 0xffffffff, так что вы в конечном итоге получаете перекрывающиеся большие сегменты, которые являются привилегированным кодом и данными, и непривилегированным кодом и данными в то же время. Это должно открыть виртуальную память и отключить эффект сегментации.

Процессор использует селекторы сегментов (сегментные регистры cs, ds, ss ...) чтобы найти правильный сегмент (опять же, сегментация обязательна).

Каждый селектор сегмента имеет размер 16 бит и имеет следующую компоновку (источник):

Введите описание изображения здесь

  • Первые два бита указывают на то, что уровень привилегий x86 поддерживает 4 уровня, но только два из них фактически используются (00 самый высокий и 11 самый низкий).

  • Третий бит указывает, что таблица должна использоваться, главным образом 0, GDT.

  • остальные 13 бит указывают индекс сегмента.

Если вы интерпретировали 0x08, который загружен в cs, он будет в двоичный код:

0000000000001     0         00
index 1 (code)   GDT    privileged

И 0x10, который загружен в ds, ss, ... :

0000000000010     0         00
index 2 (data)   GDT    privileged

Если Вы читаете селекторы сегментов любой программы пользовательского режима, вы должны видеть, что значение cs равно 27 (0x1b) что означает:

0000000000011     0         11
index 3 (code)   GDT   non-privileged

И селекторы данныхds, ss, ..., следует хранить 35 (0x23):

0000000000100     0         11
index 4 (data)   GDT   non-privileged

Селекторы сегментов данных (регистры), могут быть легко изменены с помощью простой инструкции mov, но cs не может быть использован с mov, поэтому вы используете jmp 0x08:OFFSET, чтобы загрузите конфигурации сегментов в селектор сегментов кода.

Comments

    Ничего не найдено.