ТОП 10:

Представление данных в компьютерах



Системное программирование

На языке ассемблера

Методическое пособие

по теме

«Архитектура реального режима процессора.

Директивы языка»

 

Одесса 2010

 

 

СОДЕРЖАНИЕ

 

ВВЕДЕНИЕ.............................................................................................................................. 5

1. предварительные сведения............................................................................. 7

1.1. Подготовка программ на языке ассемблера.................................................... 7

1.2. Представление данных в компьютерах............................................................. 8

1.2.1. Двоичная система счисления......................................................................... 8

1.2.2. Биты, байты и слова....................................................................................... 9

1.2.3. Шестнадцатеричная система счисления....................................................... 9

1.2.4. Числа со знаком............................................................................................. 10

1.2.5. Логические операции................................................................................... 11

1.2.6. Коды символов.............................................................................................. 11

2. процессоры INTEL в реальном режиме.................................................. 12

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

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

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

2.1.3. Стек................................................................................................................ 14

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

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

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

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

2.2.3. Прямая адресация.......................................................................................... 16

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

2.2.5. Адресация по базе со смещением................................................................ 17

2.2.6. Косвенная адресация с масштабированием............................................... 18

2.2.7. Адресация по базе с индексированием...................................................... 18

2.2.8. Адресация по базе с индексированием и масштабированием................. 18

2.3. Основные непривилегированные команды.................................................... 19

2.3.1. Пересылка данных........................................................................................ 19

2.3.2. Двоичная арифметика.................................................................................. 25

2.3.3. Десятичная арифметика............................................................................... 28

2.3.4. Логические операции................................................................................... 31

2.3.5. Сдвиговые операции.................................................................................... 32

2.3.6. Операции над битами и байтами................................................................ 35

2.3.7. Команды передачи управления................................................................... 37

2.3.8. Строковые операции.................................................................................... 43

2.3.9. Управление флагами.................................................................................... 48

2.3.10. Загрузка сегментных регистров................................................................ 49

2.3.11. Другие команды.......................................................................................... 50

3. ДИРЕКТИВЫ И ОПЕРАТОРЫ АССЕМБЛЕРА...................................................... 51

3.1. Структура программы........................................................................................... 52

3.2. Директивы распределения памяти.................................................................... 53

3.2.1. Псевдокоманды определения переменных................................................ 53

3.2.2. Структуры...................................................................................................... 54

3.3. Организация программы...................................................................................... 55

3.3.1. Сегменты....................................................................................................... 55

3.3.2. Модели памяти и упрощенные директивы определения сегментов....... 57

3.3.4. Процедуры..................................................................................................... 59

3.3.5. Конец программы......................................................................................... 59

3.3.6. Директивы задания набора допустимых команд...................................... 59

3.3.7. Директивы управления программным счетчиком.................................... 60

3.3.8. Глобальные объявления............................................................................... 61

3.3.9. Условное ассемблирование......................................................................... 61

3.4. Выражения.............................................................................................................. 62

3.5. Макроопределения................................................................................................ 64

3.5.1. Блоки повторений......................................................................................... 65

3.5.2. Макрооператоры........................................................................................... 66

3.5.3. Другие директивы, используемые в макроопределениях........................ 66

3.6. Другие директивы.................................................................................................. 67

3.6.1. Управление файлами.................................................................................... 67

3.6.2. Управление листингом................................................................................ 67

3.6.3. Комментарии................................................................................................. 68

ЛИТЕРАТУРА...................................................................................................................... 69


 

ВВЕДЕНИЕ

 

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

К системным программам обычно относят программы, разработанные с учетом специфики конкретного оборудования и выполняющие какие-либо сервисные функции. Это, в первую очередь, операционная система (включая базовую систему ввода-вывода), драйверы устройств, резидентные программы, обработчики программных прерываний, служебные сервисные подпрограммы, написанные для их последующего использования прикладными приложениями и пр. В отличие от прикладных высокоуровневых программ, решающих конкретные задачи пользователя, системные программы реализуют низкий уровень работы с вычислительной системой, обеспечивая определенный сервис для работы с устройствами, файловой системой и выполняя разнообразные рутинные операции. Качество и эффективность работы этого низкоуровневого слоя в очень большой степени определяют надежность и производительность вычислительной системы и, в конечном счете, скорость выполнения заданий пользователя. Большая часть системных программ используется очень интенсивно, поэтому к их разработке нужно подходить с особой тщательностью и ответственностью.

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

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

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

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

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

Разработка системных программ на языке ассемблера, независимо от предмета решаемых задач, предполагает знание архитектуры процессора, директив языка и правил оформления исходного кода. Данное методическое пособие призвано осветить именно эти вопросы, составляющие часть курса «Системное программирование». Здесь рассматриваются базовые элементы архитектуры семейства процессоров Intel (86- совместимых), в частности, машинное представление данных и используемые системы счисления, регистры, режимы адресации, группы и форматы команд; структура программы, директивы, операторы и выражения языка MASM.


