В какой регистр загружается длина программы

Системные команды предназначены для использования, главным образом, в модулях операционных систем (в модулях ядра операционной системы, в драйверах и т.д.). Некоторые из перечисленных ниже команд полезны и при разработке прикладных программ, работающих в защищённом режиме. Мы приведём только краткий перечень основных системных команд, подробности вы можете узнать из справочных руководств по процессорам (см. список литературы).

Как правило, системные команды могут использовать только те программы, которые выполняются в нулевом привилегированном кольце.

ARPL Коррекция поля привилегий инициатора запроса в селекторе

Эта команда используется системными модулями для проверки уровня запрашиваемых привилегий в передаваемых им в качестве параметров селекторов. Прикладная программа не должна запрашивать привилегии, превышающие её собственные.

Первый операнд команды — 16-разрядный регистр или слово памяти, содержащие значение проверяемого селектора. Второй операнд — регистр, в который записано содержимое CS прикладной программы.

Сдвиговый регистр 74HC595 и загрузка данных в него, по SPI интерфейсу.

Если команда не изменяла уровень привилегий, в регистре FLAGS (EFLAGS для процессоров i80386 и i80486) устанавливается флаг нуля. В противном случае этот флаг сбрасывается.

Пример использования команды:

mov dx, cs mov ax, TESTED_SELECTOR arpl dx, ax

CLTS Сброс флага TS переключения задачи в регистре CR0

Каждый раз при переключении задачи флаг TS устанавливается в 1. Команда CLTS позволяет сбросить этот флаг.

LAR Загрузка байта прав доступа

Для процессора i80286 команда LAR загружает в первый операнд (регистр) байт доступа дескриптора, выбираемого вторым операндом. Второй операнд является селектором, указывающим на используемый дескриптор.

В процессорах i80386 и i80486 команда LAR использует в качестве первого операнда 32-разрядный регистр. Кроме байта прав доступа в этот регистр заносятся биты типа сегмента (9-11), DPL (14), бит присутствия (15), бит дробности (23).

LGDT Загрузка регистра GDTR

Команда выполняет инициализацию регистра GDTR, указывающего расположение в памяти и размер глобальной таблицы дескрипторов.

LIDT Загрузка регистра IDTR

Команда выполняет инициализацию регистра IDTR, указывающего расположение в памяти и размер дескрипторной таблицы прерываний.

LLDT Загрузка регистра LDTR

Команда выполняет инициализацию регистра LDTR, указывающего расположение в памяти и размер локальной таблицы дескрипторов.

LMSW Загрузка слова состояния процессора

С помощью этой команды можно выполнить загрузку младшего слова регистра CR0 из регистра — операнда команды.

Эта команда может использоваться для переключения процессора в защищённый режим. Обратного переключения эта команда не обеспечивает (даже для процессоров i80386 и i80486).

LSL Загрузка предела сегмента

Команда имеет два операнда. Граница сегмента, селектор которого используется в качестве второго операнда (задаётся в регистре), загружается в регистр, указанный в качестве первого операнда.

05. Основы устройства компьютера. Регистры и команды процессора. [Универсальный программист]

LTR Загрузка регистра задачи

Команда предназначена для загрузки регистра TR — регистра задачи. Загрузка этого регистра не приводит к переключению задачи.

MOV Загрузка системных регистров

Для процессоров i80386 и i80486 в качестве операндов обычной команды MOV допустимо (на нулевом уровне привилегий) указывать системные регистры — CR0, CR2, CR3, DR0, DR1, DR2, DR3, DR6, DR7, TR6, TR7. Команда MOV может быть использована процессорами i80386 и i80486 для возврата процессора из защищённого режима в реальный.

SGDT Запись в память содержимого регистра GDTR

Команда позволяет узнать текущее содержимое регистра глобальной дескрипторной таблицы GDTR, обычное её используют в системных отладчиках.

SIDT Записать в память содержимое регистра IDTR

Команда позволяет узнать текущее содержимое регистра глобальной дескрипторной таблицы прерываний IDTR, используется в системных отладчиках.

SLDT Записать в память содержимое регистра LDTR

