Сделай Сам Свою Работу на 5

Флаги кодов условий регистра состояния

Процессор отслеживает результаты выполнения различных операций, и сохраня­ет их для использования в последующих инструкциях условного перехода. Эту информацию он записывает в специальные биты регистра состояния, называемые флагами кодов ус­ловий. В зависимости от результата выполненной операции отдельные флаги ус­танавливаются в 1 или 0. Флаги процессора Intel:

CF – флаг переноса;флаг переполнения;

PF – флаг четности;

AF – флаг дополнительного переноса;

ZF – флаг нуля;

SF – флаг знака;

TF – флаг перехвата;

IF – флаг разрешения прерывания;

DF – флаг направления обработки строк;

OF – флаг переполнения.

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

· PF (Parity Flag - флаг четности). Проверяет младшие восемь битов результатов операций над данными. Нечетное число битов приводит к установке этого флага в 0, а четное - в 1. Не следует путать флаг четности с битом контроля на четность. 1

· AF (Auxiliary Carry Flag - вспомогательный флаг переноса). Устанавливается в 1, если арифметическая операция приводит к переносу четвертого справа бита (бит номер 3) в регистровой однобайтовой команде. Данный флаг имеет отношение к арифметическим операциям над символами кода ASCII и к десятичным упакованным полям.

· ZF (Zero Flag - флаг нуля). Устанавливается в качестве результата арифметических команд и команд сравнения. Как это ни странно, ненулевой результат приводит к установке нулевого значения этого флага, а нулевой - к установке единичного значения. Кажущееся несоответствие является, однако, логически правильным, так как 0 означает "нет" (т.е. результат не равен нулю), а единица означает "да" (т.е. результат равен нулю). Команды условного перехода JE и JZ проверяют этот флаг.

· SF (Sign Flag - флаг знака). Устанавливается в соответствии со знаком результата (старшего бита) после арифметических операций:

· положительный результат устанавливает 0, а отрицательный - 1. Команды условного перехода JG и JL проверяют этот флаг. .

· TF (Trap Flag - флаг трассировки). Этот флаг устанавливается, если используется команда Т в отладчике DEBUG. Если этот флаг установлен в единичное состояние, то процессор переходит в режим пошагового выполнения команд, т.е. в каждый момент выполняется одна команда под пользовательским управлением.

· IF (Interrupt Flag - флаг прерывания). При нулевом состоянии этого флага прерывания запрещены, при единичном - разрешены.

· DF (Direction Flag - флаг направления). Используется в строковых операциях для определения направления передачи данных. При нулевом состоянии команда увеличивает содержимое регистров SI И DI, вызывая передачу данных слева направо, при нулевом - уменьшает содержимое этих регистров, вызывая передачу данных справа налево.

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

Ниже приводятся наиболее часто используемые из них:

Флаги S и Z указывают, является результат арифметической операции отри­цательным или нулевым. Кроме арифметических команд на эти флаги воз­действует команда TST, анализирующая значение в регистре или в памяти компьютера и устанавливающая либо очищающая флаги S и Z в соответствии с этими значения­ми. Флаг O указывает на то, что произошло переполнение. Как вы помните, пере­полнение происходит, когда результат арифметической операции превышает зна­чение, которое можно представить с помощью количества битов, выделенного операнду. Процессор устанавливает флаг O для того, чтобы программист мог оп­ределить, что произошло переполнение, и перейти к подпрограмме, способной исправить данную ошибку. Кроме того, в результате установки бита O в большинстве компьютеров может автоматически выполняться программное прерывание, позволяющее решить эту проблему средствами самой операционной системы.

Флаг С устанавливается в 1, если в ходе арифметической операции осуществ­ляется перенос из позиции старшего бита. Этот флаг позволяет выполнять ариф­метические операции над операндами, длина которых больше длины слова про­цессора. Такие операции реализуются в арифметике с многократно увеличенной точностью.

