После загрузки GDT
# Load the GDT.
mov $gdt_descriptor, %ecx
lgdt (%ecx)
mov $0x10, %cx
mov %cx, %ds
mov %cx, %es
mov %cx, %fs
mov %cx, %gs
mov %cx, %ss
ljmp $0x8, $1f
1: mov $kernel_stack, %esp
Я не могу понять, что делает этот код. Зачем перемещать $0x10 в cx, а затем в другие регистры после загрузки GDT? А что делает инструкция ljmp?
1 ответ
Он загружает кэши дескрипторов сегментов (внутри ЦП) из нового GDT, который lgdt
рассказал о процессоре.
Описания сегментов внутри ЦП не обновляются автоматически, когда вы изменяете записи таблицы или меняете точку таблицы.
Вы даже можете переключиться обратно в реальный режим с DS base=0 limit=4GiB (и то же самое для ES и SS), и использовать 32-битные адреса в реальном режиме до следующего mov ds, r16
или же pop ds
Инструкция перезаписывает описание кэшированного сегмента. (Это называется большой / огромный нереальный режим, огромный, если вы делаете это также для CS, но это менее удобно, потому что прерывания в реальном режиме сохраняют только IP, а не EIP.)
ljmp
это far jmp
, который устанавливает CS (в этом случае использовать дескриптор, отличный от дескрипторов данных). х86 не позволяет mov
или же pop
установить CS, только дальний прыжок. Предположительно, процессор не меняет режимы с помощью этого перехода, в противном случае источник asm должен будет использовать .code32
или же .code16
директивы.
Целью является 1:
ярлык, в f
в обратном направлении. Итак mov
в %esp
декодируется / запускается с любыми настройками сегмента кода, которые были в индексе GDT 1. (Младшие 3 бита селекторов сегмента являются битами разрешения, поэтому $8
является индексом GDT 1, и $0x10
является индексом GDT 2.)
Это немного странно отделять mov
в %ss
из инструкции, которая устанавливает %esp
потому что x86 автоматически откладывает прерывания до инструкции после mov
в SS
, Это позволяет вам настроить SS:SP без использования cli
/ sti
, но, вероятно, этот код выполняется с уже отключенными прерываниями. Этот код, вероятно, запускается только один раз во время загрузки, поэтому имеет смысл просто отключать прерывания на столько времени, сколько необходимо для установки новых GDT и IDT.