Уголовный кодекс процессоров Intel c архитектурой IA32 (с изменениями и дополнениями)
В выпуске:
а также: Зубков тоже ошибается...
Глава I ОБЩИЕ ПОЛОЖЕНИЯ (важно прочитать и запомнить!)
В это трудно поверить, но весь механизм защиты процессора Intel обеспечивается 3-мя флагами (+ еще 2 дополнительных при использовании страничной адресации) и 5-тью полями. Казалось бы, какую защиту могут обеспечить эти несчастные 8 (+2 до кучи) ребят? На самом же деле все довольно продумано и все чего надо они обеспечивают.
Флаги, обеспечивающие защитный механизм: (просто запомните их)
Поля, обеспечивающие защитный механизм: (просто запомните их)
THAT'S ALL! (это все!). Вся аппаратная защита такого монстра, как, скажем, Pentium 4, целиком и полностью стоит на описанных выше битиках! (я от нечего делать даже подсчитал - всего 35 бит! Т.е. все аппаратные защитные структуры умещаются (почти) в одно двойное слово! Честно говоря, это немного шокирует...
Если кому-то вздумается взглянуть на картинки - они есть в предыдущих выпусках.
Поле "Лимит" дескриптора сегмента призвано уберечь программы (процедуры) от незаконного обращения к памяти за пределами, установленными этим полем. Эффективное (реальное) значение лимита зависит от флага гранулярности G. Для сегментов данных, лимит также зависит от флага E (направление роста) и флага B дескриптора.
Влияние бита G на поле "Лимит" изучено и рассмотрено со всех сторон в предыдущих выпусках, но напомню: если бит G=0, то лимит сегмента совпадает со значением одноименного поля дескриптора; очевидно, что в данном случае сегмент может иметь длину от 0 до FFFFFh (1Мб). Если флаг G=1, то реальный лимит сегмента равен содержимому поля "Лимит" дескриптора, умноженному на 4Кб (FFFh). Очевидно, сегмент в этом случае может занимать от 4Кб до 4Гб.
ВАЖНО! Если бит G=1, то младшие 12 бит адреса НЕ ПРОВЕРЯЮТСЯ НА ПРЕВЫШЕНИЕ ЛИМИТА! Т.е. если создать дескриптор сегмента с G=1, и полем "Лимит" равным 0, то смещения от 0 до FFFh ВСЕ РАВНО ДОСТУПНЫ ДЛЯ ОБРАЩЕНИЯ! Т.е. процессор ИГНОРИРУЕТ младшие 12 бит при проверке на превышение лимита. Вообще, как где-то было верно подмечено, бит гранулярности - это чисто радиолюбительский трюк. Что еще небезынтересно знать - умножение на 4Кб равносильно сдвигу на 12 влево, причем младшие 12 бит при этом заполняются единицами.
Итак, процессор сгенерирует исключение #GP (самое страшное и главное, недаром ему присвоили 13 номер) в следующих случаях:
Это 4 заповеди данной главы.
Существует еще один размытый момент, который мы сейчас обсудим во всех нюансах. Этот момент - растущие "ВНИЗ" сегменты данных. Тут сразу нужно сказать - сегмент никуда не растет, это образное выражение. Все дело в том, что у растущих "ВНИЗ" сегментов поле "Лимит" в дескрипторе определяет НИЖНЮЮ границу сегмента, а ВЕРХНЯЯ граница ВСЕГДА (!) (подчеркнуть три раза) равна FFFFh (1Мб) если бит B=0 и FFFFFFFFh (4Гб) если бит B=1. Откуда взялся бит B? Вспоминаем структуру дескриптора, помните флаг D/B? Вот это он и есть. Теперь у некоторых возникает вопрос: если у нас определена НИЖНЯЯ граница сегмента (поле "Лимит") и верхняя (1Мб или 4Гб), то нахрена тогда поле БАЗА в дескрипторе? Спокойно! Стоит лишь чуть-чуть подумать и все станет ясно: поле "Лимит" хоть и определяет нижнюю границу, но все равно ОТСЧИТЫВАЕТСЯ ОТ БАЗЫ! Т.е. фактически нижняя граница у растущих ВНИЗ сегментов равна: содержимое поля "Лимит" дескриптора + содержимое поля "База" дескриптора. Вот для того нам база и нужна... (вообще с тем что поле "Лимит" всегда зависит от поля "База" интеловцы imho погорячились, т.к. весь этот механизм в конечном счете выгоден только при использовании 36-разрядного механизма адресации PAE-36. У кого есть какие-нибудь соображения на этот счет - прошу поделиться).
Здесь интересен другой момент (подумайте и вышлите свои соображения на brokensword@mail.ru): если у нас есть растущий ВНИЗ сегмент, у которого сброшен бит B, т.е. верхняя граница этого сегмента равна FFFFh, а поле "База" в дескрипторе ПРЕВЫШАЕТ значение 1Мб. Кто может ответить - какие смещения доступны в таком сегменте?
Наконец, позволю себе привести фрагмент из книги тов. Зубкова С.В. по поводу растущих вниз сегментов: "Бит направления роста сегмента (E) обращает смысл лимита сегмента. В сегментах с этим битом, сброшенным в ноль, разрешены абсолютно все смещения от 0 до лимита, а если этот бит 1, то допустимы все смещения, кроме от 0 до лимита. Про такой сегмент говорят, что он растет сверху вниз, так как если лимит, например, равен -100, допустимы смещения от -100 до 0, а если лимит увеличить, станут допустимыми еще меньшие смещения". Здесь уважаемый Зубков запорол страшную ерунду, т.к., во-первых, не "от 0 до лимита", а от "(базы) до (база+лимит)", и в случае растущих вниз сегментов, помимо той же самой ошибки, он рассмотрел только случай когда B=1 (т.е. верхняя граница равна 4Гб), тогда действительно доступны ВСЕ смещения, кроме от база+лимит до 0 ("вниз"). Да и с примером он тоже намудрил. Если кто-то не согласен - пишите, обсудим.
Еще раз нелишне повторить, что суть проверок лимитов заключается в том, чтобы не дать программам разгуляться по всей памяти, каждый сверчок должен знать свой шесток и не вылазить за отведенные ему границы.
Данная глава была бы не полной, если не вспомнить о том, что процессор (помимо проверки лимитов сегментов) проверяет также лимиты таблиц дескрипторов, инфа о которых содержится в регистрах GDTR, IDTR, LDTR и TR. #GP будет сгенерировано, если произойдет попытка обращения к дескриптору, лежащему за пределами таблицы дескрипторов.
Вот теперь по теме "Проверка границ" больше добавить действительно нечего. В следующем выпуске мы рассмотрим следующую главу УК IA-32 под названием "Проверка типов".
http://subscribe.ru/archive/comp.soft.prog.intelpm/ - здесь можно скачать архив рассылки.
www.wasm.ru - сайт, посвященный программированию на асме под win (и не только), самая крупная коллекция статей в рунете, все самое новое и нужное.
rusfaq.ru - задай любой вопрос по асму (и жди ответа).
[C] Broken Sword