Примером команды условного перехода, проверяющей один или более флагов условий, может служить команда JGT (Переход если >0, описанная раньше. Она вы­полняет переход к другой точке программы в том случае, если проверяемое значе­ние не отрицательно и не равно нулю. Это означает, что переход возможен, если ни S, ни Z не равен 1. Существует и множество других команд условного перехо­да, позволяющих проверять самые разнообразные условия. Задаются такие усло­вия в виде логических выражений, включающих флаги их кодов.

В процессорах Intel флаги кодов условий автоматически устанавлива­ются командами, которые выполняют арифметические и логические операции.

Однако это не всегда так. Многие компьютеры поддерживают две версии коман­ды Add. Одна из них, Add, не воздействует на флаги, а другая, AddSetCC (Adscc), воздей­ствует. Благодаря этому программисты и компиляторы могут проявлять боль­шую гибкость при создании программ, предназначенных для конвейерного выполнения. В процессоре I-32 и команда ADD и команда ADC, устанавливают флаги условия, но команда ADC при сложении прибавляет еще и значение флага CF.

Пример выполнения команд устанавливающих флаги регистра состояний.

1. Команда сложения. Перед выполнением команды, значение CF=1

Фрагмент программы:

MOV CX,1110001101000101b

MOV AX,1111111000011001b

ADD AX,CX

После выполнения команды ADD:

Регистр AX содержит: 1110000101011111;

флаги регистра состояния следующие:

OF=0

CF=1

SF=1

ZF=0

DF=0

IF =0

TF=0

AF=0

PF=1

5.3. Режимы адресации

В архитектуре IA-32 определен большой и гибкий набор режимов адресации, ис­пользуемых для доступа к отдельным элементам и областям памяти. Мы приве­дем полное описание этих режимов и способов их записи на языке ассемблера.

Основные режимы адресации, поддерживаемые большинством процессоров. Речь идет о непосредственной, абсолютной, регистровой и косвенной регистровой адресации. Абсолютная адресация, согласно терминоло­гии Intel, называется прямой; так ее будем называть и мы. Существует несколько режимов адресации, обеспечивающих большую гибкость доступа к операндам, хранящимся в памяти компьютера. Самым гибким из ре­жимов адресации, является индексный режим, обозначаемый как X(Ri,Rj). Исполнительный адрес операнда, EA, вычисляется в этом режиме так:

EA = [Ri] + [Rj] + Х

где Ri и Rj — это регистры общего назначения, базовый и индексный, а Х — кон­станта, определяющая величину смещения. Среди режимов адресации процессо­ров IA-32 имеется несколько упрощенных разновидностей данного режима. Полный набор режимов адресации процессоров IA-32 таков.

1. Непосредственная адресация (immediate). Операнд содержится прямо в ко­манде. Это 8-разрядное или 32-разрядное число, длина которого опреде­ляется соответствующим битом в поле кода операции. Для короткого опе­ранда указанный бит равен 0, для длинного — 1.

2. Прямая адресация (direct). Адрес операнда в памяти определяется задан­ным в команде 32-разрядным значением.

3. Регистровая адресация (register). Операнд содержится в одном из восьми регистров общего назначения, заданном в команде.

4. Косвенная регистровая адресация (register indirect). Адрес операнда в па­мяти содержится в одном из восьми регистров общего назначения, задан­ном в команде.

5. Базовая со смещением (base with displacement). В команде определяются 8- или 32-разрядное смещение со знаком и один из восьми регистров об­щего назначения, используемый в качестве базового. Исполнительный ад­рес операнда равен сумме содержимого базового регистра и смещения.

6. Индексная со смещением (index with displacement). В команде задаются 32-разрядное смещение со знаком, один из восьми регистров общего на­значения, который должен использоваться в качестве индексного, и коэф­фициент масштабирования — 1, 2, 4 или 8. Для получения исполнитель­ного адреса операнда содержимое индексного регистра умножается на коэффициент масштабирования, а к результату прибавляется смещение.

7. Базовая индексная (base with index). В команде задаются два из восьми регистров общего назначения и коэффициент масштабирования — 1, 2, 4 или 8. Регистры используются как базовый и индексный, а исполнитель­ный адрес операнда вычисляется следующим образом: содержимое ин­дексного регистра умножается на коэффициент масштабирования, а к ре­зультату прибавляется содержимое базового регистра.

8. Базовая индексная со смещением (base with index and displacement). В ко­манде задаются 8- или 32-разрядное смещение со знаком, два из восьми ре­гистров общего назначения и коэффициент масштабирования — 1, 2, 4 или 8. Регистры используются как базовый и индексный, а исполнитель­ный адрес операнда вычисляется следующим образом: содержимое ин­дексного регистра умножается на коэффициент масштабирования, а ре­зультат складывается с содержимым базового регистра и смещением.

Синтаксис перечисленных режимов адресации процессоров IA-32 приведен в табл. 5.1. Кроме того, в ней показано, как вычисляется исполнительный адрес операнда для каждого из режимов. Согласно одной из сносок, регистр ESP не мо­жет использоваться в качестве индексного, поскольку, как вы увидите далее, он служит указателем на стек процессора. Ниже будет рассмотрено несколько при­меров применения режимов адресации процессоров IA-32.

Таблица 5.1.Режимы адресации процессоров IA-32

Значение — 8- или 32-разрядное число со знаком.

Адрес — 32-разрядный адрес.

Reg, Reg1, Reg2 - один из регистров общего назначения (ЕАХ, ЕВХ, ЕСХ, EDX, ESP, ЕВР, ESI, EDI), с тем исключением, что регистр ESP не может использоваться в качестве индексного.

Disp — 8- или 32-разрядное число со знаком (смещение), с тем исключением, что смещение в режиме индексной адресации со смещением может быть только 32-разрядным. S — коэффициент масштабирования, равный 1, 2, 4 или 8.

Для иллюстрации режимов адресации удобно задействовать команду Move. Например, в команде

MOV ЕАХ,25

для пересылки десятичного значения 25 в регистр EAX применяется непосредст­венная адресация. По умолчанию заданное в такой форме число, состоящее из цифр от 0 до 9, интерпретируется как десятичное. Для обозначения двоичных и шестнадцатеричных чисел используются суффиксы В и Н. Например, команда

MOV EAX,3FA00H

пересылает в регистр EAX шестнадцатеричное число 3FA00.

В команде

MOV EAX,LOCATION

используется прямая адресация. Данная команда пересылает в регистр ЕАХ двой­ное слово из памяти по адресу, определяемому меткой LOCATION. При этом предполагается, что указанная метка определена как метка для адреса памяти в разделе объявлений программы на языке ассемблера. Из раздела 5.6 вы поймете, как это делается. Если метка LOCATION представляет адрес 1000, то данная ко­манда пересылает в ЕАХ двойное слово, расположенное по адресу 1000.

Чуть позже мы поговорим о непосредственной и прямой адресации процессо­ров IA-32 более подробно, поскольку эти режимы часто путают. Возьмем такой случай. Иногда бывает полезно определить символические имена для числовых констант, задаваемых непосредственно в командах. Для назначения константам символических имен предназначена команда EQU, описанная в разделе 5.3. На­пример, команда

NUMBER EQU 25

связывает символическое имя NUMBER с десятичным числом 25. После этого команда

MOV EAX,NUMBER

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

Во многих языках ассемблера во избежание такой неоднозначности использует­ся специальный символ, например «#», прибавляемый к числу в качестве префик­са для обозначения непосредственной адресации. В языке ассемблера процессоров IA-32 для этой цели могут использоваться квадратные скобки:

MOV EAX,[LOCATION]

Однако если метка LOCATION определена как адресная, квадратные скобки не нужны.

При необходимости интерпретировать адресную метку как непосредственно заданный операнд можно воспользоваться ассемблерной директивой OFFSET. Так, команда

MOV EBX,OFFSET LOCATION

помещает значение адресной метки LOCATION, предположим 1000, в регистр ЕВХ с применением непосредственной адресации. После этого ЕВХ может ис­пользоваться в косвенном регистровом режиме адресации в команде

MOV ЕАХ,[ЕВХ]

пересылающей в регистр ЕАХ содержимое памяти по адресу LOCATION, содер­жащемуся в регистре ЕВХ. Слово OFFSET (смещение), выбранное для этой ди­рективы языка ассемблера, подчеркивает, что адрес всегда интерпретируется как относительное расстояние от начальной точки сегмента памяти, содержащего операнд команды. Во всех приведенных выше примерах операнд назначения за­давался в регистровом режиме адресации.

Мы проиллюстрировали использование четырех основных типов адресации:

непосредственной,

прямой,

регистровой и

косвенной регистровой.

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

На рис. 5.6. показано, как используется режим базовой адресации со смеще­нием. Базовым регистром здесь служит ЕВР. Двойное слово, расположенное на расстоянии 60 байт от базового адреса 1000, то есть по адресу 1060, можно пере­слать в регистр ЕАХ при помощи команды

MOV ЕАХ,[ЕВР+60]

Команды и режимы адресации процессоров IA-32 могут использоваться для работы, как с отдельными байтами, так и с двойными словами. Если в базовом регист­ре ЕВР содержится, скажем, адрес 1000, то для загрузки в младший байт регистра ЕАХ одного байта, хранящегося по адресу 1010, можно воспользоваться командой

MOV AL,[EBP+60]

Поскольку операнд назначения AL представляет собой младший байт регист­ра ЕАХ, ассемблер выберет код той операции пересылки, которая предназначена для пересылки байтов.

Рис. 5.6. Пример типа адресации в архитектуре IA-32.

Адресация базовая со смещением, заданная как [ЕВР+60]

Наиболее гибкой из всех адресаций является базовая индексная со смещени­ем. Пример ее использования приведен на рис. 5.7., где функции базового и ин­дексного регистров выполняют регистры ЕВР и ESI. Этот пример показывает, как обратиться к операнду, который является одним из элементов списка двой­ных слов. Список начинается со смещением 200 относительно базового адреса 1000. С использованием коэффициента масштабирования 4 для доступа к двой­ным словам по адресам 1200,1204,1208,... можно обращаться при помощи после­довательности индексов 0,1, 2,... в индексном регистре ESI. В нашем случае в ин­дексном регистре содержится значение 40 и при этом выполняется обращение к двойному слову по адресу 1360 (то есть 1000 + 200 + 4 х 40). Данный операнд за­гружается в регистр ЕАХ командой

MOV EAX,[EBP+ESI*4+200]

Использование коэффициента масштабирования облегчает доступ к последо­вательным двойным словам списка в программном цикле, поскольку в этом слу­чае на каждом шаге цикла достаточно увеличивать значение индексного регистра на 1. Мы подробно обсудили два способа адресации, и теперь вы сможете понять, как функционируют сходные режимы адресации — индексная со смещением и ба­зовая индексная.

 

Рис. 5.7. Пример типа адресации в архитектуре IA-32.

Адресация базовая индексная со смещением, заданная как [EBP+ESI*4+200]

Напоследок хотелось бы высказать одно замечание. Может показаться, что ре­жим базовой адресации со смещением (табл. 5.1) является излишним, поскольку тотже результат можно получить при помощи индексной адресации со смещени­ем с коэффициентом масштабирования 1. Однако команда с использованием пер­вого режима на один байт короче. Кроме того, величина смещения во втором слу­чае может задаваться только 32-разрядным числом.

В следующем разделе рассказывается о том, как описанные режимы адресации кодируются в машинных командах. Более подробная информация по данной те­ме приведена в [1].

 

5.4. Команды IA-32

Набор команд архитектуры IA-32 очень обширен. Машинные команды имеют пе­ременную длину и не всегда однотипный формат, о чем будет рассказано ниже. В большинстве команд IA-32 задаются один или два операнда. Если опе­рандов два, только один их них может храниться в памяти, а другой должен находиться в регистре процессора. Наряду с обычными командами для пересыл­ки данных между памятью и регистрами процессора, выполнения арифметиче­ских операций в наборе команд IA-32 имеется множество команд для реализации логических операций, операций сдвига и циклического сдвига, а также для мани­пулирования стеком процессора. Для обработки нечисловых данных предусмот­рены команды, оперирующие строками байтов.

Мы начнем с рассмотрения небольшого набора команд и покажем, как они мо­гут использоваться в сравнительно небольшой программе. Команда

ADD dst,src

выполняет операцию

dst <- [dst] + [src]

а команда

MOV dst,src

как вы уже знаете, — операцию

dst <- [src]

Предположим, что операнды хранятся в регистрах ЕАХ и ЕВХ. Следующие две команды вычисляют сумму операндов в регистре ЕАХ и сохраняют ее в памя­ти по адресу SUM:

ADD EAX,EBX

MOV SUM,EAX

Поскольку в памяти может располагаться только один из операндов команды, для реализации операции С<-[А]+[В] с тремя операндами в памяти потребуется целых три команды:

MOV ЕАХ,А

ADD EAX,B

MOV С,ЕАХ

Команда вычитания

SUB dst,src

выполняет операцию

dst <- [dst] - [src]

Для увеличения и уменьшения операнда на 1 предназначены команды авто­увеличения (инкремента) и автоуменьшения (декремента), INC и DEC.

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

JG LOOPSTART

осуществляет переход по адресу LOOPSTART. Все команды условного перехода начинаются с буквы J, соответствующей слову Jump (переход), за которой следу­ют буквы, обозначающие условие. В данном примере буква G обозначает «боль­ше нуля». О других командах условного перехода будет рассказано чуть позже.

Чтобы получить возможность при косвенной регистровой адресации исполь­зовать регистр общего назначения, нужно сначала загрузить в такой регистр ад­рес операнда команды. Это можно сделать двумя способами. Если для нужного адреса в программе явно определена адресная метка, скажем LOCATION, этот ад­рес можно загрузить в регистр при помощи команды Move и с применением непо­средственной адресации, вот так:

MOV EBX,OFFSET LOCATION

Данная команда загружает в регистр ЕВХ адрес, представленный меткой LO­CATION. В качестве альтернативы можно задействовать команду Load Effective Address (загрузка исполнительного адреса) с мнемоническим обозначением LEA. Команда

LEA EBX,LOCATION

выполняет ту же операцию, что и приведенная выше команда. При помощи ко­манды LEA можно загружать в регистры адреса, динамически вычисляемые во время выполнения программы. Предположим, нам нужно загрузить в регистр ЕВХ адрес операнда, для доступа к которому применяется базовая адресация со смещением. Команда

LEA ЕВХ,[ЕВР+12]

загрузит в регистр ЕВХ адрес операнда, расположенного по адресу [ЕВР]+12. Ад­рес зависит от содержимого регистра ЕВP в момент выполнения команды.

Программа для сложения чисел

Используя только что описанные команды, мы можем создать программу для сложения чисел при помощи цикла. Предположим, что в памяти по адресу N со­держится набор 32-разрядных чисел, расположенных последовательно начиная с адреса NUM1. На рис. 5.8. приведена программа на языке ассемблера, склады­вающая эти числа и помещающая результат в память по адресу SUM.

В регистр ЕВХ загружается значение адреса NUM1. Он используется как ба­зовый регистр при базовой индексной адресации в первой команде цикла, распо­ложенной по адресу STARTADD. Индексным регистром здесь является ECX. На первой итерации цикла к содержимому регистра ЕАХ, первоначально установленному в 0, прибавляется последнее число из списка, хранящееся по адресу [ЕВХ+ECX*4] = NUM1 – 4 + n*4, поскольку в команде ADD задан коэффици­ент масштабирования 4, а базовый регистр мы предварительно уменьшили на 4 командой SUB. Затем значение индексного регистра уменьшается на 1. На второй итерации цикла к содержимому регистра ЕАХ прибавляется предпоследнее 32-разрядное число, расположенное по адресу NUM1 - 4+(n-1)*4. На каждой следующей итерации к сумме прибавляются числа, находящиеся по адресам на 4 меньше, и на последней итерации при n=1 прибавится число, расположенное по адресу NUM1. Регистр ЕСХ исполь­зуется в качестве индекса дополнительно, главная его «специализация» использование его в качестве счетчика. Сначала вторая команда программы загружает в него значе­ние, хранящееся в памяти по адресу N. Далее на каждой итерации цикла значение в этом регистре уменьшается на 1. Команда условного перехода JG выполняет пе­реход к началу цикла по адресу STARTADD, если [ЕСХ] > 0. Когда содержимое регистра ЕСХ становится равным нулю, это означает, что все числа списка сложе­ны. В таком случае переход не осуществляется и следующая команда пересылки сохраняет содержимое регистра ЕАХ в памяти по адресу SUM.

Так как счетчик (регистр ECX) меняет свое значение от n до 1, то если бы мы не уменьшили значение базового регистра на 4, то мы сложили бы n чисел, заканчивая NUM2, а начиная NUMn+4 т.е. с адресами на 4 больше, чем NUM1 и NUMn.

Используемая в программе команда LOOP STARTADD объединяет функции двух команд:

DEC ЕСХ

JG STARTADD

т.е. эта команда сначала уменьшает содержимое регистра ЕСХ, а затем выполняет переход по ад­ресу STARTADD, если значение ЕСХ не равно нулю.



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