Э. Таненбаум - Архитектура компьютера (1127755), страница 193
Текст из файла (страница 193)
Часто стек, связанный с выполнением процедуры, называется стековым фреймом. Когда ранее вызванная процедура вызывает другую процедуру, выделяется дополнительный стековый фрейм, который, как правило, размещается непосредственно под первым. Соответственно, при вызове всех последующих процедур для каждой из них в нисходящем порядке выделяются новые стековые фреймы. Не всегда, но в болыпинстве случаев стеки прирастают по нисходя- Процессор 8088 761 щей — от больших адресов к меньшим. Тем не менее, вершиной стека называется наименьший по величине адрес. Помимо локальных переменных, в стеках хранятся временные результаты выполнения.
В процессоре 8088 есть команда РО5Н, которая помещает 18-разрядное слово на вершину стека. Для этого она сначала уменьшает значение регистра 5Р на 2, а затем сохраняет свой операнд по адресу, на который этот регистр указывает после обновления. Команда РОР удаляет 16-разрядные слова с вершины стека аналогичным образом — выбирает размещенное на этой вершине значение и прибавляет к содержимому регистра 5Р двойку. Регистр 5Р, указывающий на вершину стека, можно изменить командами РО5Н, РОР и САСС; при этом РО5Н и САСС уменьшают его значение, а РОР, наоборот, увеличивает.
Следующий регистр в этой группе называется указателем базы (ВР). Обычно в него записывается некий адрес в стеке. В отличие от регистра 5Р, который всегда указывает на вершину стека, ВР может указывать на любое место в стеке. Чаще всего регистр ВР применяется для указания на начало стекового фрейма текущей процедуры; тем самым упрощается задача поиска ее локальных переменных. Таким образом, ВР часто указывает дно текущего стекового фрейма (иными словами, на слово в стековом фрейме с наименьшим числовым значением), а 5Р— на его вершину (на слово в стековом фрейме с наибольшим числовым значением). Следовательно, границы текущего стекового фрейма определяются значениями регистров-указателей ВР и 5Р. В этой группе есть два индексных регистра: 51 (5опгсе 1пдех — индекс источника) и 01 (1)езг)паг(оп 1пдех — индекс приемника).
В сочетании с ВР эти регистры часто употребляются для адресации данных в стеке, а в сочетании с ВХ вЂ” для вычисления адресов памяти. Более подробно о применении этих регистров мы поговорим в разделе, посвященном режимам адресации. Один из важнейших регистров, составляющий самодостаточную группу, называется указателем команд; этот термин введен 1пге!, в обгцем случае такой регистр называется счетчиком команд (РС). Команды обращаются к нему за адресами кодовых сегментов в памяти.
Цикл выполнения команд процессором начинается с выборки команды, на которую указывает регистр РС Перед выполнением последующих команд цикла к значению этого регистра прибавляется единица. Таким образом, счетчик команд всегда указывает на первую команду вслед за текущей. Флаговый регистр, или регистр кода условия, по существу, представляет собой целый набор регистров, по одному биту каждый; + Š— нулевой результат; + 5 — отрицательный результат (знаковый бит); + Ч вЂ” результат породил переполнение; + С вЂ” результат породил перенос; + А — служебный перенос (из бита 3); + Р— четность результата.
Другие биты в этом регистре регулируют различные аспекты работы процессора. В частности, бит 1 включает прерывания, а бит Т вЂ” режим трассировки, применяемый для отладки программ. Наконец, бит 0 регулирует направление 762 Приложение В. Программирование на языке ассемблера строковых операций. Не все 16 бит флагового регистра задействованы; неиспользуемые биты имеют фиксированное нулевое значение. К группе сегментных регистров причисляется четыре регистра. Как вы помните, стек, данные и коды команд хранятся в разных областях основной памяти. Сегментные регистры объединяют эти области памяти, называемые сегментами. К сегментным регистрам относятся регистр кодового сегмента (С5), регистр сегмента данных (05), регистр стекового сегмента (55) и регистр дополнительного сегмента (Е5).
Большую часть времени их значения остаются неизменными. На самом деле сегмент данных и стековый сегмент относятся к одной и той же области памяти, но данные хранятся на дне этого общего сегмента, а стек — на вершине. Более подробно о сегментах мы поговорим в подразделе «Организация памяти и сегменты» раздела «Память и адресация».
Память и адресация Память процессора 8088 организована достаточно необычно, что объясняется сочетанием 1-мегабайтной памяти и 16-разрядных регистров. Дело в том, что в памяти емкостью 1 Мбайт для представлеггия адреса требуется 20 бит. Следовательно, сохранить указатель на элемент памяти в одном 16-разрядном регистре невозможно. В целях решения проблемы память поделена на сегменты по 64 Кбайт каждый, и адреса в рамках этих сегментов умещаются в 16 бит. Далее мы рассмотрим архитектуру памяти 8088 более подробно. Организация памяти и сегменты Память процессора 8088, состоящая из массива адресуемых 8-разрядных байтов, применяется для хранения команд, данных и стека.
Для разделения областей памяти, применяемых для разных целей, в процессоре 8088 вводится понятие сегментов, которые представляют собой отделенные друг от друга блоки памяти. Такой сегмент в 8088 состоит из 65 536 последовательных байтов. Всего сегментов четыре: кодовый, данных, стековый и дополнительный. В кодовом сегменте содержатся команды, из которых состоят программы. Содержимое регистра РС всегда интерпретируется как адрес кодового сегмента в памяти. Нулевое значение РС указывает не на абсолютный нулевой адрес в памяти, а на нижний адрес в данном кодовом сегменте.
В сегменте данных сохраняются инициализированные и неинициализированные данные программы. Если в регистре ВХ содержится указатель, он обязательно указывает на сегмент данных. В стековом сегменте содержатся локальные переменные и промежуточные результаты, помещенные в стек. Адреса, указанные в регистрах 5Р и ВР, всегда относятся к стековому сегменту. Дополнительный сегмент — это вспомогательный сегментный регистр, который по необходимости можно разместить в произвольном месте в памяти.
Кагкдому из этих сегментов соответствует один из 16-разрядных сегментных регистров: С5, 05, 55 или Е5. Начальным адресом сегмента является 20-разрядное целое число без знака, формируемое путем сдвига сегментного регистра на 4 би- Память и адресация 763 та влево и размещения в четырех освободившихся позициях справа четырех нулей. Следовательно, сегментные регистры в рамках 20-разрядного адресного пространства всегда выражаются числами, кратными 16. Сегментный регистр указывает на базу сегмента. Адреса сегментов формируются путем преобразования 16-разрядного значения в сегментном регистре в фактический 20-разрядный адрес — для этого в конец значения прибавляется четыре нулевых бита и выполняется смещение. В итоге абсолютный адрес в памяти устанавливается путем умножения значения в сегментном регистре на 16 и прибавления смещения.
К примеру, если значение 05 равняется 7, а ВХ вЂ” 12, значит, ВХ указывает на адрес 7 х 16 + 12 = 124. Иными словами, на основании значения 7 в регистре 05 можно получить 20-разрядный двоичный адрес 00000000000001110000. Добавив к исходному значению сегмента 16-разрядное смещение 0000000000001100 (десятичное 12), получаем 20-разрядный адрес 00000000000001111100 (десятичное 124).
При каждом обращении к памяти один из сегментных регистров применяется для формирования фактического адреса в памяти. Если та или иная команда содержит непосредственный адрес без указания на регистр, считается, что этот адрес находится в сегменте данных, и для определения базы этого сегмента используется регистр 05. Физический адрес определяется путем сложения результата предыдущей операции с адресом, указанным в команде. Физический адрес в памяти кода следующей команды устанавливается путем смещения содержимого регистра С5 на четыре двоичных разряда и сложения со значением счетчика команд. Иными словами, сначала на основе значения 16-разрядного регистра С5 вычисляется фактический 20-разрядный адрес, а затем к нему прибавляется новое 16-разрядное значение РС; в результате получается 20-разрядный абсолютный адрес в памяти.
Стековый сегмент состоит из 2-байтовых слов, а это значит, что в указателе стека (5Р) может храниться только четное число. Стек заполняется в порядке от больших адресов к меньшим. Таким образом, команда Р05Н уменьшает значение указателя стека на 2, а затем сохраняет операнд по адресу в памяти, вычисленному на основании значений 55 и 5Р. Команда РОР извлекает полученное после выполнения операции Р05Н значение и увеличивает значение 5Р на 2. Те адреса в стековом сегменте, которые расположены ниже предела, определяемого регистром 5Р, считаются свободными. Следовательно, очистка стека осуществляется за счет одного лишь приращения 5Р. На практике значения регистров 05 и 55 всегда совпадают, так что для обращения к переменной в общем сегменте данных и стека достаточно 16-разрядного указателя.
Если бы значения регистров 05 и 55 различались, к каждому указателю потребовалось бы прибавлять 17-й бит — только так можно было бы различить указатели на сегмент данных и на стековый сегмент. По большому счету, создание разработчиками микросхемы отдельного стекового сегмента вряд ли можно признать оправданным. Если адреса в четырех сегментных регистрах значительно отстоят друг от друга, эти сегменты разделяются, однако в условиях ограниченного объема доступной памяти разделять их не обязательно. Объем программного кода после компиляции неизвестен. Поэтому эффективнее всего размещать начальную границу сегмента данных и стекового сегмента через первое кратное 16 значение 764 Приложение В. Программирование на языке ассемблера после последней команды.
В этом решении подразумевается, что кодовый сегмент и сегмент данных нн при каких обстоятельствах не будут использовать один и тот же физический адрес. Адресация Для выполнения абсолютного большинства команд требуются данные, которые извлекаются либо из памяти, либо из регистров. Для именования этих данных в 8088 предусмотрено несколько режимов адресации. Многие команды содержат по два операнда, которые в этом случае обычно называются исходным (источник) и целевым (приемник).