Мне сложно понять, как работает простой загрузчик. Я говорю о загрузчике из курса 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
Судя по всему, этот код устанавливает таблицу прерываний и таблицу дескрипторов, а затем включает защищенный режим.
Переходим к коду загрузчика -
# 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
И еще кое-что, чего я не понимаю - когда я отслеживаю выполнение загрузчик с gdb, я вижу, что выполняется следующая инструкция (это инструкция ljmp из кода загрузчика):
ljmp $0x8,$0x7c32
Но когда я заглянул в файл .asm, то увидел следующее:
ljmp $0xb866,$0x87c32
Здесь полностью потеряно - почему инструкция написанные в файле .asm и выполняемые инструкции отличаются? У меня есть подозрение, что это связано с защищенным режимом и тем, как он переводит адреса, но я этого не понимаю.
Буду признателен за любую помощь!