загрузчик - переключение процессора в защищенный режим.

у меня возникли трудности с пониманием того, как работает простой загрузчик. Загрузчик, о котором я говорю, - это тот, что из курса MITs "проектирование операционных систем".

во-первых, позвольте мне показать вам фрагмент кода сборки, который выполняет BIOS:

[f000:fec3]    0xffec3: lidtw  %cs:0x7908
[f000:fec9]    0xffec9: lgdtw  %cs:0x7948
[f000:fecf]    0xffecf: mov    %cr0,%eax
[f000:fed2]    0xffed2: or     x1,%eax
[f000:fed6]    0xffed6: mov    %eax,%cr0
[f000:fed9]    0xffed9: ljmpl  x8,xffee1

судя по всему, этот код создает таблицу прерываний и таблицу дескрипторов, а затем включается защищенный режим.

  1. почему мы переходим в защищенный режим в БИОСе? Не стоит этот загрузчик работает в реальном режиме (btw - почему она должна работать по-настоящему? режим?)
  2. Я искал, но нигде не нашел как именно инструкция ljmpl работает, и разница между это и ljmp и обычная jmp-I был бы признателен, если бы кто-то точку в правильном направлении.
  3. почему мы выполняем прыжок? Что цель этой инструкции?

переход к коду загрузчика -

# Switch from real to protected mode, using a bootstrap GDT
# and segment translation that makes virtual addresses
# identical to their physical addresses, so that the
# effective memory map does not change during the switch.
lgdt    gdtdesc
movl    %cr0, %eax
orl     $CR0_PE_ON, %eax
movl    %eax, %cr0

# Jump to next instruction, but in 32-bit code segment.
# Switches processor into 32-bit mode.
ljmp    $PROT_MODE_CSEG, $protcseg
  1. он говорит что процессор находится в реальный режим - но мы только что видели, что BIOS переключается в защищенный режим... Я в замешательстве-как это может быть? возможно?
  2. как мы переключаемся в режим 32bit? Что? заставляет процессор волшебным образом идти в 32-битный режим из-за ljmp инструкция?

и еще одна вещь, которую я не понимаю - когда я отслеживаю выполнение загрузчика с gdb, я вижу, что выполняется следующая инструкция (это инструкция ljmp из загрузчика код):

ljmp   x8,x7c32

но когда я посмотрел на .файл asm я увидел следующее:

ljmp   xb866,x87c32

полностью потеряно здесь-как пришла инструкция, написанная в .ASM-файл и выполняемая инструкция отличаются? У меня есть предчувствие, что это связано с защищенным режимом и как он переводит адреса, но я действительно не понимаю.

Я был бы признателен за любую помощь!

2 ответов


  1. некоторые реализации BIOS переходят в защищенный режим перед входом в загрузчик. Большинство-нет. Возможно, что BIOS переключается в защищенный режим на короткий период и переключается обратно перед переходом в загрузчик, что позволит ему использовать некоторые преимущества защищенного режима (например, 32 бит-размер адреса по умолчанию). Причина, по которой загрузчик должен быть в реальном режиме, заключается в том, что большинство функций BIOS работают только в реальном режиме, поэтому вам нужно быть в реальном режиме, чтобы использовать их.

  2. ljmp задает сегмент кода для переключения в дополнение к адресу для перехода. Они настолько похожи, что (по крайней мере, в Газе) ассемблер переключит jmp с 2 операндами на ljmp для вас.

  3. ljmp-один из единственных способов изменить регистр cs. Это необходимо сделать для активации защищенного режима, так как регистр cs должен содержать селектор для сегмента кода в GDT. (В случае, если вы хотите знать, другие способы изменение cs-это far call, far return и interrupt return)

  4. см. пункт 1. Либо BIOS переключился обратно в реальный режим, либо этот загрузчик не будет работать с этим BIOS.

  5. см. пункт 3. Он изменяет cs, чтобы указать 32-битный сегмент кода, поэтому процессор переходит в 32-битный режим.

  6. когда вы смотрели на .ASM-файл, инструкция была интерпретирована как если бы размер адреса был 32 бит, но GDB интерпретировал его как если бы размер адреса 16 бит. Данные по адресу инструкции будут 0xEA 32 7C 08 00 66 B8. EA-это код операции прыжка в длину. В 32-битном адресном пространстве адрес будет указан с использованием следующих четырех байтов для адреса 0x87C32, но в 16-битном адресном пространстве используется только 2 байта для адреса 0x7C32. 2 байта после адреса указывают запрошенный сегмент кода, который будет 0xB866 в 32-битном режиме и 0x0008 в 16-битном режиме. 0x66 B8-это начало следующего инструкция, которая перемещает 16-битное немедленное значение в регистр ax, вероятно, для настройки сегментов данных для защищенного режима.


почему мы переходим в защищенный режим в BIOS? Не должен ли загрузчик работать в реальном режиме (кстати-почему он должен работать в реальном режиме?)

защищенный режим просто предлагает намного больше возможностей, чем realmode: по сути, механизм защиты привилегий Intel CPU (http://en.wikipedia.org/wiki/Ring_ (computer_security), 32-разрядный режим выполнения и т.д.

Я искал, но не нашел нигде точно, как работает инструкция ljmpl, и разница между ним и ljmp и обычный jmp-я был бы признателен, если бы кто-то указал в правильном направлении.

ljmpl и ljmp здесь контекстуально.

почему мы выполняем прыжок? Какова цель этой инструкции?

это требуется, как описано в руководстве Intel, и документировано в коде, показанном ниже..

для перехода от реального к защищенному он реализован в загрузчике stage2 здесь:

http://src.illumos.org/source/xref/illumos-gate/usr/src/grub/grub-0.97/stage2/asm.S#real_to_prot

974   /* load the GDT register */
975   DATA32  ADDR32  lgdt    gdtdesc
976 
977   /* turn on protected mode */
978   movl    %cr0, %eax
979   orl $CR0_PE_ON, %eax
980   movl    %eax, %cr0
981 
982   /* jump to relocation, flush prefetch queue, and reload %cs */
983   DATA32  ljmp    $PROT_MODE_CSEG, $protcseg
984

Как вы можете видеть, каждая часть кода имеет функцию, и ljmp по существу, чтобы очистить очередь предварительной выборки, как требуется в руководстве Intel, я не могу вспомнить, где.