mirror of
https://github.com/0xAX/linux-insides.git
synced 2024-11-16 04:59:13 +00:00
Уточнения адреса загрузки
This commit is contained in:
parent
1a0d714f8e
commit
c27b4dced5
@ -325,16 +325,13 @@ state.gs = state.fs = state.es = state.ds = state.ss = segment;
|
||||
state.cs = segment + 0x20;
|
||||
```
|
||||
|
||||
Это означает, что после начала настройки ядра регистры сегмента будут иметь следующие значения:
|
||||
В моём случае, ядро загружается по адресу `0x10000`. Это означает, что после начала настройки ядра регистры сегмента будут иметь следующие значения:
|
||||
|
||||
```
|
||||
gs = fs = es = ds = ss = 0x1000
|
||||
cs = 0x1020
|
||||
```
|
||||
|
||||
|
||||
В моём случае, ядро загружается по адресу `0x10000`.
|
||||
|
||||
После перехода на метку `start_of_setup`, необходимо соблюсти следующие условия:
|
||||
|
||||
* Убедиться, что все значения всех сегментных регистров равны
|
||||
|
@ -443,9 +443,9 @@ Aligned - 16
|
||||
|
||||
`GDT_ENTRY` - это макрос, который принимает флаги, базовый адрес, предел и создаёт запись в GDT. Для примера посмотрим на запись сегмента кода. `GDT_ENTRY` принимает следующие значения:
|
||||
|
||||
* базовый адрес - 0
|
||||
* предел - 0xfffff
|
||||
* флаги - 0xc09b
|
||||
* базовый адрес - `0`
|
||||
* предел - `0xfffff`
|
||||
* флаги - `0xc09b`
|
||||
|
||||
Что это значит? Базовый адрес сегмента равен 0, а предел (размер сегмента) равен `0xffff` (1 Мб). Давайте посмотрим на флаги. В двоичном виде значение `0xc09b` будет выглядеть следующим образом:
|
||||
|
||||
@ -506,7 +506,9 @@ protected_mode_jump(boot_params.hdr.code32_start, (u32)&boot_params + (ds() << 4
|
||||
|
||||
Давайте заглянем внутрь `protected_mode_jump`. Как я уже писал выше, вы можете найти его в `arch/x86/boot/pmjump.S`. Первый параметр находится в регистре `eax`, второй в `edx`.
|
||||
|
||||
В первую очередь мы помещаем адрес `boot_params` в регистр `esi` и адрес регистра сегмента кода `cs` (0x1000) в `bx`. Далее мы сдвигаем `bx` на 4 бита и добавляем к нему адрес метки `2` (после этого мы будем иметь физический адрес метки `2` в `bx`) и переходим на метку `1`. Далее мы помещаем сегмент данных и сегмент состояния задачи в регистры `cs` и `di`:
|
||||
В первую очередь мы помещаем адрес `boot_params` в регистр `esi` и адрес регистра сегмента кода `cs` в `bx`. Далее мы сдвигаем `bx` на 4 бита и добавляем к нему адрес метки `2` (`(cs << 4) + in_pm32`, физический адрес для "прыжка" после перехода в 32-битный режим) и переходим на метку `1`. После этого `in_pm32` в метке `2` будет перезаписан следующим образом: `(cs << 4) + in_pm32`.
|
||||
|
||||
Далее мы помещаем сегмент данных и сегмент состояния задачи в регистры `cx` и `di`:
|
||||
|
||||
```assembly
|
||||
movw $__BOOT_DS, %cx
|
||||
@ -535,7 +537,7 @@ movl %edx, %cr0
|
||||
|
||||
* `0x66` - префикс размера операнда, который позволяет смешивать как 16-битный, так и 32-битный код,
|
||||
* `0xea` - опкод инструкции перехода,
|
||||
* `in_pm32` - смещение сегмента
|
||||
* `in_pm32` - смещение сегмента или `(cs << 4) + in_pm`
|
||||
* `__BOOT_CS` - сегмент кода, на который мы хотим перейти.
|
||||
|
||||
После этого мы наконец-то в защищённом режиме:
|
||||
|
Loading…
Reference in New Issue
Block a user