Команда позволяет узнать текущее содержимое регистра локальной дескрипторной таблицы LDTR, используется в системных отладчиках.

SMSW Записать слова состояния процессора

Команда записывает в память или 16-битовый регистр младшее слово регистра CR0 и может быть использована в системных отладчиках.

STR Запись регистра задачи

Команда записывает текущее содержимое регистра задачи TR в 16-разрядную ячейку памяти или 16-разрядный регистр. Может использоваться в системных отладчиках.

VERR Проверить сегмент на возможность чтения

VERW Проверить сегмент на возможность записи

С помощью этих двух команд можно проверить доступность выбранного селектором сегмента на чтение и запись, соответственно. Если операция чтения или записи доступна, флаг нуля ZF устанавливается в единицу, в противном случае он сбрасывается в ноль.

Основное назначение этой команды — предотвратить возникновение исключения по защите памяти при попытке обращения к сегменту. Прежде чем выполнять обращение, программа может проверить доступность сегмента и сделать соответствующие выводы.

Оказывается, для процессора i80286 существует способ получения доступа к расширенной памяти, не переключаясь в защищённый режим. Для этого может быть использована недокументированная команда LOADALL, имеющая код 0F05h (команда не имеет операндов). Эта команда не описана в справочниках по процессору i80286, информация о ней поставляется фирмой Intel по запросу. Те сведения о команде LOADALL, которые приведены в нашей книге, получены по электронной почте из BBS и могут быть использованы только для расширения вашего кругозора и для оценки полезности этой команды в ваших разработках.

Команда LOADALL первоначально была задумана фирмой Intel как тестовая. Однако оказалось, что она пригодна и для обращения к расширенной памяти в реальном режиме. Широко известный драйвер расширенной памяти HIMEM.SYS обращается в область адресов выше первого мегабайта именно с помощью команды LOADALL (а не переключаясь в защищённый режим и возвращаясь обратно, как это можно было бы предположить).

Команда LOADALL сокращает время, требуемое драйверу HIMEM.SYS на доступ к расширенной памяти, так как время на переключение в защищённый режим и обратное переключение достаточно велико по сравнению с временем, необходимым на копирование данных из основной памяти в расширенную или обратно.

Другое применение команды — драйвер электронного диска Microsoft RAMDRIVE.SYS и блок совместимости операционной системы Microsoft OS/2 версии 1.x.

Секрет команды LOADALL заключается в том, что она загружает ВСЕ регистры процессора, и может выполняться в реальном режиме. Изменяя поле базы регистра кэша дескриптора (внутренний системный регистр процессора) программа может обратиться к сегменту, лежащему за пределами первого мегабайта адресного пространства.

Читайте также:
Smart notebook как работать с программой

Как мы уже говорили, команда LOADALL не имеет операндов. Регистры загружаются из буфера, который имеет длину 102 байта и должен быть подготовлен в области памяти с физическим адресом 00800h.

Формат буфера представлен в следующей таблице:

Таблица 16. Формат буфера для команды LOADALL.

Адрес Регистры процессора
800h-805h Не используется
806h-807h Слово состояния процессора MSW (Machine Status Word)
808h-815h Не используется
816h-817h Регистр задачи TR (Task Register)
818h-819h Регистр флагов
81Ah-81Bh Регистр IP (Instruction Pointer)
81Ch-81Dh Селектор LDT (Local Descriptor Table)
81Eh-81Fh Регистр DS (Data Segment Selector)
820h-821h Регистр SS (Stack Segment Selector)
822h-823h Регистр CS (Code Segment Selector)
824h-825h Регистр ES (Extra Segment Selector)
826h-827h Регистр DI (Destination Index)
818h-829h Регистр SI (Source Index)
82Ah-82Bh Регистр BP (Base Pointer)
82Ch-82Dh Регистр SP (Stack Pointer)
82Eh-82Fh Регистр BX (Data Register BX)
830h-831h Регистр DX (Data Register DX)
832h-833h Регистр CX (Data Register CX)
834h-835h Регистр AX (Accumulator)
836h-83Bh Кэш дескриптора ES
83Ch-841h Кэш дескриптора CS
842h-847h Кэш дескриптора SS
848h-84Dh Кеш дескриптора DS
84Eh-853h Регистр GDTR (Global Descriptor Table Register)
854h-859h Кэш дескриптора LDT
85Ah-85Fh Регистр IDTR (Interrupt Descriptor Table Register)
860h-865h Кэш дескриптора TSS (Task State Segment)

