Сдам Сам

ПОЛЕЗНОЕ


КАТЕГОРИИ







Регистры процессора. Их назначение.





В статье 1 при описании приведенной там программы упоминались регистры процессора, в частности, сегментные и общего назначения. Регистры процессора являются важнейшим инструментом программиста (между прочим, не только на языке ассемблера, но и на языках высокого уровня), и необходимо иметь четкое представление о составе регистров процессора, их названиях и применении. В примере 1.1 в явной форме использовались лишь три регистра процессора — AX (и его старшая половина AH), DS и DX; по мере чтения книги вы столкнетесь с примерами использования остальных регистров. Однако для того, чтобы читатель мог получить общее представление об этом важном средстве, ниже дан краткий обзор всей системы регистров процессора. Если в этом обзоре вам встретятся незнакомые понятия или неясные места — не огорчайтесь; в последующих статьях они будут описаны более подробно.

Строго говоря, приведенное ниже описание относится только к процессорам 8086 и 80286, для которых были характерны 16-разрядные регистры. В современных процессорах типа Pentium почти все регистры 32-разрядные, что существенно увеличивает возможности компьютера. Однако младшие половины регистров этих процессоров совпадают и по названиям, и по назначению с 16-разрядными регистрами процессора 8086. Поэтому программы, написанные для выполнения под управлением MS-DOS, то есть для 16-разрядного процессора, прекрасно работают и на 32-разрядном, хотя и не используют все его возможности. Поначалу мы ограничимся 16-разрядной архитектурой; особенности современных 32-разрядных процессоров будут описаны позже.

Процессор содержит двенадцать 16-разрядных программно-адресуемых регистров, которые принято объединять в три группы: регистры данных, регистры-указатели и сегментные регистры. Кроме того, в состав процессора входят счетчик команд и регистр флагов (рис. 3.1).

Рис. 3.1. Регистры процессора

В группу регистров данных включаются регистры AX, BX, CX и DX. Программист может использовать их по своему усмотрению для временного хранения любых объектов (данных или адресов) и выполнения над ними требуемых операций. При этом регистры допускают независимое обращение к старшим (AH, BH, CH и DH) и младшим (AL, BL, CL и DL) половинам. Так команда

mov BL,AH

пересылает старший байт регистра AX в младший байт регистра BX, не затрагивая при этом вторых байтов этих регистров. Еще раз отметим, что сначала указывается операнд-приемник, а после запятой — операнд-источник, т.е. команда выполняется как бы справа налево. Во многих случаях регистры общего назначения вполне эквивалентны, однако предпочтительнее в первую очередь использовать AX, поскольку многие команды занимают в памяти меньше места и выполняются быстрее, если их операндом является регистр AX (или его половины AH или AL).

Индексные регистры SI и DI так же, как и регистры данных, могут использоваться произвольным образом. Однако их основное назначение — хранить индексы (смещения) относительно некоторой базы (т.е. начала массива) при выборке операндов из памяти. Адрес базы при этом обычно находится в одном из базовых регистров (BX или BP). Примеры такого рода будут приведены ниже.

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

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

Регистры SI, DI, BP и SP, в отличие от регистров данных, не допускают побайтовую адресацию.

Четыре сегментных регистра CS, DS, ES и SS хранят начальные адреса сегментов программы и, тем самым, обеспечивают возможность обращения к этим сегментам.

Регистр CS обеспечивает адресацию к сегменту, в котором находится код команд программы, регистры DS и ES — к сегментам данных (таким образом, в любой точке программа может иметь доступ к двум сегментам данных, основному и дополнительному), а регистр SS — к сегменту стека. Сегментные регистры, естественно, не могут выступать в качестве регистров общего назначения.

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

Регистр флагов, эквивалентный регистру состояния процессора других вычислительных систем, содержит информацию о текущем состоянии процессора (рис. 3.2). Он включает 6 флагов состояния и 3 бита управления состоянием процессора, которые, впрочем, тоже обычно называются флагами.


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

Флаг переноса CF (Carry Flag) индицирует перенос или заем при выполнении арифметических операций, а также служит индикатором ошибки при обращении к системным функциям.

Флаг паритета PF (Parity Flag) устанавливается в 1, если младшие 8 бит результата операции содержат четное число двоичных единиц.

