ТОП 10:

Модели памяти и сегментные регистры



Оперативная память в ПК представляет собой совокупность байтовых ячеек, каждая из которых обладает уникальным адресом. Адреса байтов, которые необходимо указывать при обращении к ним, могут быть представлены по-разному. В бессегментной или "плоской" (flat) модели памяти байты просто последовательно пронумерованы, и каждый номер (адрес) однозначно соответствует определенному байту. В конечном счете, именно по таким адресам производит обращение к памяти процессор. Диапазон адресов современных процессоров с 32-разрядной адресной шиной — от 0 до 232–1 (4 гигабайта). Для обеспечения независимости программ от их возможного местоположения в памяти, а также для уменьшения размеров адресов, используемых в программах, применяют сегментированные модели памяти. При этом память условно делят на участки (сегменты), размер которых не может превышать определенной величины. Для формирования адреса какой-либо ячейки памяти задействуются два числа — адрес начала сегмента и смещение искомой ячейки относительно этого начала.

Операционные системы (кроме DOS) могут размещать сегменты, с ко­торыми работает программа пользователя, в разных местах в памяти, и даже могут временно записывать их на диск, если памяти не хватает. Так как сегменты могут оказаться где угодно, программа обращается к ним, используя вместо настоящего адреса начала сегмента 16-битное число, называемое селектором. В процессорах Intel предусмотрено шесть 16-битных регистров — CS, DS, ES, FS, GS, SS, исполь­зуемых для хранения селекторов. (Регистры FS и GS отсутствовали в 8086, но появились уже в 80286.) Это не значит, что программа не мо­жет работать одновременно с большим количеством сегментов памя­ти, — в любой момент времени можно изменить значения, записанные в этих регистрах.

В реальном режиме селектор любого сегмента равен адресу его начала, деленному на 16. Чтобы получить адрес в памяти, 16-битное смещение скла­дывают с этим селектором, сдвинутым предварительно влево на 4. Таким образом, оказывается, что максимальный доступный адрес в реальном ре­жиме 220 - 1 = 1 048 575. Для сравнения, в защищенном режиме адрес нача­ла для каждого сегмента хранится отдельно, так что возможно 246 (64 тера­байта) различных логических адресов в формате сегмент:смещение (программа может определить до 16 383 сегментов, каждый из которых имеет размер до 4 Гб). Реально процессор может адресоваться только к 4 (или 64 для Pentium Pro) гигабайтам памяти.

В отличие от регистров DS, ES, GS, FS, которые называются регист­рами сегментов данных, регистры CS и SS отвечают за сегменты двух особенных типов — сегмент кода и сегмент стека. Сегмент кода содержит программу, исполняющуюся в данный момент, так что запись нового се­лектора в этот регистр приводит к тому, что далее будет исполнена не следующая по тексту программы команда, а команда из кода, находяще­гося в другом сегменте, с тем же смещением. Смещение следующей выполняемой команды всегда хранится в специальном регистре — EIP (указатель инструкции, шестнадцатибитная форма IP). Название регистра EIP является условным, так как оно не используется для обращения к данному регистру в качестве операнда команд. Косвенно запись в регистр EIP можно осуществить лишь командами передачи управления. Каждая из этих команд — перехода, условного перехода, цикла, вызова подпрограммы и т. п. — осуществляет запись в регистры CS и EIP, благодаря чему следующей исполняется команда из другого места памяти.

Стек

Стек — это специальным образом организованный участок памяти, ис­пользуемый для временного хранения переменных, для передачи пара­метров вызываемым подпрограммам и для сохранения адреса возврата при вызове процедур и прерываний. Процессор имеет особые команды для записи в стек (PUSH) и считывания из стека (POP). Элемент, записанный в стек последним, считывается из него первым и наоборот. Таким образом, если записать в стек числа 1, 2, 3, то считываться они будут в обратном порядке — 3, 2, 1. Стек располагается в сегменте памяти, описываемом регистром SS, текущее смещение вершины стека (последней заполненной ячейки) записано в регистре ESP, причем при записи в стек значе­ние этого смещения уменьшается, то есть стек растет в направлении от максималь­но возможного адреса к меньшим (младшим) адресам (рис. 4). Такое расположение стека может быть необходимо, например в бессегментной модели памяти, когда все сегменты, включая сегмент стека и сегмент кода, зани­мают одну и ту же область — всю память. Тогда программа исполняется в нижней области памяти, в области малых адресов, и EIP растет, а стек располагается в верхней области памяти, и ESP уменьшается.

 

    Дно стека
FFFFFFFC    
FFFFFFF8   Параметры
FFFFFFF4  
FFFFFFF0   EBP = FFFFFFF0
FFFFFFEC   Локальные переменные
FFFFFFE8  
FFFFFFE4   ESP = FFFFFFE4
   
         

 

Рис. 4. Стек

 

Если необходимо обращаться к ячейкам стека без использования команд PUSH и POP (например, при обращении в процедуре к параметрам, переданным в стеке), сделать это можно при помощи регистра EBP. Адрес сегмента при этом будет вычисляться с использованием регистра SS.

Регистр флагов