Для ускорения доступа к содержимому дескрипторных таблиц в процессоре имеются так называемые теневые регистры или регистры кэша дескрипторов. Когда процессор загружает селектор в сегментный регистр, автоматически выполняется загрузка соответствующего регистра кэша дескриптора. Не существует какого-либо иного способа загрузить кэш дескриптора явно из программы с помощью обычных команд. Однако вы можете воспользоваться для этого командой LOADALL, подготовив в описанном выше буфере необходимые значения.

Формат кэша дескриптора приведён в следующей таблице:

Таблица 17. Формат кэша дескриптора.

Смещение поля Назначение поля
0-2 24-битовый базовый адрес сегмента
3 Байт доступа, его формат полностью аналогичен формату байта доступа дескриптора, за исключением бита присутствия. На месте этого бита находится бит VALID. Если этот бит сброшен в 0, при попытке использовать дескриптор для адресации памяти произойдёт исключение 13 с кодом ошибки 0.
4-5 16-битовый предел сегмента
  • Запретитите прерывания.
  • Сохраните где-нибудь в буфере программы область памяти, начинающуюся с адреса 00800h и имеющую длину 102 байта.
  • Заполните буфер для команды LOADALL необходимыми значениями для всех загружаемых регистров. Базовый адрес в области кэша дескриптора сегмента данных должен указывать на необходимый вам участок расширенной памяти.
  • Выполните команду LOADALL. Сегмент данных теперь будет указывать на область расширенной памяти.
  • Выполните запись или чтение области расширенной памяти.
  • Восстановите базовый адрес сегмента данных в кэше дескриптора данных в буфре, расположенном по адресу 00800h.
  • Выполните команду LOADALL ещё раз.
  • Восстановите содержимое сохранённого ранее буфера.
  • Разрешите прерывания.

При выполнении команды LOADALL не делается никаких проверок. Вам необходимо самим позаботиться о том, чтобы загружаемые в регистры процессора значения имели какой-нибудь смысл. В противном случае состояние процессора окажется непредсказуемым.

Команда LOADALL может выполняться в защищённом режиме в нулевом приоритетном кольце. Но, к сожалению, эту команду нельзя использовать для переключения процессора из защищённого в реальный режим.

Процессор i80387 также имеет команду LOADALL, но её код и выполняемые функции другие.

Для определения активных интерфейсов с защищённым режимом можно использовать предлагаемую утилиту MEMOSCOP. Эта утилита проверяет присутствие всех уровней поддержки программ, работающих в защищённом режиме или с расширенной памятью — от BIOS до DPMI.

Исходные тексты функций, вызываемых утилитой MEMOSCOP приведены ниже:

Для работы с функциями драйвера HIMEM.SYS используется интерфейс, описанный нами в томе 2 «Библиотеки системного программсита»:

Если вы разрабатываете программное обеспечение, защищённое от несанкционированного копирования, вам необходимо позаботиться о том, чтобы потенциальные взломщики («кракеры» и «хакеры») не смогли выполнить программу инсталляции под управлением отладчика. Если взломщик сможет «подглядеть» за работой вашей программы, он рано или поздно разгадает ваш замысел и сведёт на нет все ваши усилия по защите программы от копирования.

В третьей книге первого тома «Библиотеки системного программиста» мы излагали некоторые соображения по организации защиты программ от несанкционированного копирования. Мы, в частности, рассказали о некоторых методах защиты программ от отладки — использование таймера, внутренней очереди команд процессора и другие.