Флаг вспомогательного переноса AF (Auxiliary Flag) используется в операциях над упакованными двоично-десятичными числами. Он индицирует перенос или заем из старшей тетрады (бита 4).

Флаг нуля ZF (Zero Flag) устанавливается в 1, если результат операции равен нулю.

Флаг знака SF (Sign Flag) показывает знак результата операции, устанавливаясь в 1 при отрицательном результате.

Флаг переполнения OF (Overflow Flag) фиксирует переполнение, т.е. выход результата операции за пределы допустимого для данного процессора диапазона значений.

Флаги состояния автоматически устанавливаются процессором после выполнения каждой команды. Так, если в регистре AX содержится число 1, то после выполнения команды декремента (уменьшения на 1)

dec AX

содержимое AX станет равно 0, и процессор сразу отметит этот факт, установив в регистре флагов бит ZF (флаг нуля). Если попытаться сложить два больших числа, например, 58000 и 61000, то установится флаг переноса CF, так как число 119000, получающееся в результате сложения, должно занять больше двоичных разрядов, чем помещается в регистрах или ячейках памяти, и возникает «перенос» старшего бита этого числа в бит CF регистра флагов.

Индицирующие флаги процессора дают возможность проанализировать, если это нужно, результат последней операции и осуществить «разветвление» программы: например, в случае нулевого результата перейти на выполнение одного фрагмента программы, а в случае ненулевого — на выполнение другого фрагмента. Такие разветвления осуществляются с помощью команд условных переходов, которые в процессе своего выполнения анализируют состояние регистра флагов. Так, команда

jz zero

осуществляет переход на метку zero, если результат выполнения предыдущей команды окажется равен нулю (т.е. флаг ZF установлен), а команда

jnc okey

выполнит переход на метку okey, если предыдущая команда сбросила флаг переноса CF (или оставила его в сброшенном состоянии).

Управляющий флаг трассировки TF (Trace Flag) используется в отладчиках для осуществления пошагового выполнения программы. Если TF = 1, то после выполнения каждой команды процессор реализует процедуру прерывания 1 (через вектор прерывания с номером 1).

Управляющий флаг разрешения прерываний IF (Interrupt Flag) разрешает (если равен 1) или запрещает (если равен 0) процессору реагировать на прерывания от внешних устройств.

Управляющий флаг направления DF (Direction Flag) используется особой группой команд, предназначенных для обработки строк. Если DF = 0, строка обрабатывается в прямом направлении, от меньших адресов к большим; если DF = 1, обработка строки идет в обратном направлении.

Таким образом, в отличие от битов состояния, управляющие флаги устанавливает или сбрасывает программист, если он хочет изменить настройку системы (например, запретить на какое-то время аппаратные прерывания или изменить направление обработки строк).

Вернемся к примеру 1.1. Для того, чтобы инициализировать сегментный регистр DS сегментным адресом text нашего (единственного) сегмента, значение text загружается сначала в регистр общего назначения AX, а из него — в сегментный регистр DS. В принципе в качестве «перевалочного пункта» вместо регистра AX можно взять любой другой (например, BX или SI), однако некоторым трансляторам это может не понравиться, так что лучше все-таки использовать AX.

В предложении 5 в регистр AH заносится номер функции DOS, реализующей вывод на экран строки текста. DOS, получив управление с помощью команды int 21h, определяет номер требуемой функции именно по содержимому регистра AH, поэтому никаким другим регистром здесь воспользоваться нельзя. Функция DOS для вывода строки извлекает адрес выводимой строки из регистра DX, поэтому в строке 6 использование регистра DX также предопределено. В действительности дело обстоит сложнее. Функция 09hпредполагает, что строка с выводимым текстом находится в сегменте, на который указывает вполне определенный сегментный регистр, а именно регистр DS. Поэтому перед вызовом функции 09h необходимо настроить этот регистр, что мы и сделали в предыдущих предложениях программы. Сведения о том, какие регистры требуется настроить для выполнения той или иной функции DOS, можно почерпнуть из справочника по функциям DOS, без которого, таким образом, практически невозможно писать программы с обращениями к системным средствам.

В предложениях 8...10 осуществляется вызов системной функции 4Ch, служащей для завершения текущей программы. По-прежнему номер функции заносится в регистр AH; кроме этого, в AL помещается код завершения программы, который в нашем примере равен 0.

Др.док.:

Регистры входят в состав любого процессора. Каждый компьютер, в том числе и процессор х86, который по-своему, тоже является компьютером, нуждается в месте для временного хранения обрабатываемой информации.

Менялись процессоры х86, менялись количество и размер их регистров. Первенцы, 8086 и 8088, имели 14 регистров, каждый из которых вмещал в себя 16-разрядное число. В последнем члене семейства, Pentium II, регистров гораздо больше, большинство из них хранят в себе 64-разрядные числа. Некоторые из регистров хранят числа и подлиннее. В случае с этими большими регистрами, называемыми буферами ассоциативной трансляции.(translation lookaside buffers), программе, выполняемой CPU, видна только часть содержащихся в них битов. Остаток спрятан из поля зрения программы, но вполне доступен CPU, что ускоряет его работу.

Одна из причин, по которым в последних моделях процессоров х86 так много регистров, заключается в том, что процессоры стали настолько сложны, что в них были добавлены специальные регистры, облегчающие автоматическое тестирование процессора в конце производственного цикла - ведь нужно убедиться в правильной работе процессора перед тем, как он покинет стены фирмы-изготовителя. Есть и другая причина. Дополнительно к оборудованию, предназначенному непосредственно для выполнения основной вычислителительной работы (для которой процессоры и созданы), все эти модели включают в себя аппаратные средства управления системой {system management hardware), выполняющие различные специальные операции, перевод процессов в энергосберегающий режим при длительном простое, например.

Рассмотрим сначала регистры процессора 8086. Все остальные регистры, добавленные позднее в другие модели семейства х86, похожи на них, по крайне мере концептуально. Всего в 8086 (и в 8088) 14 регистров, их можно разнести по 5 категориям, краткое описание каждой из которых и имен соответствующих им регистров дано ниже.

1. Регистры общего назначения

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

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

Имена этих регистров очень просты. Когда они используются полностью, как 16-разрядные регистры, их называютАХ, ВХ, СХ и DX (букву Х можно считать сокращением слова extended, т. е. расширенный). Когда требуется обратиться к одной из 8-разрядных частей регистров, то младшие (правые) байты называются AL, BL, CL и DL, а старшие (левые) АН, ВН, СН и DH.

Регистр АХ (или АН плюс AL) наиболее часто используется как аккумулятор (accumulator) - место, где накапливаются результаты вычислений. Например, к содержимому регистра А можно прибавить число из другого регистра или из основной памяти так, чтобы полученная сумма оказалась в регистре А, заместив его предыдущее значение

В регистре ВХ чаще всего хранят сегментную часть адреса. Отсюда и его мнемоническое имя - базовый (base), так как сегментная часть адреса указывает на начало некоторой области памяти и служит отправной (базовой) точкой для дальнейшей адресации внутри этой области. Регистр ВХ (или BL, или ВН) можно использовать и для хранения данных другого рода.

Регистр СХ обычно используется как регистр счетчика (counter). В нем хранят число, показывающее, сколько раз была повторена некоторая операция Когда число повторений достигает заранее определенного значения, в программе происходит передача управления в другую точку По большому счету, счетчиком может быть любой регистр общего назначения, но только с регистром СХ необходимые сравнение и переход осуществляются за одну инструкцию Регистр DX (или DH и DL) принято называть регистром данных (data) Иногда он используется для хранения адреса порта. Иногда он используется в паре с регистром АХ для хранения 32-разрядного числа, получающегося, например, в результате умножения двух 16-разрядных чисел.

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

Регистр флагов (flags register) - так называется один очень специфичный регистр, рассматриваемый обычно не как единое целое, а как набор 16 отдельных битов, каждый из которых указывает на определенный факт Наверное, простейший по значению флаг - это флаг, показывающий, оказались ли сравниваемые числа равными между собой или нет. Другие флаги показывают, был ли результат последней арифметической операции положительным, либо отрицательным, был ли он нулевым, было ли переполнение, т. е. выход получившегося числа за пределы 16 разрядов. Есть флаги, характеризующие состояние процессора: отвечает ли он на внешние прерывания или игнорирует их, находится ли в пошаговом режиме выполнения, а также, при обработке цепочек данных, работает ли он "вверх" по цепочке или "вниз"?

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

3. Регистры - указатели