Еще один важный регистр, использующийся при выполнении большин­ства команд, — регистр флагов EFLAGS (условное название). Как и раньше, его младшие 16 бит, соответствующие этому регистру до 80386, называются FLAGS. В этом регистре каждый бит является флагом, то есть устанав­ливается в 1 при определенных условиях или установка его в 1 изменя­ет поведение процессора. Все флаги, расположенные в старшем слове регистра EFLAGS, имеют отношение к управлению защищенным режи­мом, поэтому здесь рассмотрен только регистр FLAGS (рис. 5).

 

NT IOPL OF DF IF TF SF ZF AF PF CF

15 0

Рис. 5. Регистр флагов FLAGS

 

· CF — флаг переноса. Устанавливается в 1, если результат предыдущей операции не уместился в приемнике и произошел перенос из старше­го бита или если требуется заем (при вычитании), иначе устанавли­вается в 0. Например, после сложения слова 0FFFFh и 1, если регистр, в который надо поместить результат, — слово, в него будет записано 0000h и флаг CF установится (CF = 1).

· PF — флаг четности. Устанавливается в 1, если младший байт резуль­тата предыдущей команды содержит четное число бит, равных 1, ус­танавливается в 0, если нечетное. (Это не то же самое, что делимость на два. Число делится на два без остатка, если его самый младший бит равен нулю, и не делится, если он равен 1).

· AF — флаг полупереноса или вспомогательного переноса. Устанавли­вается в 1, если в результате предыдущей операции произошел пере­нос (или заем) из третьего бита в четвертый. Этот флаг используется автоматически командами двоично-десятичной коррекции.

· ZF — флаг нуля. Устанавливается в 1, если результат предыдущей ко­манды — ноль.

· SF — флаг знака. Этот флаг всегда равен старшему биту результата.

· TF — флаг ловушки. Этот флаг был предусмотрен для работы от­ладчиков, не использующих защищенный режим. Установка его в 1 приводит к тому, что после выполнения каждой команды программы управление временно передается отладчику (вызывается прерывание 1 — см. описание команды INT).

· IF — флаг прерываний. Установка этого флага в 1 приводит к тому, что процессор перестает обрабатывать прерывания от внешних уст­ройств (см. описание команды INT). Обычно его устанавливают на короткое время для выполнения критических участков кода.

· DF — флаг направления. Этот флаг контролирует поведение команд обработки строк — когда он установлен в 1, строки обрабатываются в сторону уменьшения адресов, когда DF = 0 — наоборот.

· OF — флаг переполнения. Этот флаг устанавливается в 1, если резуль­тат предыдущей арифметической операции над числами со знаком выходит за допустимые для них пределы. Например, если при сложе­нии двух положительных чисел получается число со старшим битом, равным единице, то есть отрицательное, и наоборот. Флаги IOPL (уровень привилегий ввода-вывода) и NT (вложенная задача) применяются в защищенном режиме.

 

Способы адресации

 

Большинство команд процессора вызываются с аргументами, которые в ассемблере принято называть операндами. Например: команда сложе­ния содержимого регистра с числом требует задания двух операндов — содержимого регистра и числа. Далее рассмотрены все существующие способы задания адреса хранения операндов — способы адресации.

Регистровая адресация

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

mov ax,bx

Непосредственная адресация

Некоторые команды (все арифметические команды, кроме деления) по­зволяют указывать один из операндов непосредственно в тексте про­граммы, например команда

mov ax,2

помещает в регистр АХ число 2.

Прямая адресация

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

mov ax,es:0001

поместит это слово в регистр AX. В реальных программах обычно для задания статических переменных используют директивы определения данных, которые позволяют ссылаться на статические переменные не по адресу, а по имени. Тогда, если в сегменте, указанном в ES, была описана переменная word_var размером в слово, можно записать ту же команду как

mov ax,es:word_var

В таком случае ассемблер сам заменит имя “word_var” на соответствующий адрес. Если селектор сегмента данных находится в DS, имя сегментного регистра при прямой адресации можно не указывать, DS используется по умолчанию. Прямая адресация иногда называется адресацией по смещению.

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

Косвенная адресация

По аналогии с регистровыми и непосредственными операндами адрес операнда в памяти также можно не указывать непосредственно, а хранить в любом регистре. До 80386 для этого можно было использовать только BX, SI, DI и BP, но потом эти ограничения были сняты, и адрес операнда разрешили считывать также из EAX, EBX, ECX, EDX, ESI, EDI, EBP и ESP (но не из AX, CX, DX или SP напрямую). Например, следующая команда помещает в регистр AX слово из ячейки памяти, селектор сегмента которой находится в DS, а смещение — в BX:

mov ax,[bx]

Как и в случае прямой адресации, DS используется по умолчанию, но не во всех случаях: если смещение берут из регистров ESP, EBP или BP, то в качестве сегментного регистра используется SS. В реальном режиме можно свободно пользоваться всеми 32‑битными регистрами, надо только следить, чтобы их содержимое не превышало границ 16-битного слова.







Последнее изменение этой страницы: 2016-08-15; Нарушение авторского права страницы

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.235.172.213 (0.007 с.)