Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методички по ассемблеру / Методичка_часть1 Архитектура Вычислительных Систем-Новиков.doc
Скачиваний:
88
Добавлен:
02.05.2014
Размер:
1.31 Mб
Скачать

2.1.2. Сегментные регистры

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

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

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

2.1.3. Стек

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

Дно стека

FFFFFFFC

FFFFFFF8 Параметры

FFFFFFF4

FFFFFFF0 EBP=FFFFFFF0

FFFFFFEC

FFFFFFE8 локальные переменные

FFFFFFE4 ESP=FFFFFFE4

Рис. 4. Стек

При вызове подпрограммы параметры в большинстве случаев помещают в стек, а в EBP записывают текущее значение ESP. Тогда, если подпрограмма использует стек для хранения локальных переменных, ESP изменится, но EBP можно будет использовать для того, чтобы считывать значения параметров напрямую из стека (их смещения будут записываться как EBP + номер параметра). Более подробно вызовы подпрограмм и все возможные способы передачи параметров рассмотрены в главе 4.3.2.