Еще один специальный регистр хранит адрес в основной памяти текущей исполняемой инструкции. И называется он указатель инструкций (instruction pointer, IP). Но указывает этот регистр на ячейку основной памяти, где хранится текущая выполняемая инструкция, несколько неявным образом. Для получения нормального полноценного адреса необходимо по определенному правилу скомбинировать значение из регистра IP со значением из другого регистра, называемого регистром сегмента кода (code segment register).

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

Нормальное выполнение программы

До тех пор, пока выполняемая инструкция не предписывает другого, значение регистра IP, иногда называемого счетчиком команд (program counter), после выполнения инструкции автоматически увеличивается на ее длину. Так как чаще всего следующая инструкция, подлежащая выполнению, хранится в основной памяти сразу после текущей инструкции, то это правильно и удобно, тем более что процессоры х86 являются CISC-устройствам с переменной длиной инструкций.

Инструкции перехода

Примерно 10% времени выполнения программы это не так. В этих случаях текущая инструкция может предписывать процессору перейти в некоторую другую точку программы. Такие инструкции называются инструкциями ветвления (branch instructions) или инструкциями перехода (jump instructions), и бывают они двух видов. Один тип инструкций, называемый безусловным ветвлением (unconditional branch instructions), всегда приводит к переходу к другой точке программы. В другом типе инструкций, называемых инструкциями условного ветвления (conditional branch instructions), такой переход осуществляется лишь при выполнении определенного условия, иначе выполняется инструкция, непосредственно следующая за инструкцией условного ветвления. Решение о переходе обычно базируется на значении одного из битов peгистра флагов. На рис. 2.1. наглядно объясняется различие между нормальным выполнением и обоими типами ветвлений. При нормальном выполнении программы инструкции выполняются последовательно, от низших адресов памяти к высшим (ситуация 1). Инструкция безусловного перехода переводит выполнение программы через таблицу данных и другие препятствия (ситуация 2). Инструкция проверки, за которой следует инструкция ветвления, может привести к двум результатам. Если проверка выдаст значение "Истина", выполнение программы пойдет по ветви "Да". Если проверка выдаст значение "Ложь", выполнение программы продолжится со следующей инструкции (ветвь "Нет") (ситуация 3). Инструкции могут образовать цикл. Если проверка выдает значение "Истина", цикл выполняется еще раз. Если она выдает значение "Ложь", программа выходит из цикла (ситуация 4).

Кроме регистра IP, в 8086 есть еще два регистра-указателя (pointer registers). Название первого - указатель базы, или ВР (base pointer), другого - указатель стека, или SP (stack pointer). Каждый из них хранит число, используемое при работе процессора в реальном режиме в качестве сегментной части адреса. В защищенном режиме эти числа называются селекторами (selectors), но выполняют похожую функцию. В любом случае, эти регистры используются для указания на начало области памяти, отведенной под стек.

Каждый раз, переключаясь с одной задачи на другую, CPU требуется сохранить где-нибудь текущее содержимое всех регистров для этой задачи и загрузить в эти регистры значения, оставшиеся от предыдущего цикла работы со следующей задачей. Здесь-то CPU и нужен стек. Разумеется, стек используется и в других случаях, но этот пример — самый показательный из возможных.

Рисунок 2.1. Нормальное выполнение программы и влияние на него инструкций перехода

Концепция стека очень проста — последним пришел, первым ушел, Last-In-First-Out (LIFO)

В компьютере стек реализуется в виде области памяти, отведенной под него, плюс регистр, содержащий адрес вершины стека. Когда число (для простоты один байт) помещается в стек, то оно записывается в память по адресу вершины стека, а значение адреса уменьшается на единицу, поэтому следующий байт, помещенный в стек, окажется в памяти рядом с предыдущим, но ниже. И наоборот, когда байт извлекается из стека, он читается из ячейки памяти по адресу из этого регистра, после чего значение регистра увеличивается на единицу. На рис. 2.2. показано, как эта концепция реализована внутри компьютера. Число, помещенное в стек первым, находится по адресу, соответствующему первоначальному (и максимальному) значению регистра SP, указателя стека. Значение в регистре SP (смещение) складывается с линейным адресом, для получения которого используется селектор из SS, регистра сегмента стека. Селектор в регистре SS указывает на дескриптор, содержащий этот линейный адрес. Число, помещенное в стек последним, находится по адресу, соответствующему минимальному значению указателя стека. Именно оно будет следующим числом, взятым из стека.