1. предварительные сведения

 

Подготовка программ на языке ассемблера

Как уже отмечалось, язык ассемблера отражает архитектурные особенности компьютера. Для каждого семейства компьютеров используется свой язык ассемблера и свои программы для обработки исходного текста ассемблерных программ. Здесь рассматривается язык ассемблера для семейства персональных IBM-совместимых компьютеров (IBM PC), получивших сегодня повсеместное распространение. Компьютеры IBM-PC базируются на микропроцессорах семейства x86, выпускаемых фирмой Intel и конкурирующими компаниями. Однако и здесь существует несколько разных версий ассемблеров, разработанных различными производителями программного обеспечения. Среди выпущенных пакетов ассемблеров наиболее популярными являются TASM фирмы Borland и MASM фирмы Microsoft.

Исходный текст программы на языке ассемблера представляет собой "чистый" текстовый файл (содержащий неформатированный текст) с расширением ASM. Для обработки исходного текста используется как минимум две программы: непосредственно ассемблер, переводящий мнемонические команды процессора в машинный код (объектный файл определенного формата с расширением OBJ), и компоновщик (редактор связей), преобразующий OBJ-файл в исполнимый модуль (EXE или COM), а также объединяющий несколько объектных модулей, если они указаны. Помимо этого для разных целей могут потребоваться дополнительные вспомогательные программы — компиляторы ресурсов, расширители DOS и т. п.

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

Запуском программы-ассемблера с определенными ключевыми параметрами можно инициировать создание файла-листинга. Листинг представляет собой текстовый файл с расширением LST, содержащий исходный текст программы с указанием номеров строк, относительных адресов команд и данных, машинное представление команд и данных (в 16-ричной системе счисления), список свойств переменных, меток и сегментов, сообщения об ошибках и прочую служебную информацию. Файл листинга разбивается на страницы, снабжается колонтитулами и управляющими кодами принтера (для управления разбиением можно использовать директивы PAGE и TITLE) и, таким образом, подготовлен для печати в текстовом режиме принтера.

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

На этапе компоновки происходит связывание отдельных частей программы в единый исполнимый модуль. Формат этого модуля зависит от используемой операционной системы. В MS-DOS используется два различных формата исполнимых модулей — EXE и COM. Во время обработки объектного кода программа-компоновщик проверяет правильность размещения данных в сегментах, наличие стека и другие особенности объектного модуля, часть из которых зависит от формата создаваемого исполнимого файла (EXE или COM). При наличии некритичных несоответствий, например, при отсутствии стека, компоновка файлов все же может выполниться, тогда на экран будут выданы соответствующие предупреждения.

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

 

Двоичная система счисления

Практически все существующие сейчас компьютерные системы, включая IBM PC, используют для всех вычислений двоичную систему счисления. В их электрических цепях напряжение может принимать два значения, и эти значения условно названы нулем и единицей. Двоичная система счисления как раз и использует только эти две цифры, а вместо степеней десяти, как в обычной десятичной системе, здесь используют степени двойки. Чтобы перевести двоичное число в десятичное, надо сложить двойки в степенях, соответствующих позициям двоичного числа, где стоят единицы. Например:

 

10010110b=1×27+0*26+0*25+1*24+0*23+1*22+1*21+0*20=128+16+4+2=150

Чтобы перевести десятичное число в двоичное, можно, например, просто делить его на 2, записывая 0 каждый раз, когда число делится на два, и 1, когда не делится (табл. 2).

 

Таблица 2. Перевод числа из десятичной системы в двоичную
    Остаток Разряд  
  150/2 = 75  
  75/2 =37  
  37/2 =18  
  18/2 = 9  
  9/2 = 4  
  4/2 = 2  
  2/2 = 1  
  1/2 = 0  
  Результат: 10010110b  
         

 

Чтобы отличать двоичные числа от десятичных, в ассемблерных программах в конце каждого двоичного числа ставят букву «b».

Биты, байты и слова

Минимальная единица информации называется битом. Бит может принимать только два значения — обычно 0 и 1.

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

 

                 
 
                                 

 

Рис. 1. Байт

 

Так как всего в байте восемь бит, байт может принимать до 28 = 256 разных значений. Байт используют для представления целых чисел от 0 до 255 (тип unsigned char в С), целых чисел со знаком от –128 до +127 (тип signed char в С), набора символов ASCII (тип char в С) или переменных, принимающих менее 256 значений, например для представления десятичных чисел от 0 до 99. Следующий по размеру базовый тип данных — слово. Размер одного слова в процессорах Intel — два байта.

