Дальний прыжок в ГДТ в загрузчика
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, а затем в другие регистры
1 ответ:
X86 поддерживает две схемы виртуальной памяти (читайте об этом здесь):
Большинство операционных систем хотят использовать подкачку и не хотят сегментации, но ее необходимо и нельзя просто отключить. Таким образом, фокус в том, чтобы отключить его эффект, поскольку его там не было. Обычно это можно сделать, создав 4 больших перекрывающиеся дескрипторы сегментов (рядом с нулевым сегментом):
- сегментация, должна управляться с помощью таблицы сегментов, GDT.
- подкачка, необязательно, управляется с помощью таблицы страниц, PDT.
- индекс сегмента 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