Защищённый режим работы процессора открывает перед вами новую возможность. Возьмите любую программу, приведённую в этой книге и попытайтесь запустить её под управлением какого-либо отладчика (например, попробуйте Turbo Debugger или Code View). Всё будет хорошо до тех пор, пока ваша программа не попытается загрузить регистр IDTR при помощи команды LIDT. После выполнения этой команды отладчик зависает и единственное средство вновь оживить компьютер — нажать на кнопку сброса, расположенную на системном блоке.

Причина очевидна — изменились расположение и формат дескрипторной таблицы прерываний. Она подготовлена для работы в защищённом режиме, но отладчик работает в реальном режиме. Поэтому обработка всех прерываний, в том числе и от клавиатуры, невозможна.

Идея использования защищённого режима работы процессора при создании программ, защищённых от несанкционированного копирования, очевидна. Используя примеры программ, приведённые в книге, вы сможете во время работы программы инсталляции перевести процессор в защищённый режим и выполнить часть работы по инсталляции в защищённом режиме.

Например, перед переключением в защищённый режим вы можете подготовить в памяти массив контрольной информации. Расшифровка и проверка этого массива, а также запись данных в нестандартные сектора инсталляционной дискеты могут выполняться в защищённом режиме. При этом, пользуясь обычными отладчиками, невозможно определить действия, выполняемые в защищённом режиме. Особенно, если участок программы, работающий в защищённом режиме, зашифрован.

Далее процессор можно вернуть в реальный режим и продолжить процесс инсталляции.

Находясь в защищённом режиме, вы можете читать и писать сектора дискеты только используя уровень портов ввода/вывода контроллера флоппи-диска. Программирование контроллера флоппи-диска описано в третьей книге первого тома «Библиотеки системного программиста». Обрабатывать прерывания в защищённом режиме вы уже умеете.

Очевидный недостаток применения защищённого режима при организации защиты от копирования заключается в необходимости использования процессоров i80286, i80386 или i80486. Это означает, что указанный метод непригоден для компьютеров IBM PC/XT, использующих процессор i8086 или i8088.

Источник: www.iakovlev.org

r (регистры)

Команда r отображает или изменяет регистры, регистры с плавающей запятой, флаги, псевдорегистраторы и псевдонимы с фиксированным именем.

[~Thread] r[M Mask|F|X|?] [ Register[:[Num]Type] [= [Value]] ] r.
[Processor] r[M Mask|F|X|Y|YI|?] [ Register[:[Num]Type] [= [Value]] ] r.

Параметры

Процессор
Указывает процессор, из которых считываются регистры. Значение по умолчанию равно нулю. Если указан параметр Обработчик, параметр Register включить нельзя— отображаются все регистры. Дополнительные сведения о синтаксисе см. в разделе Многопроцессорный синтаксис. Можно указать процессоры только в режиме ядра.

Читайте также:
Установить программу на ТВ LG

Поток
Указывает поток, из которых считываются регистры. Если поток не указан, используется текущий поток. Дополнительные сведения о синтаксисе см. в разделе Синтаксис потока. Потоки можно указать только в пользовательском режиме.

MMask
Указывает маску, используемую при отображении отладчиком регистров. Буква «M» должна быть прописной буквой. Маска — это сумма битов, которые указывают на отображение регистра. Значение битов зависит от процессора и режима (дополнительные сведения см. в таблицах в следующем разделе примечаний). Если опустить M, используется маска по умолчанию.

Вы можете задать или отобразить маску по умолчанию с помощью команды Rm (Register Mask).

F
Отображает регистры с плавающей запятой. Буква «F» должна быть прописной буквой. Этот параметр эквивалентен 0x4 M.

X
Отображает регистры XMM SSE. Этот параметр эквивалентен M 0x40.

Y
Отображает регистры AVX YMM. Этот параметр эквивалентен 0x200 M.

YI
Отображает целочисленные регистры AVX YMM. Этот параметр эквивалентен 0x400 M.

Z
Отображает регистры AVX-512 YMM (zmm0-zmm31) в формате с плавающей запятой.

ZI
Отображает регистры AVX-512 YMM (zmm0-zmm31) в целочисленном формате.

K
Отображение регистров предиката AVX-512 Opmask (K0–K7).

