Организация памяти
За последнюю неделю дважды объяснял людям как организована работа с памятью в х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, так как они нам не понадобятся. Итак наше небольшое отступление про регистры и стек закончилось переходим обратно к организации памяти.
Как вы помните целью статьи является рассказ про преобразование логической памяти в физическую, на самом деле есть еще промежуточный этап и полная цепочка выглядит так:
Логический адрес —> Линейный (виртуальный)—> Физический
линейный адрес=Базовый адрес сегмента(на картинке это начало сегмента) + смещение
Сегмент кода
Сегмент данных
Сегмент стека
Используемый сегмент стека задается значением регистра 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 содержат линейный базовый адрес описываемым данным дескриптором сегмента. Напомню нашу формулу для нахождения линейного адреса:
линейный адрес = базовый адрес + смещение
[база; база+предел)
(база+предел; вершина]
Кстати интересно почему база и предел так рвано располагаются в дескрипторе. Дело в том что процессоры х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, и производится повторное обращение к дескриптору, сегмент которого находится уже в памяти.
На этом заканчивается преобразование логического адреса в линейный, и я думаю на этом стоит прерваться. В следующий раз я расскажу вторую часть преобразования из линейного в физический.
А так же думаю стоит немного поговорить о передачи аргументов функции, и о размещении переменных в памяти, чтобы была какая-то связь с реальностью, потому размещение переменных в памяти это уже непосредственно, то с чем вам приходится сталкиваться в работе, а не просто какие-то теоретические измышления для системного программиста. Но без понимания, как устроена память невозможно понять как эти самые переменные хранятся в памяти.
В общем надеюсь было интересно и до новых встреч.
Источник
Организация памяти ЭВМ
В компьютерах для хранения информации выделяют следующие основные типы памяти [107]: внутренняя память, кэш-память и внешняя память (рис. 4.3). Кроме того, в ЭВМ могут присутствовать различные специализированные виды памяти, характерные для тех или иных устройств вычислительной системы, например, видеопамять.
Внутренняя память предназначена для оперативного хранения и обмена данными непосредственно участвующими в процессе обработки (оперативная память, кэш-память), а также для долговременного хранения информации о конфигурации ПК (энергонезависимая). Конструктивно она исполняется в виде интегральных схем (ИС) и подразделяется на два вида: постоянное запоминающее устройство (ПЗУ) и оперативное запоминающее устройство (ОЗУ).
Кэш-память служит для хранения копий информации, используемой в текущих операциях обмена и являющееся буфером между устройствами с различным быстродействием. Обычно используется при обмене данными между микропроцессором и оперативной памятью для компенсации разницы в скорости обработки информации процессором и несколько менее быстродействующей оперативной памятью.
Рис. 4.3. Структура памяти ПК
Внешняя память используется для долговременного хранения больших объемов информации. В современных компьютерных системах в качестве устройств внешней памяти наиболее часто применяются:
· накопители на жестких магнитных дисках (НЖМД);
· накопители на гибких магнитных дисках (НГМД);
· накопители на магнитооптических дисках (НМОД);
· накопители на оптических дисках;
· ленточные накопители (стримеры).
Оперативное запоминающее устройство (ОЗУ). Оперативное запоминающее устройство, или оперативная память, — это массив кристаллических ячеек, способных хранить данные. Ее основная особенность заключена в том, что хранение информации в ней осуществляется только до тех пор, пока компьютер включен. При выключении компьютера вся хранимая информация сразу же удаляется без возможности восстановления, т.е. это энергозависимая память. По способу хранения информации оперативная память делится на статическую (SRAM — Static RAM) и динамическую (DRAM — Dynamic RAM).
Микросхемы динамической памяти используют в качестве основной оперативной памяти компьютера. Микросхемы статической памяти используют в качестве вспомогательной памяти (кэш-памяти), предназначенной для оптимизации работы процессора.
Оперативная память в компьютере размещается на стандартных панельках, называемых модулями. Модули оперативной памяти вставляют в соответствующие разъемы на материнской плате.
Постоянное запоминающее устройство (ПЗУ).В момент включения компьютера в его оперативной памяти ничего нет — ни данных, ни программ, поскольку оперативная память не может ничего хранить без подзарядки ячеек более долей секунды, но процессору нужны команды, в том числе и в первый момент после включения.
Поэтому сразу после включения на адресной шине процессора выставляется стартовый адрес. Это происходит аппаратно, без участия программ (всегда одинаково). Процессор обращается по выставленному адресу за своей первой командой и далее начинает работать по программам.
Этот исходный адрес не может указывать на оперативную память, в которой пока ничего нет. Он указывает на другой тип памяти — постоянное запоминающее устройство (ПЗУ) — ROM ( Read Only Memory — память только для чтения). Микросхема ПЗУ способна длительное время хранить информацию, даже когда компьютер выключен. Программы, находящиеся в ПЗУ, называют «зашитыми» — их записывают туда на этапе изготовления микросхемы.
Комплект программ, находящихся в ПЗУ, образует базовую систему ввода-вывода (BIOS — Basic Input Output System) . Основное назначение программ этого пакета состоит в том, чтобы проверить состав и работоспособность компьютера и обеспечить взаимодействие с клавиатурой, монитором, жестким диском и дисководом гибких дисков. Программы, входящие в BIOS, позволяют нам наблюдать на экране диагностические сообщения, сопровождающие запуск компьютера, а также вмешиваться в ход запуска с помощью клавиатуры.
Работа таких стандартных устройств, как клавиатура, может обслуживаться программами, входящими в BIOS, но такими средствами нельзя обеспечить работу со всеми возможными устройствами. Так, например, изготовители BIOS абсолютно ничего не знают о параметрах наших жестких и гибких дисков, им не известны ни состав, ни свойства произвольной вычислительной системы. Для того чтобы начать работу с другим оборудованием, программы, входящие в состав BIOS, должны знать, где можно найти нужные параметры. По очевидным причинам их нельзя хранить ни в оперативной памяти, ни в постоянном запоминающем устройстве.
Специально для этого на материнской плате есть микросхема «энергонезависимой памяти», по технологии изготовления называемая CMOS (complementary metaloxide semiconductor). От оперативной памяти она отличается тем, что ее содержимое не стирается во время выключения компьютера, а от ПЗУ — тем, что данные в нее можно заносить и изменять самостоятельно, в соответствии с тем, какое оборудование входит в состав системы. Эта микросхема постоянно подпитывается от небольшой батарейки, расположенной на материнской плате. Заряда этой батарейки хватает на то, чтобы микросхема не теряла данные, даже если компьютер не будут включать несколько лет. В микросхеме CMOS хранятся данные о гибких и жестких дисках, о процессоре, о некоторых других устройствах материнской платы. Тот факт, что компьютер четко отслеживает время и календарь (даже и в выключенном состоянии), тоже связан с тем, что показания системных часов постоянно хранятся (и изменяются) в CMOS.
Таким образом, программы, записанные в BIOS, считывают данные о составе оборудования компьютера из микросхемы CMOS, после чего они могут выполнить обращение к жесткому диску, а в случае необходимости и к гибкому, и передать управление тем программам, которые там записаны.
Специальная память. К устройствам специальной памяти относятся постоянная память (ПЗУ), перепрограммируемая постоянная память (ППЗУ — Flash Memory), память CMOS RAM, питаемая от батарейки, видеопамять и некоторые другие виды памяти.
Перепрограммируемая постоянная память (Flash Memory) — энергонезависимая память, допускающая многократную перезапись своего содержимого с дискеты.
Видеопамять (VRAM) — разновидность оперативного запоминающего (ЗУ), в котором хранятся закодированные изображения. Это ЗУ организовано так, что его содержимое доступно сразу двум устройствам — процессору и дисплею. Поэтому изображение на экране меняется одновременно с обновлением видеоданных в памяти.
Внешние устройства хранения информации.В качестве внешних запоминающих устройств при работе на ПК в основном используются накопители на гибких магнитных дисках (НГМД) или дискеты, накопитель на жестком магнитном диске (НЖМД) или винчестер и накопители на лазерных компакт-дисках или CD-диски (рис. 4.4). Кроме того, в последнее время все большую популярность стали приобретать разные сменные карты памяти. Основными характеристиками всех внешних устройств хранения информации являются:
1. Информационная емкость — максимально возможный объем хранимой информации. Выражается в мегабайтах (для дискет и CD-дисков) и гигабайтах (для винчестеров и DVD-дисков).
2. Время доступа к информации — временной интервал между моментом, когда процессор запрашивает с диска данные, и моментом их выдачи. Измеряется в миллисекундах (мс). Наибольшее время доступа к информации у накопителей на гибких магнитных дисках (дискетах), а наименьшее — у винчестеров.
3. Скорость чтения и записи информации — определяется количеством байт, прочитанных/записанных в секунду. Выражается в Мбайт/с.
Источник