Рисунок 2.2. Работа стека

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

Любая грамотно написанная программа одним из своих первых действий создает свой собственный стек для дальнейшего единоличного использования. Делается это потому, что в уже существующем стеке к этому моменту может не остаться столько места, сколько нужно программисту. Создается новый стек простым выделением области памяти требуемого объема, после чего в существующий стек помещаются текущие значения указателя стека и сегмента стека, а затем в регистры SP и SS загружаются новые значения, указывающие на только что выделенный участок памяти. В конце своей работы программа извлекает из стека старые значения этих регистров и восстанавливает CPU в его первоначальное состояние. (Кроме того, в стеке необходимо сохранить значения всех регистров, содержимое которых программа собирается изменить с тем, чтобы в конце вернуться к сохраненным значениям.)

В любой момент времени внутри ПК может находиться любое количество стеков, но только один из них будет текущим (current), т. е. тем, на который указывает логический адрес [SPj:[SS]. В этой системе обозначений подразумеваются два числа, содержащихся в этих регистрах, разделенных двоеточием.

Во всех последних моделях процессоров х86 имеется еще один стек, связанный с операциями над числами с плавающей точкой —и в Pentium ММХ и Pentium 11 — с выполнением инструкций ММХ. Он состоит из восьми 80-разрядных регистров внутри CPU и обычно используется только инструкциями ММХ и математическими инструкциями с плавающей точкой, и совершенно не похож на "стандартный" стек, создаваемый внутри основной памяти и используемый инструкциями pop (взять из стека) и push (поместить в стек).

Стек — одна из наиважнейших вещей в программировании. С ним можно писать гораздо более сложные программы, чем без него, только с регистрами CPU для временного хранения/информации. Без стека вся идея многозадачности так и осталась бы всего лишь идеей.

4. Индексные регистры

Таковыми являются регистры SI и DI, используются они, в основном, при перемещении цепочек данных (многобайтных последовательностей произвольной длины) Регистр SI называется регистром индекса источника (so index register) и содержит адрес начала цепочки, которую требуется переместить. Регистр DI называется регистром индекса приемника (destination index register) и содержит адрес, по которому нужно переместить цепочку. Число перемещаемых байт обычно хранится в регистре СХ (счетчике). Кроме операций по перемещению цепочек данных, индексные регистры можно применять и для адресации внутри массивов числовых данных.

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

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

Первый из таких регистров, CS - регистр сегмента кода (code segment register). В сочетании с регистром IP он образует полный адрес текущей выполняемой инструкции Следующий регистр - регистр DS, известный как регистр сегмента данных (data segment register), обычно указывает на начало области памяти, отведенной под данные. В сочетании с регистрамиВХ, SI или DI может использоваться для доступа к определенным байтам или словам внутри области данных. Третий регистр носит имяES, он же регистр дополнительного сегмента (extra segment register). Как подсказывает его имя, это просто дополнительный сегментный регистр, отданный на откуп программисту, но наиболее естественно видеть его имя в инструкциях по обработке цепочек Имя последнего регистра пишется как SS, а расшифровывается как регистр сегмента стека (stack segment register). В сочетании с регистром SP, регистр SS указывает на текущее хранимое в стеке число, но может использоваться и в паре с регистром ВР при выполнении некоторых инструкций.

Вопрос №16:







Живите по правилу: МАЛО ЛИ ЧТО НА СВЕТЕ СУЩЕСТВУЕТ? Я неслучайно подчеркиваю, что место в голове ограничено, а информации вокруг много, и что ваше право...

ЧТО И КАК ПИСАЛИ О МОДЕ В ЖУРНАЛАХ НАЧАЛА XX ВЕКА Первый номер журнала «Аполлон» за 1909 г. начинался, по сути, с программного заявления редакции журнала...

Конфликты в семейной жизни. Как это изменить? Редкий брак и взаимоотношения существуют без конфликтов и напряженности. Через это проходят все...

ЧТО ПРОИСХОДИТ ВО ВЗРОСЛОЙ ЖИЗНИ? Если вы все еще «неправильно» связаны с матерью, вы избегаете отделения и независимого взрослого существования...





Не нашли то, что искали? Воспользуйтесь поиском гугл на сайте:


©2015- 2024 zdamsam.ru Размещенные материалы защищены законодательством РФ.