Биты с 0 по 7 составляют младший байт слова, а биты с 8 по 15 — старший. В слове содержится 16 бит, а значит, оно может принимать до 216 = 65536 разных значений. Слова используют для представления целых чисел без знака со значениями 0 – 65535 (тип unsigned short в С), целых чисел со знаком со значениями от –32768 до +32767 (тип short int в С), адресов сегментов и смещений при 16-битной адресации. Два слова подряд образуют двойное слово, состоящее из 32 бит, а два двойных слова составляют одно учетверенное слово (64 бита). Байты, слова и двойные слова — основные типы данных, используемые в языке ассемблера.

 

   

15 8 7 0

 

Рис. 2. Слово

 

Еще одно важное замечание: в компьютерах, использующих процессоры Intel, все данные хранятся так, что младший байт находится по младшему адресу, так что слова записываются в обратной последовательности. Если из программы всегда обращаться к слову как к слову, а к двойному слову как к двойному слову, это не оказывает никакого влияния. Но если нужно считать первый (старший) байт из слова в памяти, необходимо прибавить к адресу слова 1. Двойные и учетверенные слова записываются так же — от младшего байта к старшему.

Числа со знаком

Легко использовать байты, слова или двойные слова для представления целых положительных чисел — от 0 до 255, 65535 или 4 294 967 295 соответственно. Чтобы использовать те же самые байты или слова для представления отрицательных чисел, существует специальная опера­ция, известная как дополнение до двух (дополнительный код). Для изменения знака числа выполняют инверсию, то есть заменяют в двоичном представлении числа все единицы нулями и нули единицами, а затем прибавляют 1.

Например, пусть используются переменные типа слова:

150 = 0096h = 0000 0000 1001 0110b

инверсия дает: 1111 1111 0110 1001b

+1 = 1111 1111 0110 1010b = 0FF6Ah

Проверим, что полученное число на самом деле –150: сумма с +150 должна быть равна нулю:

+150 + (-150) = 0096h + FF6Ah = 10000h

Единица в 16-м двоичном разряде не помещается в слово и отбрасывается, значит, действительно получен 0. В этом формате старший (7-й, 15-й, 31-й для байта, слова, двойного слова соответственно) бит всегда соответствует знаку числа 0 — для положительных и 1 — для отрицательных. Таким образом, схема с использованием дополнения до двух выделяет для положительных и отрицательных чисел равные диапазоны: –128…+127 — для бай­та, –32768…+32767 — для слов, –2147483648 …+2147483647 — для двойных слов и т. д.

Логические операции

Один из широко распространенных вариантов значений, которые может принимать один бит, — это значения «правда» и «ложь», используемые в логике, откуда происходят так называемые «логические операции» над битами. В ассемблере используются четыре основные логические операции — И (AND), ИЛИ (OR), исключающее ИЛИ (XOR) и отрицание (NOT), действие которых приводится в таблице 4.

  Таблица 4. Логические операции
И Или Исключающее ИЛИ Отрицание  
1 AND 0 = 0 1 OR 0 = 1 1 XOR 0 = 1 NOT 1 = 0  
0 AND 1 = 0 0 OR 1 =1 0 XOR 1 = 1 NOT 0 = 1  
0 AND 0 = 0 0 OR 0 = 0 0 XOR 0 = 0    
1 AND 1 = 1 1 OR 1 = 1 1 XOR 1 = 0    
           

 

Все эти операции побитовые, поэтому, чтобы выполнить логическую операцию над числом, надо перевести его в двоичный формат и выпол­нить операцию над каждым битом, например:

 

96h AND 0Fh = 10010110b AND 00001111b = 00000110b = 06h

Коды символов

Для представления всех букв, цифр и знаков, появляющихся на экране компьютера, обычно используется всего один байт. Символы, соответствующие значениям от 0 до 127, то есть первой половине всех возможных значений байта, были стандартизованы и названы символами ASCII (хотя часто кодами ASCII называют всю таблицу из 256 символов). Сюда входят некоторые управляющие коды (символ с кодом 0Dh — конец строки), знаки препинания, цифры (символы с кодами 30h – 39h), большие (41h – 5Ah) и маленькие (61h – 7Аh) латинские буквы. Вторая половина символьных кодов используется для алфавитов других языков и псевдографики, и набор и порядок символов в ней различаются в разных странах и даже в пределах одной страны. Например, для букв одного только русского языка существует пять разных вариантов размещения во второй половине таблицы символов ASCII. В MS-DOS наибольшее распространение получила так называемая альтернативная кодировка ГОСТа или кодировка cp866 (табл. 5). Существует также стандарт, использующий слова для хранения кодов символов, известный как UNICODE или UCS-2, и даже двойные слова (UCS-4).

