# #assembly #x86 #operating-system #xv6 #gdt
Вопрос:
В bootasm.S
.p2align 2 # force 4 byte alignment
gdt:
SEG_NULLASM # null seg
SEG_ASM(STA_X|STA_R, 0x0, 0xffffffff) # code seg
SEG_ASM(STA_W, 0x0, 0xffffffff) # data seg
gdtdesc:
.word (gdtdesc - gdt - 1) # sizeof(gdt) - 1
.long gdt # address gdt
И это используется в
lgdt gdtdesc
Разве первое слово gdtdesc не должно быть размером gdt в байтах? В данном случае это 3*8=24
, что равно gdtdesc - gdt
.
Почему gdtdesc - gdt - 1
здесь?
Комментарии:
1. Причина, по которой это ограничение, а не размер, заключается в том, что вы не можете уместить размер gdt максимальной длины (8192 записи) в 16 бит.
Ответ №1:
Согласно руководству, lgdt
требуется размер GDT в байтах, но также описывает его как «предел». Эта формулировка неоднозначна между размером и адресом последнего байта. (Что имело бы смысл как способ разрешить более высокий предел без обертывания 16-битного предела.)
Но примеры в https://wiki.osdev.org/GDT_Tutorial используйте sizeof(gdt), так что это либо ошибка в xv6, либо в учебнике osdev.
https://wiki.osdev.org/Global_Descriptor_Table согласен с xv6, говоря, что «ограничение»-это размер 1, в отличие от учебника GDT. В этом есть смысл:
Размер
size
таблицы вычитается на 1. Это связано с тем, что максимальное значение размера составляет 65535, в то время как GDT может составлять до 65536 байт (максимум 8192 записи). Кроме того, ни один GDT не может иметь размер 0.
Если вы хотите подтвердить детали, ознакомьтесь с руководствами Intel или AMD; мы надеемся, что они прояснят этот момент где-нибудь в деталях разработки системы, отдельно от справочной записи набора инструкций для lgdt
.
Или вы надеетесь, что они это сделают. Но, к сожалению, Intel говорит:
Раздел 2.4.1 Регистр глобальных таблиц дескрипторов (GDTR)
«ограничение таблицы определяет количество байтов в таблице».
Что, вероятно, просто означает, что тот, кто это написал, настолько увлекся идеей ограничения = смещения последнего байта = размера, что даже не понял, что это неясно. Сами ограничения сегмента (в записях GDT) также работают таким образом, используя 0xFFFFF
(с детализацией=страница), чтобы указать ограничение как самую верхнюю часть адресного пространства 4GiB, т. е. неограниченное.
Комментарии:
1. Можно подумать. Вместо этого возникает еще большая путаница 🙂 В разделе 2.4.1 Глобальный регистр таблиц дескрипторов (GDTR) говорится: «ограничение таблицы определяет количество байтов в таблице» . Это intel, еще не проверял AMD.
2. @Jester: Есть ли какие-либо фактические сомнения в том, что предел должен быть смещением последнего байта, а не
sizeof
? например, кто-нибудь дважды проверял, установив limit=15, а затем пытаясь использовать 2-ю запись? Я предполагаю, что тот, кто написал этот раздел руководства, просто думал о том, как работают ограничения на сегменты в записях GDT, указывая самый высокий допустимый адрес (или страницу).3.
15
работает, по крайней мере, с kvm. Кажется, это предел, да.4. Руководство по системному программированию AMD кажется более четким: «Ограничение. 2 байта. Эти биты определяют 16-битный предел, или размер, GDT в байтах. Предельное значение добавляется к базовому адресу, чтобы получить адрес конечного байта GDT.» «или размер» здесь тоже немного сбивает с толку, но затем он объясняет, что он дает адрес последнего байта. Далее говорится: » Исключение общей защиты (#GP) возникает, если программное обеспечение пытается получить доступ к дескриптору за пределами ограничения GDT.» Кроме того, это считается «псевдо-дескриптором», что подразумевает обычную семантику ограничения.
5. О, и я тестировал на AMD Ryzen 1700x. Так что Intel могла бы сделать это по-другому. Если есть какие-либо сомнения, я бы, тем не менее, установил для поля размер, а не предел, так как это будет работать одинаково в обеих реализациях.