Я пытаюсь понять основы операционных систем и нашел курс по этому вопросу в OCW (название 6.828). Я нашел код загрузчика в лабах курса, пробовал, но не понял следующую часть кода:
# Enable A20:
# For backwards compatibility with the earliest PCs, physical
# address line 20 is tied low, so that addresses higher than
# 1MB wrap around to zero by default. This code undoes this.
seta20.1:
inb $0x64,%al # Wait for not busy
testb $0x2,%al
jnz seta20.1
movb $0xd1,%al # 0xd1 -> port 0x64
outb %al,$0x64
seta20.2:
inb $0x64,%al # Wait for not busy
testb $0x2,%al
jnz seta20.2
movb $0xdf,%al # 0xdf -> port 0x60
outb %al,$0x60
Как мы проверяем, занят ли порт 0x64 и почему этот порт используется для включения бита A20? Далее, чтобы заставить чип работать в 32-битном режиме, конфигурация GDT выполняется следующим образом:
# 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
# Bootstrap GDT
.p2align 2 # force 4 byte alignment
gdt:
SEG_NULL # null seg
SEG(STA_X|STA_R, 0x0, 0xffffffff) # code seg
SEG(STA_W, 0x0, 0xffffffff) # data seg
gdtdesc:
.word 0x17 # sizeof(gdt) - 1
.long gdt # address gdt
Что делает приведенный выше код? Что означают строки, начинающиеся с «.»? Кроме того, существует два формата ассемблерного кода: .S и .asm. В чем разница между ними?
SEG_NULL
иSEG
- это макросы, определенные ранее, не показанные в вашем вопросе. GDT — это таблица, содержащая данные, описывающие сегменты. Эти данные настраиваются с помощью макросов.gdtdesc
, в свою очередь, описывает GDT, как говорится в комментарии, размер и расположение. Он нужен для инструкцииLGDT
. 31.01.2015