Таблица 5. Кодировка ASCII ср866 (альтернативная ГОСТ)

 
 

 

 

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

 

Начиная с 80386, процессоры Intel предоставляют 16 основных регист­ров для пользовательских программ, а также 11 регистров для работы с числами с плавающей запятой (FPU/NPX) и мультимедийными при­ложениями (ММХ). Все команды так или иначе изменяют значения ре­гистров, и всегда быстрее и удобнее обращаться к регистру, чем к памяти.

Помимо основных регистров из реального (но не из виртуального) ре­жима доступны также регистры управления памятью (GDTR, IDTR, TR, LDTR), регистры управления (CR0, CR1 - CR4), отладочные регистры (DR0 - DR7) и машинно-специфичные регистры, но они не применя­ются для повседневных задач и здесь не рассматриваются.

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

32-битные регистры ЕАХ (аккумулятор), ЕВХ (база), ЕСХ (счетчик), EDX (регистр данных) могут использоваться без ограничений для любых це­лей — временного хранения данных, аргументов или результатов различ­ных операций. Названия этих регистров происходят от того, что некото­рые команды применяют их специальным образом: так, аккумулятор часто используется для хранения результата действий, выполняемых над двумя операндами, регистр данных в этих случаях получает старшую часть результата, если он не умещается в аккумулятор, регистр-счетчик ис­пользуется как счетчик в циклах и строковых операциях, а регистр-база используется при так называемой адресации по базе. Младшие 16 бит каждого из этих регистров могут использоваться как самостоятельные ре­гистры и имеют имена (соответственно АХ, ВХ, СХ, DX). В процессорах 8086 - 80286 все регистры имели размер 16 бит и называ­лись именно так, а 32-битные ЕАХ - EDX появились с введением 32-битной архитектуры в 80386. Кроме этого, отдельные байты в 16-бит­ных регистрах АХ - DX тоже имеют свои имена и могут использоваться как 8-битные регистры. Старшие байты этих регистров называются АН, ВН, СН, DH, а младшие — AL, DL, CL, DL (рис. 3).

Другие четыре регистра общего назначения — ESI (индекс источни­ка), EDI (индекс приемника), ЕВР (указатель базы), ESP (указатель сте­ка) — имеют более конкретное назначение и могут применяться для хра­нения всевозможных временных переменных, только когда они не используются по назначению. Регистры ESI и EDI используются в стро­ковых операциях, ЕВР и ESP используются при работе со стеком. Так же как и с регистрами ЕАХ - EDX, младшие половины этих четырех регистров называются SI, DI, ВР и SP соответственно, и в процессорах до 80386 только они и присутствовали.

 

  AX
ЕАХ   AH AL
    BX
ЕBХ   BH BL
    CX
ЕCХ   CH CL
    DX
ЕDХ   DH DL

31 16 15 8 7 0

 

ESI   SI

 

EDI   DI

 

EBP   BP

 

ESP   SP

 

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

Стек

Стек — это специальным образом организованный участок памяти, ис­пользуемый для временного хранения переменных, для передачи пара­метров вызываемым подпрограммам и для сохранения адреса возврата при вызове процедур и прерываний. Процессор имеет особые команды для записи в стек (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-битного слова.

Пересылка данных

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

 

Команда: MOV приемник,источник

• Назначение: Пересылка данных

• Процессор: 8086

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

mov dx, bx

эквивалентна выражению

ax:=bx;

языка Паскаль или

ах=bх;

языка С, за исключением того, что команда ассемблера позволяет ра­ботать не только с переменными в памяти, но и со всеми регистрами процессора.

В качестве источника для MOV могут использоваться: число (непос­редственный операнд), регистр общего назначения, сегментный регистр или переменная (то есть операнд, находящийся в памяти). В качестве приемника — регистр общего назначения, сегментный регистр (кроме CS) или переменная. Оба операнда должны быть одного и того же раз­мера — байт, слово или двойное слово.

Нельзя выполнять пересылку данных с помощью MOV из одной пере­менной в другую, из одного сегментного регистра в другой и нельзя поме­щать в сегментный регистр непосредственный операнд — эти операции выполняют двумя командами MOV (из сегментного регистра в обычный и уже из него в другой сегментный) или парой команд PUSH/POP.

Загрузка регистра SS командой MOV автоматически запрещает прерыва­ния до окончания следующей за этим команды MOV, так что можно загру­зить SS и ESP двумя последовательными командами MOV, не опасаясь, что в этот момент произойдет прерывание, обработчик которого получит не­правильный стек. В любом случае для загрузки значения в регистр SS предпочтительнее команда LSS.

Команда: CMOVcc приемник,источник

• Назначение: Условная пересылка данных

• Процессор: Р6







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

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