?
(Только псевдорегистративное назначение) Заставляет псевдорегистрал получать типизированные сведения. Разрешен любой тип. Дополнительные сведения о синтаксисе r? см. в разделе Примеры командной программы отладчика.

Num
Указывает количество отображаемых элементов. Если этот параметр опущен, но указан тип, отобразится полная длина регистра.

Тип
Задает формат данных для отображения каждого элемента регистра. Тип можно использовать только с 64-разрядными и 128-разрядными векторными регистрами. Можно указать несколько типов.

Можно указать одно или несколько из следующих значений.

Источник: learn.microsoft.com

Организация памяти

За последнюю неделю дважды объяснял людям как организована работа с памятью в х86, с целью чтобы не объяснять в третий раз написал эту статью.

И так, чтобы понять организацию памяти от вас потребуется знания некоторых базовых понятий, таких как регистры, стек и тд. Я по ходу попробую объяснить и это на пальцах, но очень кратко потому что это не тема для этой статьи. Итак начнем.

Как известно программист, когда пишет программы работает не с физическим адресом, а только с логическим. И то если он программирует на ассемблере. В том же Си ячейки памяти от программиста уже скрыты указателями, для его же удобства, но если грубо говорить указатель это другое представление логического адреса памяти, а в Java и указателей нет, совсем плохой язык. Однако грамотному программисту не помешают знания о том как организована память хотя бы на общем уровне. Меня вообще очень огорчают программисты, которые не знают как работает машина, обычно это программисты Java и прочие php-парни, с квалификацией ниже плинтуса.

Так ладно, хватит о печальном, переходим к делу.
Рассмотрим адресное пространство программного режима 32 битного процессора (для 64 бит все по аналогии)
Адресное пространство этого режима будет состоять из 2^32 ячеек памяти пронумерованных от 0 и до 2^32-1.
Программист работает с этой памятью, если ему нужно определить переменную, он просто говорит ячейка памяти с адресом таким-то будет содержать такой-то тип данных, при этом сам програмист может и не знать какой номер у этой ячейки он просто напишет что-то вроде:
int data = 10;
компьютер поймет это так: нужно взять какую-то ячейку с номером стопицот и поместить в нее цело число 10. При том про адрес ячейки 18894 вы и не узнаете, он от вас будет скрыт.

Все бы хорошо, но возникает вопрос, а как компьютер ищет эту ячейку памяти, ведь память у нас может быть разная:
3 уровень кэша
2 уровень кэша
1 уровень кэша
основная память
жесткий диск

Это все разные памяти, но компьютер легко находит в какой из них лежит наша переменная int data.
Этот вопрос решается операционной системой совместно с процессором.
Вся дальнейшая статья будет посвящена разбору этого метода.

Архитектура х86 поддерживает стек.

Стек это непрерывная область оперативной памяти организованная по принципу стопки тарелок, вы не можете брать тарелки из середины стопки, можете только брать верхнюю и класть тарелку вы тоже можете только на верх стопки.
В процессоре для работы со стеком организованны специальные машинные коды, ассемблерные мнемоники которых выглядят так:

push operand
помещает операнд в стек

pop operand
изымает из вершины стека значение и помещает его в свой операнд

Стек в памяти растет сверху вниз, это значит что при добавлении значения в него адрес вершины стека уменьшается, а когда вы извлекаете из него, то адрес вершины стека увеличивается.

Теперь кратко рассмотрим что такое регистры.
Это ячейки памяти в самом процессоре. Это самый быстрый и самый дорогой тип памяти, когда процессор совершает какие-то операции со значением или с памятью, он берет эти значения непосредственно из регистров.
В процессоре есть несколько наборов логик, каждая из которых имеет свои машинные коды и свои наборы регистров.
Basic program registers (Основные программные регистры) Эти регистры используются всеми программами с их помощью выполняется обработка целочисленных данных.
Floating Point Unit registers (FPU) Эти регистры работают с данными представленными в формате с плавающей точкой.
Еще есть MMX и XMM registers эти регистры используются тогда, когда вам надо выполнить одну инструкцию над большим количеством операндов.

