Здравствуйте! Начал изучать асм совсем недавно, вот появился вопрос. В доках пишут, что в Винде каждому процессу выделяется адресное пространство в 4 гб (хотя использовать он может только 2, не суть важно). Так вот, 4 гб. Я не могу понять, как физически это представлено? Ясно, что есть ЛИНЕЙНОЕ адресное пространство равное 4 гб. С помощью страничной модели мы проецируем это пространство на ФИЗИЧЕСКОЕ пространство. Но каким боком здесь ВИРТУАЛЬНОЕ адресное пространство (4 гб для процесса)??? В мануалах от Интела я пояснений не нашел. UPD. Вот есть у нас логический адрес: селектор:16бит + смещение:32бита. Селектор из GDT получает базу и размер сегмента, складывает со смещением и получает линейный адрес. Далее страничная модель и с ней все понятно. Ясно, что может быть много сегментов и все они должны укладываться в ЛИНЕЙНОЕ адресное пространство. А как же тогда 4 гб для процесса??? Не понимаю )))
Непонятно какую роль играет селектор. Он только ссылается на дескриптор? Ведь исходя из схемы трансляции логического (виртуального) адреса, сам селектор в адресации не используется, используется только базща из дескриптора. Тогда почему Broken Sword пишет
А сколько должно быть? различными значениями селекторов ты не добьешься различных 4гигабайт, поэтому гигабайт все равно останется четыре. Хотя спор на эту тему на васме уже был не так давно и даже в нескольких экземплярах.
Не только. Он еще содержит текущий уровень привелегий. Сам дескриптор на самом деле находятся в теневой облости селектора.
spec А тут целый клубок проблем, и надо помнить сразу несколько вещей. В интеловских мануалах используется терминология самого Интела. Линейный адрес -- чисто интеловская вещь, физический -- общеупотребительная, но всё же относящаяся к железу. Ну а виртуальный адрес -- общеупотребительный термин, но имеющий отношение не столько к железу, сколько к ПО, и поэтому искать его определение у Интела бесполезно. Вторая вещь, которую нужно помнить: Винда -- кроссплатформенная система. Создавалась она не только для ИА-32, но и для нескольких других процессоров; соответственно, её терминология ни к какому конкретному процессору не привязана. Была даже темка где-то здесь на форуме, где по этому поводу долго и нудно спорили, но каждый остался при своём. Лично я исхожу из того, что говорит Майкрософт как создатель системы (речь в данном случае только о 32-разрядных версиях Винды): виртуальный адрес является 32-разрядным и может передаваться различным вызовам АПИ в качестве адреса (указателя). Технически для ИА-32 таковым является то, что в интеловских мануалах называется смещением из состава логического адреса. Селектор же вообще никак не используется: у Винды, как известно, плоская модель памяти, и с селектором напрямую не работают. Есть, правда, пара исключений. Одно из них -- использование регистра FS, второе -- возможность создать свою LDT и загружать сегментные регистры селекторами из неё. Однако это платформенно-специфическая вещь, привязанная конкретно к ИА-32, а Винда, напомню, замысливалась (да и является по сути) кроссплатформенной системой, не привязанной жёстко к конкретным особенностям железа. Таким образом, виртуальный адрес Майкрософт -- это смещение из логического адреса Интел. Численно он будет равен линейному адресу Интел, однако считать линейный адрес Интел виртуальным адресом Майкрософт нельзя, поскольку Майкрософт прямо пишет о том, что виртуальный адрес передаётся при вызовах АПИ в качестве параметра, ну а линейный адрес передать нельзя в принципе: программист с ним не работает.
spec А тут как раз та самая терминологическая путаница. Интел не использует термин "виртуальный адрес", она использует "логический адрес". Он действительно 48-разрядный, состоящий из двух частей -- селектора и смещения. Однако Майкрософт оперирует термином "виртуальный адрес" и прямо говорит, что он 32-разрядный. Технически это достигается тем, что ОС загружает в сегментные регистры потока стандартные значения селекторов и создаёт стандартные же таблицы дескрипторов, ну а прикладной программист работает исключительно со смещениями, т.е. с его точки зрения виртуальный адрес имеет длину 32 бита.
spec Наговорили тут заумных вещей - попробую попроще 1) в win32 используется flat модель памяти, т.е. все сегменты имеют базовый адрес = 0 и размер 4Гб, т.е. полностью перекрывают друг друга без попыток расширить адресное пространство. Прикладным программам не разрешается даже менять значение сегментных регистров, поскольку они не имеют никакого права знать содержание таблицы дескрипторов, а значит и не знают какие селекторы окажутся верными, а какие укажут в пустоту. 2) если переходить в защищённый режим самостоятельно без win32, то процессоры (32 разрядные) позволяют сегментам начинаться не с нулевого адреса и иметь размер не более 4Гб например так: 0 1Гб 2Гб 4Гб |--сегмент 1--|--сегмент 2--|--------сегмент 3---------| здесь 3 сегмента выстроены друг за другом и имеют размеры: два по 1Гб и один 2Гб. Размеры и базовый адрес хранятся в дескрипторах. Селектор - это указатель на дескриптор который можно помещать в сегментный регистр: ds, es, и т.д. Сегменты могут полностью или частично перекрываться например так: 0 1Гб 2Гб 4Гб |--сегмент 1--|--сегмент 2--|--------сегмент 3---------| |--------сегмент 4---------| |--------сегмент 5---------| |------------------------сегмент 6 (4Гб) ----------------| и т.д. 3) базовый адрес сегмента может находиться в диапазоне от 0 до 4Гб, что гипотетически даёт возможность пристроить второй 4Гб сегмент "в хвост" первому и получить адресацию 8Гб, но на практике процессор 32битный, поэтому 33 бит (нужный для 8Гб) просто обрезается и та часть сегмента что оказалась за пределами 4Гб перепроецируется на младшие адреса. Для наглядности: Гипотетически: 0 3Гб 7Гб |---------сегмент 1 (3Гб)--------|--------------сегмент 2 (4Гб) --------------| На самом деле это выглядит так: 0 3Гб 4Гб |---------сегмент 1 (3Гб)--------|--------\ -----сегмент 2 (4Гб) ------------| \ т.е хвост второго сегмента ушёл в младшие адреса и адресовать больше 4Гб с помощью сегментов всё равно не получилось Еще раз повторю что 2) и 3) это уже не win32, в ней базовый адрес сегмента всегда = 0, а размер сегмента 4Гб. 4) Страничный механизм подключается к формированию физического адреса после того как сформирован линейный - сегмент:смещение. Это свойство как раз и позволяет win32 создать у задачи иллюзию, что всё АП в 4Гб принадлежит только ей (хотя частично занято системой) - получается псевдооднозадачность - каждая программа не знает про другие. Т.е. в нужные места индивидуальных 4Гб просто подставлены разные страницы памяти, содержащие разную информацию. Страницы с одинаковой информацией (например самой системой или общими dll) могут быть и общими для разных задач, но про это знает только ОСь, а не прикладная программа. Если страниц реальной памяти не хватает на все запущенные программы, то их содержимое временно сохраняется на диск, обеспечивая таким образом адресное пространство (АП) системы существенно превышающее и 4Гб и размер ОЗУ и теоретически ничем не ограниченное (практически ограничено суммарной емкостью всех девайсов способных постоянно или временно хранить информацию из ОЗУ). Ограничение в 64Гб задаваемое 36 разрядным страничным адресом касается размера ОЗУ которое можно физически прицепить к процессору, но АП операционной системы, способной рассматривать ОЗУ как "всего лишь" кеш для диска и ему подобных устройств это ограничение не касается. 5) Как я уже писал в другом топике байка про 64Тб не более чем рекламный ход интел, чтобы её не допекали преждевременными разговорами о скором моральном устаревании IA-32, никакой практически полезной информации об устройстве процессора эта байка не несёт
SII Ты не прав. Просто базы сегментов из дескрипторов в GDT нулевые, по дефолту они и юзоются. Насчёт Fs, адресующего TEB - планировщик перезагружает в GDT этот дескриптор при переключении на новый поток. Например можно заюзоть селектор 0x40 - база 0x400, лимит 0xFFFF, учитывая RPL_MASK конечноже.