загрузчик - переключение процессора в защищенный режим - PullRequest
25 голосов
/ 06 марта 2011

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

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

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

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

  1. Почему мы переходим в защищенный режим в BIOS?Разве загрузчик не должен работать в реальном режиме (кстати, зачем ему работать в реальном режиме?)
  2. Я искал, но нигде не нашел точно, как работает инструкция ljmpl, и в чем разница?и ljmp и обычный jmp - я был бы признателен, если бы кто-то указывал в правильном направлении.
  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. Как перейти в 32-битный режим?Что заставляет процессор магически переходить в 32-битный режим из-за инструкции ljmp?

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

ljmp   $0x8,$0x7c32

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

ljmp   $0xb866,$0x87c32

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

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

Ответы [ 2 ]

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

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

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

  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-битное непосредственное значение в регистр топора, вероятно, для установки сегментов данных для защищенного режима.

2 голосов
/ 18 февраля 2012

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

Защищенный режим просто предлагает гораздо больше возможностей, чем реальный режим: по сути, механизм привилегий защитного кольца ЦП Intel (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, я не могу вспомнить, где.

...