Рассмотрим подробнее основные программные регистры. К ним относятся восемь 32 битных регистров общего назначения: EAX, EBX, ECX, EDX, EBP, ESI, EDI, ESP
Для того чтобы поместить в регистр данные, или для того чтобы изъять из регистра в ячейку памяти данные используется команда mov:

mov eax, 10
загружает число 10 в регистр eax.

mov data, ebx
копирует число, содержащееся в регистре ebx в ячейку памяти data.

Регистр ESP содержит адрес вершины стека.
Кроме регистров общего назначения, к основным программным регистрам относят шесть 16битных сегментных регистров: CS, DS, SS, ES, FS, GS, EFLAGS, EIP
EFLAGS показывает биты, так называемые флаги, которые отражают состояние процессора или характеризуют ход выполнения предыдущих команд.
В регистре EIP содержится адрес следующей команды, которая будет выполнятся процессором.
Я не буду расписывать регистры FPU, так как они нам не понадобятся. Итак наше небольшое отступление про регистры и стек закончилось переходим обратно к организации памяти.

Как вы помните целью статьи является рассказ про преобразование логической памяти в физическую, на самом деле есть еще промежуточный этап и полная цепочка выглядит так:

Логический адрес —> Линейный (виртуальный)—> Физический

image

Все линейное адресное пространство разбито на сегменты. Адресное пространство каждого процесса имеет по крайней мере три сегмента:
Сегмент кода. (содержит команды из нашей программы, которые будут исполнятся.)
Сегмент данных. (Содержит данные, то бишь переменные)
Сегмент стека, про который я писал выше.

Читайте также:
Как узнать версию программы в репозитории ubuntu

Линейный адрес вычисляется по формуле:

линейный адрес=Базовый адрес сегмента(на картинке это начало сегмента) + смещение
Сегмент кода

Базовый адрес сегмента кода берется из регистра CS. Значение смещения для сегмента кода берется из регистра EIP, в котором хранится адрес инструкции, после исполнения которой, значение EIP увеличивается на размер этой команды. Если команда занимает 4 байта, то значение EIP увеличивается на 4 байта и будет указывать уже на следующую инструкцию. Все это делается автоматически без участия программиста.
Сегментов кода может быть несколько в нашей памяти. В нашем случае он один.

Сегмент данных

Данные загружаются в регистры DS, ES, FS, GS
Это значит что сегментов данных может быть до 4х. На нашей картинке он один.
Смещение внутри сегмента данных задается как операнд команды. По дефолту используется сегмент на который указывает регистр DS. Для того чтобы войти в другой сегмент надо это непосредственно указать в команде префикса замены сегмента.

Сегмент стека

Используемый сегмент стека задается значением регистра SS.
Смещение внутри этого сегмента представлено регистром ESP, который указывает на вершину стека, как вы помните.
Сегменты в памяти могут друг друга перекрывать, мало того базовый адрес всех сегментов может совпадать например в нуле. Такой вырожденный случай называется линейным представлением памяти. В современных системах, память как правило так организована.

Теперь рассмотрим определение базовых адресов сегмента, я писал что они содержаться в регистрах SS, DS, CS, но это не совсем так, в них содержится некий 16 битный селектор, который указывает на некий дескриптор сегментов, в котором уже хранится необходимый адрес.

Так выглядит селектор, в тринадцати его битах содержится индекс дескриптора в таблице дескрипторов. Не хитро посчитать будет что 2^13 = 8192 это максимальное количество дескрипторов в таблице.
Вообще дескрипторных таблиц бывает два вида GDT и LDT Первая называется глобальная таблица дескрипторов, она в системе всегда только одна, ее начальный адрес, точнее адрес ее нулевого дескриптора хранится в 48 битном системном регистре GDTR. И с момента старта системы не меняется и в свопе не принимает участия.
А вот значения дескрипторов могут меняться. Если в селекторе бит TI равен нулю, тогда процессор просто идет в GDT ищет по индексу нужный дескриптор с помощью которого осуществляет доступ к этому сегменту.
Пока все просто было, но если TI равен 1 тогда это означает что использоваться будет LDT. Таблиц этих много, но использоваться в данный момент будет та селектор которой загружен в системный регистр LDTR, который в отличии от GDTR может меняться.
Индекс селектора указывает на дескриптор, который указывает уже не на базовый адрес сегмента, а на память в котором хранится локальная таблица дескрипторов, точнее ее нулевой элемент. Ну а дальше все так же как и с GDT. Таким образом во время работы локальные таблицы могут создаваться и уничтожаться по мере необходимости. LDT не могут содержать дескрипторы на другие LDT.
Итак мы знаем как процессор добирается до дескриптора, а что содержится в этом дескрипторе посмотрим на картинке:
Дескрипторы состоит из 8 байт.
Биты с 15-39 и 56-63 содержат линейный базовый адрес описываемым данным дескриптором сегмента. Напомню нашу формулу для нахождения линейного адреса:

линейный адрес = базовый адрес + смещение

С помощью такой нехитрой операции процессор может обращаться по нужному адресу линейной памяти.
Рассмотрим другие биты дескриптора, очень важным является Segment Limit или предел, он имеет 20битное значение от 0-15 и 48-51 бит. Предел задает размер сегмента. Для сегментов данных и кода доступными являются все адреса, расположенные в интервале:

[база; база+предел)

В зависимости от 55 G-бита(гранулярити), предел может измеряться в байтах при нулевом значении бита и тогда максимальный предел составит 1 мб, или в значении 1, предел измеряется страницами, каждая из которых равна 4кб. и максимальный размер такого сегмента будет 4Гб.
Для сегмента стека предел будет в интервале:

(база+предел; вершина]

Кстати интересно почему база и предел так рвано располагаются в дескрипторе. Дело в том что процессоры х86 развивались эволюционно и во времена 286х дескрипторы были по 8 бит всего, при этом старшие 2 байта были зарезервированы, ну а в последующих моделях процессоров с увеличением разрядности дескрипторы тоже выросли, но для сохранения обратной совместимости пришлось оставить структуру как есть.
Значение адреса «вершина» зависит от 54го D бита, если он равен 0, тогда вершина равна 0xFFF(64кб-1), если D бит равен 1, тогда вершина равна 0xFFFFFFFF (4Гб-1)
С 41-43 бит кодируется тип сегмента.
000 — сегмент данных, только считывание
001 — сегмент данных, считывание и запись
010 — сегмент стека, только считывание
011 — сегмент стека, считывание и запись
100 — сегмент кода, только выполнение
101- сегмент кода, считывание и выполнение
110 — подчиненный сегмент кода, только выполнение
111 — подчиненный сегмент кода, только выполнение и считывание

44 S бит если равен 1 тогда дескриптор описывает реальный сегмент оперативной памяти, иначе значение S бита равно 0.

Самым важным битом является 47-й P бит присутствия. Если бит равен 1 значит, что сегмент или локальная таблица дескрипторов загружена в оперативку, если этот бит равен 0, тогда это означает что данного сегмента в оперативке нет, он находится на жестком диске, случается прерывание, особый случай работы процессора запускается обработчик особого случая, который загружает нужный сегмент с жесткого диска в память, если P бит равен 0, тогда все поля дескриптора теряют смысл, и становятся свободными для сохранения в них служебной информации. После завершения работы обработчика, P бит устанавливается в значение 1, и производится повторное обращение к дескриптору, сегмент которого находится уже в памяти.

На этом заканчивается преобразование логического адреса в линейный, и я думаю на этом стоит прерваться. В следующий раз я расскажу вторую часть преобразования из линейного в физический.
А так же думаю стоит немного поговорить о передачи аргументов функции, и о размещении переменных в памяти, чтобы была какая-то связь с реальностью, потому размещение переменных в памяти это уже непосредственно, то с чем вам приходится сталкиваться в работе, а не просто какие-то теоретические измышления для системного программиста. Но без понимания, как устроена память невозможно понять как эти самые переменные хранятся в памяти.
В общем надеюсь было интересно и до новых встреч.

Источник: habr.com

Рейтинг
( Пока оценок нет )
Загрузка ...
EFT-Soft.ru