Выбери формат для чтения
Загружаем конспект в формате rtf
Это займет всего пару минут! А пока ты можешь прочитать работу в формате Word 👇
Министерство общего и профессионального образования РФ
Иркутский государственный технический университет
Кафедра вычислительной техники
МАШИННО-ОРИЕНТИРОВАННЫЕ ЯЗЫКИ
(микропроцессор 8088)
конспект лекций
Для студентов специальности ЭВМ зс-2010
Иркутск 2010 г
Оглавление
Введение Предмет и задачи курса . Архитектура МП 8086 3
Архитектура МП 8086 3
ЛЕКЦИЯ №1 Язык Ассемблера МП 8080. Основные операторы. 8
Структура оператора 9
Директивы определения данных 10
ЛЕКЦИЯ №2 Система команд МП 8086 11
Способы адресации операндов 12
Команды передачи данных 12
ЛЕКЦИЯ №3 Команды двоичной арифметики 15
Арифметические команды языка ассемблера. 15
Команды преобразования данных 18
ЛЕКЦИЯ №4 Программирование разветвлений 18
Команда сравнения двоичных целых чисел. 18
Команды передачи управления 18
Команды условного перехода 19
Управление циклом 21
Лекция №5 Работа с массивами 22
Основные понятия. Массив. Элемент массива. 22
Примеры составления программ работы с массивами 23
Лекция № 6 Прерывания 26
Векторы прерываний. 26
Контроллер 8259 фирмы Intel 26
Прерывание DOS int 21h: 28
Введение Предмет и задачи курса . Архитектура МП 8086
Современные компьютеры можно сравнить с существами, взаимодействующими с внешним миром на уровне большого, но ограниченного набора безусловных рефлексов. Этот набор рефлексов образует систему машинных команд. На каком бы высоком уровне вы не общались с компьютером, в конечном итоге все сводится к последовательности машинных команд. Каждая машинная команда является своего рода раздражителем для возбуждения того или иного безусловного рефлекса. Реакция на этот раздражитель всегда однозначная и “зашита” в блоке микрокоманд в виде микропрограммы. Эта микропрограмма и выполняет действия по реализации машинной команды, но уже на уровне сигналов, подаваемых на те или иные логические схемы компьютера, тем самым, управляя различными подсистемами компьютера. В этом состоит так называемый принцип микропрограммного управления.
Машинно-ориентированное программирование появилось одновременно с созданием электронных вычислительных машин. Сначала это были программы в машинных командах. Таким образом, внешне являясь полиглотом, компьютер понимает только один язык — язык машинных команд. Конечно, для общения и работы с компьютером, необязательно знать этот язык, но практически любой профессиональный программист рано или поздно сталкивается с необходимостью его изучения.
Еще в 50-е годы программисты стали использовать для программирования символический аналог машинного языка, который назвали языком ассемблера. Язык ассемблера является первой ступенью в автоматизации процесса программирования. Этот язык точно отражает все особенности машинного языка. Именно поэтому, в отличие от языков высокого уровня, язык ассемблера для каждого типа компьютера свой.
Так как для компьютера язык ассемблера “родной”, то очевидно, и самая эффективная программа может быть написана только на нем (при условии, что ее пишет квалифицированный программист). Здесь есть одно маленькое “но”: это очень трудоемкий, требующий большого внимания и практического опыта процесс. Поэтому реально на ассемблере пишут в основном программы, которые должны обеспечить эффективную работу с аппаратной частью. Программы на языке Ассемблер (ЯА), разработанные квалифицированными программистами, по размеру компактны и выполняются быстрее программ, составленных на других языках. В то время как эффективность выходного кода компиляторов языков высокого уровня определяется качеством генераторов машинного кода. Иногда на ассемблере пишутся критичные по времени выполнения или расходованию памяти участки программы. Впоследствии они оформляются в виде подпрограмм и совмещаются с кодом на языке высокого уровня, которые имеют возможность включения вставок языка ассемблера (корректность вставки определяется знанием внутренних правил использования ресурсов процессора).
В данном курсе будет рассматриваться язык Ассемблера персональных ЭВМ IBM PC Intel процессора 8086 , это базовый язык всех моделей, начиная с 8088 и к старшим моделям процессоров данного семейства (286 ® 386 ® 486® Pentium), так как программы совместимы от младших моделей к старшим.
Архитектура МП 8086
Принципиально все современные компьютеры базируются на архитектуре фон Неймана - совместное хранение данных и программы. Она включает в себя три основные составляющие: центральный процессор (ЦП,CPU- Cetnral Processing Unit), оперативное запоминающее устройство (ОЗУ) и внешние запоминающие устройства (ВЗУ). У семейства IBM PC ЦП и ОЗУ размещаются на материнской плате. На этой плате есть соответствующие разъемы, к которым может быть подсоединено огромное количество разнообразных ВЗУ: клавиатура, дисплей, дисководы, принтер, модем и прочие.
Команды и данные находятся либо в ОЗУ, либо в ВЗУ. В случае, когда программа выполняется, она должна находиться в ОЗУ. Обмен информацией между процессором и ОЗУ происходит через адресную шину и/ или через шину данных в зависимости от вида обрабатываемой информации. От пропускной способности этих шин зависит скорость вычислений и размер адресуемой памяти.
Для разработки эффективных программ языки программирования должны учитываться особенности аппаратуры вычислительного комплекса, возможность оперировать такими объектами, как биты, байты, слова, строки, сегменты, смещения, содержимое регистров, символы, целочисленные данные разной длины со знаком и без знака. Ниже приведена схема взаимодействия основных блоков процессора 8086.
Рис.1 Архитектура МП
Использованы обозначения:
ЦП – центральный процессор;
АЛУ – арифметико-логическое устройство;
УУ – устройство управления;
ОЗУ – оперативно запоминающее устройство:
Ув/в – устройство ввода-вывода.
АЛУ предназначено для выполнения арифметических и логических операций, а также операций сравнения. В АЛУ имеются специальные ячейки, называемые регистрами, которые служат для приема и хранения данных, участвующих в выполняемой операции. Регистры микропроцессора 8086 бывают 8- и 16-разрядные, то есть максимальная разрядность -16 битов, следовательно, разрядность шины данных (ШД) тоже 16 бит.
Оперативная память физически выполнена в виде микросхем и предназначена для временного хранения программ и данных.ОЗУ можно представить в виде ячеек( байтов), каждая из которых имеет свой номер. Максимальный объем оперативной памяти МП 8086- 1 Мб.
Линейный или физический адрес любого байта памяти - это его порядковый номер от начала памяти, то есть, целое число в интервале от 0 до 220-1 или в 16-ричной системе 00000-FFFFF. Откуда следует, что разрядность адресной шины должна быть 20 битов или 20 двоичных разрядов. Управляющая шина служит для передачи сигналов из УУ в периферийные устройства.
В архитектуру процессора i8086/i8088 была заложена идея сегментной организации памяти, которая сохранилась с появлением новых семейств процессоров. Оперативная память процессора 8086 разбита на сегменты. Размер сегмента не более 64 килобайт или 65536 байт. Для удобства адресации оперативной памяти используется относительная адресация, из двух частей: адрес начала сегмента, где находится байт, и смещение (расстояние) байта от начала сегмента. Минимальное смещение равно 0, это первый байт сегмента. Максимальное смещение равно 65535=216-1 для последнего байта сегмента или FFFFh
В центральном процессоре доступны программисту следующие регистры:
1. РОН - регистры общего назначения
2. Сегментные регистры;
3. Счетчик команд IP (instruction pointer)
4. Индексные регистры;
5. Регистр флагов.
Регистры общего назначения
Четыре регистра общего назначения (или общих регистров) процессора 8086 (каждый размером 16 бит) используются в операциях большинства инструкций в качестве источника или приемника при перемещении данных и вычислениях, указателей на ячейки памяти и счетчиков. Каждый регистр общего назначения может использоваться для хранения 16-битового значения в арифметических и логических операциях, может выполняться обмен между регистром и памятью (запись из регистра в память и наоборот). Допускается интерпретация регистра в виде двух 8-битовых регистров High (старший и Low (младший ).
High Биты Low
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
Регистр AX
AH
AL
Регистр BX
BH
BL
Регистр CX
CH
CL
Регистр DX
DH
DL
Кроме такого общего свойства регистров, как использование их для хранения значений или в качестве источника и приемника при работе с данными, каждый регистр общего назначения имеет свою особенность.
AX - cумматор (accumulator). Является основным регистром при выполнении всех арифметических и логических команд. Команды операций с сумматором работают эффективней подобных команд с другими регистрами. Они короче по длине и исполняются быстрее. Регистр AX используется во всех командах ввода и вывода.Команды умножения и деления используют обязательно только регистр AX в случае 16-разрядных операндов; или AL для 8-разрядных.
ВХ – регистр базы (Base Register). Регистр ВХ может использоваться как арифметический регистр, а так же для указания адреса операнда, который хранится в ОЗУ (адрес операнда указывается [BX] , т.е. имеет место косвенная адресация операнда); Регистр ВХ хранит смещение операнда. Он используется для передачи адресов параметров в процедуры.
СХ – регистр- счётчик (Count Register). Регистр СХ используется: как любой арифметический регистр; как счётчик циклов; как счётчик сдвигов.– Сl .
DX–регистр данных (Data Register): Специфическое применение в операциях умножения и деления 16-разрядных операндов. Перед выполнением операции умножения в регистре АХ должно быть 16-разрядное множимое. При выполнении умножения на 16-разрядный множитель получается 32-разрядное произведение. Старшие 16 разрядов произведения заносятся в регистр DX, младшие разряды - в регистр АХ. Перед выполнением операции деления делимое должно быть записано в виде 32- разрядного кода в пару регистров DX и AX. В результате деления нацело на 16-разрядный делитель 16- разрядный остаток от деления помещается в регистр DX, . частное попадает в регистр AX.
Регистр DX используется в операциях вывода для передачи адреса данного.
Регистр DX - это единственный регистр, которые может использоваться в качестве указателя адреса ввода-вывода в инструкциях IN и OUT
Сегментные регистры
В процессоре имеется четыре сегментных регистра CS, DS, ES, SS. Они служат для указания начала соответствующего сегмента.
1. Регистр CS (Code Segment) содержит адрес начала текущего сегмента кода, где располагаются команды или коды программы.
2. SS (Stack Segment) - содержит адрес начала сегмента стека . Регистр SS инициализируется операционной системой автоматически
3. DS (Data Segment) –содержит адрес текущего сегмента данных. Вообще в программе может быть несколько сегментов данных.
4. ES ( Extra Segment) – регистр дополнительного сегмента данных.
Счетчик команд IP (instruction pointer
Указатель инструкций (регистр IP) всегда содержит смещение в памяти, по которому хранится следующая выполняемая инструкция. Когда выполняется одна инструкция, указатель инструкций перемещается таким образом, чтобы указывать на адрес памяти, где хранится следующая инструкция.
Значение счетчика инструкций нельзя прочитать или записать непосредственно. Загрузить в указатель инструкций новое значение может только специальная инструкция перехода.
Указатель инструкций IP сам по себе не определяет адрес, по которому находится следующая выполняемая инструкция. Для извлечения инструкции используется регистр CS, где хранится базовый адрес, при этом указатель инструкций задает смещение относительно этого базового адреса.
. Примеры адресации
Адрес команды в сегменте кода имеет вид:[CS]:[ смещение]
Линейный или физический адрес вычисляется по формуле
(CS) * 16 + смещение
16-разрядный регистр, содержит смещение текущей команды относительно регистра CS
Адрес операнда из сегмента данных имеет вид: [DS]:[смещение]
Адрес операнда из дополнительного сегмента данных: [ES]:[смещение]
Линейные или физические адреса вычисляются по формулам:
(DS) * 16 + смещение
(ES) * 16 + смещение
Адресация сегмента стека
В программе всегда только один сегмент стека
Стек - это область памяти, в которой можно сохранять значения и из которой они могут затем извлекаться по дисциплине "последний пришел- первый ушел" (LIFO). То есть последнее сохраненное в стеке значение будет первым значением, которое вы получите при чтении из стека. Классической аналогией стека является стопка тарелок. Поскольку тарелки можно класть только сверху стопки (и брать также), то первая положенная тарелка будет последней, которую вы сможете взять.
Доступ к элементам стека происходит с помощью двух регистров SP и BP
Регистр SP (stack pointer) - 16 разрядный регистр, называется также указателем текущей вершины стека. Регистр SP в начале работы программы имеет значение объема стека( максимальное значение). При каждом занесении данных в стек регистр SP автоматически уменьшается на 2 (длина слова). Текущая вершина стека имеет адрес [SS]:[ SP]; действительный адрес вычисляется по формуле [ss]*16+[sp]. Как и в случае стопки тарелок, вершина стека - это то место, в котором в стеке сохраняется последнее помещенное туда значение. Действие, состоящее в занесении значений в стек, называют также "заталкиванием" (pushing) в стек. В самом деле, инструкция PUSH используется для занесения значений в стек. Аналогично, действие, состоящее в извлечении (выборке) значений из стека, называют также "выталкиванием" (popping) из стека (для этого используется инструкция POP).
При выталкивании слова из стека регистр SP увеличивается на 2 .
Регистр ВР - basa pointer служит для косвенной адресации и доступа к содержимому стека без разрушения стека (выталкивания данных из стека). Регистр SP копируется в регистр BP, адрес [SS] [BP+2] обеспечит доступ к содержимому стека, расположенному на 2 байта дальше вершины стека.
Индексные регистры
Регистр SI (Source Index). Этот 16-разрядный регистр является индексом источника, обычно он используется в паре [DS]:[SI] для выполнения операций над цепочками символов или строк.
Регистр DI (Destination Index ). Этот 16-разрядный регистр является индексом назначения или приемника, обычно он используется в паре [ES]:[DI] также для строковых операций..
Оба регистра можно применять в арифметических операциях. Индексные регистры используются при работе с таблицами данных, где доступ к отдельному элементу обеспечен с помощью расширенной индексной адресации операндов.
Регистры SI и DI не могут использоваться одновременно при формировании одного адреса.
Регистр флагов
Регистр флагов сигнализирует процессору о его состоянии, о том, как выполнилась арифметическая или логическая команда.
Девять из 16 битов регистра флагов являются активными. Флаг – это бит, принимающий значение 1, если он установлен, и 0, если он сброшен. За битами регистра флагов закреплены соответствующие имена.
Регистр флагов Flags
Биты
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
OF
DF
IF
TF
SF
ZF
AF
PF
CF
Таблица Назначение битов регистра флагов.
Флаг
Назначение
Флаги условий
CF (Carry Flag)
Флаг переноса. Содержит признак переноса единицы в старший разряд или заема единицы из этого разряда после арифметических операций, а также последний бит при операции сдвига.
PF(Parity Flag)
Флаг чётности. Он устанавливается в 1, если в младшем байте результата очередной команды содержится чётное число единичных битов.
AF( Auxiliary Flag)
Флаг вспомогательного переноса. Фиксирует особенности операций над двоично-десятичными числами.
ZF(Zero Flag)
Флаг нуля. Он устанавливается в 1, если результат последней команды равен 0.
SF(Signim Flag)
Флаг знака. Отражает старший бит результата выполнения команды.
OF(Overflow Flag)
Флаг переполнения
Флаги состояний
IF( Interrupt flag)
Флаг прерывания. Если IF=1, прерывания разрешаются, а иначе блокируются.
TF(Trap/Trace flag)
Флаг трассировки. Обеспечивает возможность пошагового выполнения программы. Например, программа отладчик устанавливает данный флаг так, что возможно пошаговое выполнение каждой команды для проверки изменения содержимого регистров и памяти.
DF(Direction Flag)
Флаг направления. Устанавливает направление обработки цепочек символов в памяти машины.
.
Регистр флагов не считывается и не модифицируется непосредственно.
ЛЕКЦИЯ №1 Язык Ассемблера МП 8080. Основные операторы.
Алфавит языка ассемблера составляют следующие символы:
• Все латинские буквы от а до z , A..Z ( большие и малые не различаются0
• Цифры: 0 –9
• Спец. знаки : @ , $, _ , &.
• Разделители: :, . , [ ] , ( ) , {} , ; , ^
• Знаки операций: + , - , / , * , % , = ,| ,“ ”, # , \ .
Лексемы – минимальная неделимая единица языка, цепочка символов. Имена, используемые со знаками _,?, @, $ .Ключевые слова. Константы
Имена - это названия сегментов и переменных, метки команд.
Ключевые слова – это директивы языка, названия регистров, мнемокоды машинных команд, операции в выражениях:
Shr, shl , type , dup и др.
Length , size , offset , и др.
Константы – это числа и строки.
Числовые константы могут быть заданы в 2-, 10-, 16-системах исчисления. Тип константы указывается с помощью символа - концом числа за последней цифрой.
Пример: Константа 10
двоичная система исчисления - 1010В
десятичная система исчисления - 10{T}
шестнадцатеричная система исчисления - 0AH
В 16-ной системе исчисления константу начинают с нуля(0). Количество цифр в константе ограничивается форматом данных, где используется эта константа.
Пример:
MOV AH , 11111111B
MOV BX , 0C5H ; C516=110001012
Символьные константы это цепочка любых символов, заключенная в кавычки: `ТЕКСТ `;”ТЕКСТ”. Количество символов в цепочке также зависит от формата данных, где она используется :
MOV AH , `A` ; константа длиной в байт
MOV AX , `AA` ; константа длиной в слово
Структура оператора
Каждый оператор занимает одну строку.
Операторы могут быть трех видов: комментарий, директива и машинная команда.
комментарий - ; не транслируется.
Директива не порождает машинную команду, она является указанием для транслятора о сегментации программы, о структуре листинга (объект кода), о резервировании и инициализации полей данных. Квадратные скобки в формате директивы означают, что данная часть может отсутствовать в некоторых директивах.
[имя ] директива [ параметры ]
DSEG SEGMENT PARA ; директива начала сегмента
Оператор машинная команда
[метка:] мнемокод [операнды ]
Поле имя и поле операнды могут отсутствовать в некоторых командах.
Оператор машинной команды порождает одну машинную команду. Длина команды от 1 + до 6 байт (зависит от вида операции, (кода команды) и от способа адресации оперативной памяти).
Директивы языка Ассемблера
Директивы сегментации программы.
Сегменты программы должны описываться с помощью директивы SEGMENT, указывающей имя сегмента, используемое для ссылок в программе, границу выравнивания (байт, слово, параграф, страница), тип комбинации его с другими сегментами, класс сегмента, определяющий порядок следования сегмента в памяти Директива SEGMENT открывает сегмент. Любой код или данные, следующие за ней, будут помещаться в указанный сегмент до тех пор, пока не встретится директива ENDS, закрывающая сегмент.
имя SEGMENT [ атрибуты ]
Имя сегмента — обычно используется идентификатор, из которого можно сделать вывод о характере данных, содержащихся в сегменте.
Атрибуты могут состоять из одного или нескольких следующих значений: Комбинации сегмента, класса сегмента, выравнивания сегмента, размера сегмента, доступа к сегменту.
Во время трансляции Turbo Assembler рассматривает атрибуты, указанные в директиве SEGMENT, слева направо.
Атрибут комбинации сегмента предназначен для указания компоновщику, каким образом объединять сегменты, находящиеся в разных модулях и имеющие одинаковые имена.
Параметры директивы SEGMENT.
1) Параметры выравнивания начального адреса сегмента
PARA – сегмент на границе параграфа. ХХХХ0 => адрес кратен 16.
2) Информация, необходимая для программы- компоновщика:TLINK
Атрибут класса сегмента представляет строку, заключенную в кавычки, которая помогает определить компоновщику нужный порядок размещения сегментов, когда он помещает их в программу из разных модулей. Компоновщик группирует вместе все сегменты с одинаковым классом. Кодовый сегмент программы использует класс ‘CODE’. STACK должен быть в любой компонуемой программе (хотя бы один сегмент, “стек”). В многомодульной программе сегмент стека общий (до 64 Кб).
Параметры директивы SEGMENT имеют тип ключевых параметров (могут идти в произвольном порядке через пробел или могут комбинироваться)
Директива SEGMENT начинает описание сегмента, завершает сегмент директива ENDS
Директива ASSUME
ASSUME <сегментный регистр> двоеточие < имя сегмента>
Эта директива служит для указания транслятору информации о связи между сегментным регистром и адресом в оперативной памяти.
ASSUME DS:A_DATA , CS:A _COD
Транслятор на основании этой директивы строит адреса операндов в памяти в виде смещения относительно регистра DS, полагая, что регистр DS содержит адрес A_DATA.
В одной директиве ASSUME можно указать привязку четырех сегментных регистров через запятую .
Занесение соответствующих адресов в сегментные регистры CS и SS выполняет загрузчик, а DS и ES необходимо загружать программно.
MOV AX, A_DATA
МOV DS , AX
Директива END [метка] - для обозначения конца файла исходного модуля; [метка] служит для указания метки первой исполняемой команды главной программы.
Директивы определения данных
Эти директивы обычно размещаются в сегменте данных. С помощью них можно определить именованные константы, каждая из которых занимает соответствующее число байтов, резервировать поля под данные.
Синтаксис директивы Define
[ Имя] Dх выражение 1[ , выражение 2 ]
Где х модификатор, состоящий из одной буквы(B,W,D).
DB - определить поле длиной в byte
DW – определить поле длиной в слово.
DD – определить поле длиной в два слова.
Для простого резервирования памяти в поле операнда ставят знак вопроса ?
X DB ?
Y DB 100 dup(?) ; выделить 100 байт памяти
Ключевое слово dup обозначает знак повторителя
При определении констант операнд(выражение) может представлять собой константу в двоичной, десятичной, шестнадцатеричной системе исчисления.
Инициализация таблицы данных:
А DB 4, -4, 7, 80, 100 ;
; адреса констант : 4® А+0, -4®А+1, 7® А+2 , 80® A+3, 100 ® А+4
В DW 1000, -400, 7, 8 ; {integer}
; адреса констант 1000 ® B +0 ,-400 ® B+2, 7® B+2, 8 ® B+6
Выражение может быть задано адресом памяти:
A DB 4 , -4
AD DW A ;после трансляции в двухбайтовое поле с именем АD будет записано 16- разрядное расстояние адреса А от начала сегмента данных.
Выражения могут содержать следующие операции:
+, -, * , / (деление нацело). MOD, Shr, Shl.
логические операции: NOT, OR, XOR, AND
Специальные обозначения
$ Значения счётчика адреса - (текущее смещение).
offset имя ; смещение внутри сегмента
Примеры использования
X dw 5 ;
Y DW offset x ;
z DW $ ; текущее смещение.
ЛЕКЦИЯ №2 Система команд МП 8086
Компьютеры изначально были предназначены для выполнения математических операций над целыми числами. В набор команд процессора 8086 не входят операции с плавающей точкой, возведения в степень, cos, sin и т.д Процессор 8086 имеет 92 команды, улучшенные процессоры еще больше типов команд. Команды языка Ассемблер можно разделить на 5 классов по их функциям.
Операторы машинных команд следующий формат:
[метка:] мнемокод операции [операнды]
Код операции (КОП) показывает, что делать;
Поле операнды указывает, над какими данными выполняется действие. В некоторых командах операнды могут отсутствовать.
Например, команда CLD не имеет операнда, предназначена для установки флага DF в состояние 0.
Пример команды с одним операндом : div x - делить на Х.
Команда с двумя операндами: приемник и источник.
К регистру АХ прибавить константу 4 : add AX, 4
По первому адресу пишется приёмник, а по второму -источник.
Способы адресации операндов
В зависимости от спецификации и местоположения операндов в языке Ассемблер различают следующие способы адресации:
РЕЖИМ
ФОРМАТ ЗАПИСИ
Регистр сегмента по умолчанию
ПРИМЕРЫ
Непосредственный операнд
Выражение — Константа
101B, 5, 0AH
‘A’, Y-A+5,2*(X-Y)
(X-D) DIV TYPE X
Прямая адресация
Переменная
Переменная ± Выражение —
Константа
DS
X, X+5, X-4
[X]
Регистровый
Регистр
— —
AH,BX,CL,DI,DX,DS
КОСВЕННАЯ РЕГИСТРОВАЯ
Базовая
[Регистр ]
DS
SS
[BX], [SI], [DI]
[BP]
Базовая со смещением
[Регистр] ± Выражение - Константа
Прямой адрес [базовый Регистр] + —
+ — Выражение - Константа]
DS
DS
SS
[BX -6] , [BX] - 6 , [SI] 4
X[BX]
[BP] + 4 , [BP + 4]
Индексная со смещением
Прямой адрес [индексный регистр]
Прямой адрес + [индексный регистр]
DS
X [DI] , X + [DI]
X [SI] X + 4 [SI]
Базово —индексная
[Базовый регистр] [индексный регистр]
DS
[BX] [SI] , [BX] [DI]
Базово —индексная со смещением
Прямой адрес [BX] индексный регистр]]
Прямой адрес + [BX] +[ индексный регистр]
[Базовый регистр] ± Константа[ индексный регистр]
DS\
DS
SS
X [BX] [SI], D[BX][DI]
X+4[BX][DI]
[BP]+4[SI], [BP+4][SI]
Команды передачи данных
Команды передачи данных выполняют копирование или обмен данными. Они имеют характер подготовительно - завершающей операции, т.е. используются для начальной подготовки адресов и данных, а также для сохранения и вывода полученного результата.
FКоманды передачи данных не меняют регистр флагов!
В этой группе команды
1. Общая пересылка данных MOV приемник, источник
2. Обмен данных хchg приемник, источник
3. Работа со стеком
◦ Извлечение из стека слова POP приемник
◦ Занесение слова в стек PUSH источник
◦ Команды пересылки флагов LAHF, SAHF, POPF,PUSHF
4. Команды пересылки адреса LEA, LDS, LES
Рассмотрим первой общую пересылку данных. Она имеет два операнда.
MOV приемник, источник
Все возможные комбинации операндов команды MOV ниже представлены на схеме:
Из схемы видно, что источником команды пересылки могут быть константы, регистры и поля памяти (байт или слово). Приемником могут быть только регистры и поля памяти.
Адресация операндов команды MOV
• Непосредственная адресация источника.
MOV AX, 5
MOV AX, -5
MOV Ah, ‘H’
При исполнении команды не тратится время на перемещение операнда, так как при трансляции команды непосредственный операнд-константа становится частью команды.
Константу нельзя переслать в сегментные регистры.
• Регистровая адресация, то есть используют АХ, ВХ, СХ, DХ, DI , SI, SP, BP и
8-битовые регистры AL, BH, BL (тип регистра определяет разрядность операции).
MOV BL, AL ; - 8 бит.
MOV BX, CX ; - 16 бит
• прямая адресация имеет место, когда один из операндов находится в памяти – переменная (переменная +(-) выражение const)
MOV AX, A ; A имеет тип WORD
MOV A ,BX
MOV A, 120
• косвенная адресация имеет место при работе со стеком при передаче данных из одной процедуры в другую и при работе с массивами.
• косвенная регистровая: [BX], [BP], [DI], [SI]
MOV BX, offset A ; в BХ заносится смещение переменной А, внутри сегмента.
MOV AX, [BX] ; в регистр AX копируется значение из поля A. Исполнительный адрес вычисляется : Ea = (DS) * 16 + (BX) = [ds]:offset A
По умолчанию DS – регистр сегмента данных. Если имеется другой регистр, то его записываем явно [ES] : [DI]
Нельзя одновременно в одном операнде использовать два индексных или базовых регистра.
Обмен данных
Команда xchg производит обмен данных между операндами:
Регистр – регистр
Регистр – память
Память – регистр
В обмене не может участвовать сегментный регистр !
Команда PUSH источникc помещает содержимое источника на текущую вершину стека с предварительным уменьшением указателя регистра стека SP –2.
Пример. PUSH A ; содержимое источника копируется на вершину стека
1. SP: = SP - 2
2. (A)à([SS:] [SP + 0 ])
Команда POP приемник извлекает содержимое слова из вершины стека и пересылает его в поле приемника, после чего содержимое SP увеличивается на 2:.
Пример. POP A
3. ([SS:] [SP + 0 ]) ® приемник
4. SP: = SP + 2
Команды пересылки адреса
• LEA регистр, источник
• LDS регистр, источник
• LES регистр, источник
LEA регистр, -память
регистр - обязательно 16- разрядный.
Эта команда загружает в регистр-приемник исполнительный адрес источника.
LEA AX , A
Ограничения:
• 1-й операнд не может быть сегментным регистром
• источник не может быть непосредственным операндом или регистром.
LDS регистр, источник
LES регистр, источник
Эти команды производят загрузку адреса в виде двойного слова, причем источник должен быть объявлен с помощью директивы DD.
LDS –это команда загрузки указателя с использованием регистра DS:
1-е слово загружается в регистр общего назначения
2-е слово загружается в регистр DS.
LES – это команда загрузки указателя с использованием регистра ES:
1-е слово загружается в регистр общего назначения
2-е слово загружается в регистр ES.
Команды пересылки флагов
Они НЕ имеют операндов.
• LAHF ; команда пересылает содержимое регистра флагов в регистр АН
• SAHF ; команда пересылает содержимое регистра АН в регистр флагов
• PUSHF ; команда помещает регистр флагов на текущую вершину стека.
• РОРF ; команда восстанавливает из вершины стека регистр флагов.
Эти команды используются при работе с сопроцессором, выполнении команд прерывания.
ЛЕКЦИЯ №3 Команды двоичной арифметики
Как известно, целые положительные числа хранятся в памяти машины в прямом коде, а отрицательные- в дополнительном. Арифметические команды могут обрабатывать целые двоичные числа двух видов: беззнаковые и знаковые. Двоичные числа могут быть 8- и 16-разрядными. Беззнаковые 8-разрядные двоичные числа могут иметь значение от 0 до 255. Для представления беззнаковых чисел в диапазоне от 0 до 65 535 используются 16 разрядов.
Знаковые двоичные числа (целые) также могут быть 8- и 16-разрядными. Самый старший (самый левый) бит знакового числа интерпретируется как знак этого числа: 0 – положительное число, 1 – отрицательное. Отрицательные числа представляются в стандартном двоичном дополнительном коде. Так как старший бит знакового числа используется для обозначения знака, диапазон представления 8-разрядных знаковых чисел от -128 до +127. 16-разрядное целое число представляется в диапазоне от -32 768 до +32 767. Нуль представляется положительным числом.
Для двоичных целых чисел могут выполняться операции сложения, вычитания, умножения и деления
Арифметические команды языка ассемблера.
Сложение
ADD (операнд назначения),(операнд-источник)
Сумма двух операндов, которые могут быть байтами или словами, помещается в операнд назначения. Размеры операндов должны быть одинаковыми, и только один операнд может быть операндом памяти. Регистр сегмента не может быть операндом назначения. Оба операнда могут быть знаковыми или беззнаковыми числами. Команда ADD изменяет значение флагов AF, CF, OF, PF, SF и ZF.
Пример.
Mov BX, 1FFEh
mov CX, 3
add BX, CX ; ВХ=2001h
ADC (операнд назначения),(операнд-источник)
Команда ADC (суммирование с учетом разряда переноса) суммирует операнды, которые могут быть байтами или словами, и добавляет 1, если установлен разряд переноса; результат помещается в операнд назначения. Оба операнда могут быть знаковыми или беззнаковыми числами. Команда ADD изменяет значение флагов AF, CF, OF, PF, SF и ZF. Так как команда ADC учитывает значение разряда переноса от предыдущей операции, это может быть использовано для организации суммирования чисел произвольной разрядности.
INC (операнд назначения)
Команда INC (инкремент) добавляет единицу к операнду назначения. Операнд может быть байтом или словом и трактуется как беззнаковое двоичное число. Команда INC изменяет значение флагов AF, OF, PF, SF и ZF; значение флага CF эта команда не изменяет. Не допускается использовать в качестве операнда непосредственное значение.
Вычитание
SUB (операнд назначения),(операнд-источник)
Содержимое операнда-источника вычитается из содержимого операнда назначения, и результат помещается в операнд назначения. Операнды могут быть знаковыми или беззнаковыми, однобайтовыми или двухбайтовыми числами. Команда SUB изменяет значение флагов AF, CF, OF, PF, SF и ZF.
SBB (операнд назначения),(операнд-источник)
Команда SBB (вычитание с учетом заема) вычитает содержимое операнда-источника из содержимого операнда назначения, затем вычитает из результата 1, если был установлен флаг переноса CF. Результат помещается на место операнда назначения.
Операнды могут быть знаковыми или беззнаковыми, двоичными однобайтовыми или двухбайтовыми числами. Команда SBB изменяет значение флагов AF, CF, OF, PF, SF и ZF. Команда SBB может быть использована для организации вычитания многобайтовых чисел.
DEC (операнд назначения)
Команда DEC (декремент) вычитает единицу из операнда назначения, который может быть одно- или двухбайтовым. Команда DEC изменяет содержимое флагов AF, OF, PF, SF и ZF. Содержимое флага CF при этом не изменяется.
NEG (операнд назначения)
Команда NEG (инверсия) вычитает операнд назначения, который может быть байтом или словом из 0 и помещает результат в операнд назначения. Такая форма двоичного дополнения числа пригодна для инверсии знака целых чисел. Если операнд нулевой, его знак не меняется. Попытка применить команду NEG к байтовому числу -128 или к двухбайтовому числу -32 768 не приводит к изменению значения операнда, но устанавливает флаг OF. Команда NEG воздействует на флаги AF, CF, OF, PF, SF и ZF. Флаг CF всегда установлен за исключением случая, когда операнд равен нулю, когда этот флаг сброшен. Не допускается использовать в качестве операнда непосредственное значение.
CMP (операнд назначения),(операнд-источник)
Команда СМР (сравнение) вычитает операнд-источник из операнда назначения, не изменяя при этом значения операндов. Операнды могут быть байтовыми или двухбайтовыми числами. Хотя значения операндов не изменяются, значения флагов обновляются, что может быть учтено в последующих командах условного перехода. Команда CMP воздействует на флаги AF, CF, OF, PF, SF и ZF. При совпадении значений операндов флаг ZF устанавливается в 1. Флаг переноса CF ZF устанавливается в 1, если операнд назначения меньше операнда-источника.
Умножение
MUL (операнд-источник)
Команда MUL (умножение) выполняет беззнаковое умножение операнда-источника и содержимого аккумулятора. Если операнд-источник однобайтовый, осуществляется умножение на содержимое регистра AL, а двухбайтовый результат возвращается в регистры AH и AL. Если операнд-источник двухбайтовый, осуществляется умножение на содержимое регистра AX, а четырехбайтовый результат возвращается в пару регистров DX и AX.
Операнды рассматриваются как беззнаковые двоичные числа. Если старшая половина результата (регистр AH при однобайтовом умножении и DX при двухбайтовом умножении) не равна нулю, взводятся флаги CF и OF, в противном случае эти флаги сбрасываются.
Если после выполнения умножения установлены флаги CF и OF, это говорит о наличии значащих цифр результата в регистре AH или DX. Содержимое флагов AF, PF, SF и ZF после выполнения команды умножения не определено.
Пример 1.
Mov AL, 5 ; первый сомножитель
Mov BL, 3 ; второй сомножитель
mul BL ;AX=000Fh
Пример 2.
Mov AX, 255 ; первый сомножитель
mov BX, 255 ; второй сомножитель
mul BX ; DX=0001h,AX=0000h
; число 65536
IMUL (операнд-источник)
Команда IMUL (целочисленное умножение) выполняет знаковое умножение содержимого аккумулятора на операнд-источник. Если операнд-источник однобайтовый, осуществляется умножение содержимого регистра AL, а двухбайтовый результат возвращается в регистрах AH и AL. Если операнд-источник двухбайтовый, осуществляется умножение содержимого регистра AX, а четырехбайтовый результат возвращается в паре регистров DX и AX. Операнды рассматриваются как беззнаковые двоичные числа. Если старшая половина результата (регистр AH при однобайтовом умножении и DX при двухбайтовом умножении) взводятся флаги CF и OF, в противном случае эти флаги сбрасываются. Если после выполнения умножения взведены флаги CF и OF, это говорит о наличии значащих цифр результата в регистре AH или DX. Содержимое флагов AF, PF, SF и ZF после выполнения команды целочисленного умножения не определено.
Деление
DIV (операнд-источник)
Команда DIV (деление) выполняет беззнаковое деление содержимого аккумулятора (и его расширения) на операнд-источник. Если операнд-источник однобайтовый, осуществляется деление двухбайтового делимого, расположенного в регистрах AH и AL. Однобайтовое частное получается в регистре AL, а однобайтовый остаток – в регистре AH. Если операнд-источник двухбайтовый, осуществляется деление четырехбайтового делимого, расположенного в регистрах DX и AX. Двухбайтовое частное при этом получается в регистре AX, а двухбайтовый остаток – в регистре DX. Если значение частного превышает разрядность аккумулятора (0FFh для однобайтового деления и 0FFFFh – для двухбайтового) или выполняется попытка деления на нуль, генерируется прерывание типа 0, а частное и остаток остаются неопределенными. Содержимое флагов AF, CF, OF, PF, SF и ZF после выполнения команды DIV не определено. Делитель не может быть задан в виде константы!
IDIV (операнд-источник)
Команда IDIV (целочисленное деление) выполняет знаковое деление содержимого аккумулятора (и его расширения) на операнд-источник. Если операнд-источник однобайтовый, осуществляется деление двухбайтового делимого, расположенного в регистрах AH и AL. Однобайтовое частное получается в регистре AL, а однобайтовый остаток - в регистре AH. Для байтового целочисленного деления положительное частное не может быть больше значения +127 (7Fh), а отрицательное не может быть меньше -127 (81h).
Если операнд-источник двухбайтовый, осуществляется деление четырехбайтового делимого, расположенного в регистрах DX и AX. Двухбайтовое частное при этом получается в регистре AX, а двухбайтовый остаток - в регистре DX. Для двухбайтового целочисленного деления положительное частное не может быть больше значения +32767 (7FFFh), а отрицательное не может быть меньше значения -32767 (8001h). Если частное положительное и превышает максимум или отрицательное и меньше минимума, генерируется прерывание типа 0, а частное и остаток остаются неопределенными. Частным случаем такого события является попытка деления на нуль. Содержимое флагов AF, CF, OF, PF, SF и ZF после выполнения команды IDIV не определено.
Пример.
Mov AX, -506 ;AX=FE06h Делимое
Mov BL, 50 ;Делитель
Idiv BL ;AL=F6h=-10 (частное)
;AH=FAh=-6 (остаток)
Перед операцией деления без знака старшие разряды делимого должны содержать нули:
MOV CL , 3
MOV AL, 32
MOV AH, 0 ; 0 в старшие 8 бит делимого
DIV CL
Перед операцией деления со знаком старшие разряды делимого должны содержать знаковый разряд регистра AL (AX), таким образом, происходит увеличение размера числа. Для этой цели можно использовать следующие команды преобразования:
Команды преобразования данных .
• CBW
• CWD
CBW
Команда CBW (преобразование байта в слово) расширяет знак байта в регистре AL на весь регистр АХ. Команда CBW не воздействует на флаги. Команда CBW может быть использована для получения двухбайтового делимого из однобайтового перед выполнением команды деления.
CWD
Команда CWD (преобразование слова в двойное слово) расширяет знак слова в регистре AХ на регистр DX. Команда CWD не воздействует на флаги. Команда CWD может быть использована для получения четырехбайтового делимого из двухбайтового перед выполнением команды деления.
ЛЕКЦИЯ №4 Программирование разветвлений
Команда сравнения двоичных целых чисел.
Сmp dst, src - данная команда работает аналогично команде вычитания (sub), только приемник не меняется, но при этом устанавливается регистр флагов. Данная команда применяется для организации разветвлений и обычно используется с командами передачи управления.
Команды передачи управления
код операции
операнды
функция
JA/ JNBE
метка
переход, если выше
JAE/ JNB
метка
переход, если выше или равно
JB/ JNAE
метка
переход, если ниже
JBE/JNA
метка
переход, если ниже или равно
JC
метка
переход, если был перенос
JE/JZ
метка
переход. если равно (нуль)
JG/ JNLE
метка
переход, если больше
JGE/ JNL
метка
переход, если больше или равно
JL/ JNGE
метка
переход, если меньше
JLE/ JNS
метка
переход, если меньше или равно
JMP
метка
безусловный переход по метке
JMP
метка
безусловный переход по косвенному адресу
JNC
метка
Переход, если не было переноса
JNE/ JNZ
метка
переход, если не равно ( не нуль)
JNO
метка
переход, если не было переполнения
JNP/ JPO
метка
переход, если нет четкости
JNS
метка
переход, если нет знака
JO
метка
переход. если было переполнение
JP/ JPE
метка
переход, если есть четность
JS
метка
переход, если есть знак
JCXZ
метка
переход, если в СХ — нули
LOOP
метка
цикл
LOOPE/
LOOPZ
метка
цикл, пока равно (нуль)
LOOPNE/
LOOPNZ
метка
цикл, пока не равно (нуль)
Команда безусловного перехода
Jmp метка в Ассемблере.
Jmp меняет содержимое регистра IP в случае :
а) если метка имеет тип short и находится от места командировки на –128..127
б) если метка имеет тип near и находится от места командировки на
-32768..32767
После трансляции код команды jmp может иметь длину 2 байта (short), 3 байта (near), пять байтов (far).
Адрес перехода может быть задан в формате прямой адресации:
Jmp M1
где М1 - label
М1 – адрес этой метки определяется через пару СS: offsetM1
Команды условного перехода
Условные переходы делятся на две группы:
• Проверяющие результаты предыдущей арифметической или логической команды;
• Управляющие итерациями фрагмента программы.
Команды условного перехода выполняют или не выполняют передачу управления на указанный адрес в зависимости от состояния флагов процессора не момент выполнения команды. Эти команды проверяют различные комбинации флагов и условий. Если условие истинно, осуществляется передача управления на указанный адрес. Если условие неверно, управление передается команде, следующей за командой условного перехода. Все команды условного перехода являются короткими (SHORT), так что диапазон переходов в этих командах лежит в диапазоне от -128 до +127 байтов.
Некоторые команды условного перехода проверяют текущее состояние регистра флагов, а затем в зависимости от кодов условия команда делает переход ( или не делает). Команды условного перехода не устанавливают флаги, а только проверяют их текущее состояние. Ранее рассмотренные арифметические и логические команды устанавливают флаги.
Существуют четыре возможных соотношения между операндами без знака. Для того чтобы отличить команды условного перехода арифметики без знака от команд условного перехода арифметики со знаком используются мнемоники “выше” и “ниже”. В то время как мнемоники “больше” и “меньше” говорят о соотношении чисел со знаком, для арифметики без знака - мнемоники ”выше” ( above) и “ниже” ( below). Например, программа использует команду JA (переход, если выше). Микропроцессор выполняет условный переход в зависимости от соотношения двух чисел, считая их числами без знака, т.е. именно программист обязан выбрать правильную команду условного перехода.
Отдельную группу команд условного перехода составляют арифметические сравнения со знаком. Существуют четыре условия, которые могут быть проверены: меньше ( JL), меньше или равно ( JLE), больше (JG), больше или равно ( JGE). Другие четыре мнемоники — отрицания этих четырех. В случае арифметики со знаком ассемблер использует мнемонику “меньше” ( less) и “ больше” (greater). Арифметические сравнения можно понять, используя их вместе с командой СМР. Например,
CМР АХ, ВХ
JL LABEL
Переход произойдет, если содержимое регистра АХ меньше содержимого регистра ВХ. Можно читать комбинацию команд сравнения и условного перехода вместе, как один оператор: операнд результата встречается первым, затем идет условный оператор, а за ним следует исходный операнд. Другой пример:
CMP CX, WORD_IN_MEMORY
JNLE LABEL
можно прочитать так: переход, если содержимое регистра СХ не меньше или равно содержимому ячейки памяти WORD_IN_MEMORY. Этот прием можно использовать для определения значения любой команды арифметического перехода, учитывающей знак или не учитывающий.
Пример 1.
;Пример lab2:
; y=min(a*b,d*d)
a_data segment para
a dw 6
b dw 5
d dw 7
y dw ?
a_data ends
a_stack segment para stack
db 100 dup(0)
a_stack ends
a_code segment para
assume ss:a_stack, ds:a_data,cs:a_code
begin:
mov ax,a_data
mov ds,ax
; a*b-> BX
mov ax,a
imul b
mov bx,ax
; d*d ->ax
mov ax,d
imul ax
; Развилка
cmp bx,ax ;d*d-a*b
jle m1 ;if d*d<=a*b then jump label m1
; else
mov y,ax
jmp finish
m1:
mov y,bx
finish:
mov ah,4CH
int 21h
a_code ends
end begin
Управление циклом
Существует несколько команд условного перехода, предназначенных для управления циклами в программах.
Команды цикла LOOP используют регистр СХ в качестве счетчика цикла. Команда LOOP уменьшает регистр СХ и передает управление на метку, если содержимое регистра СХ не равно 0. Если вычитание 1 из регистра СХ привело к нулевому результату, команда LOOP не делает перехода и выполняется следующая команда. Ниже приведен принцип работы команды LOOP:
Программный фрагмент, который демонстрирует обычное использование команды LOOP:
MOV CX, LOOP_COUNT
BEGIN_LOOP:
; ... тело цикла
LOOP BEGIN_LOOP
Программа помещает число итераций цикла в регистр СХ перед выполнением цикла. Затем выполняется тело цикла, а следом за ним — команда LOOP. Она уменьшает счетчик на 1, что соответствует единственной, только что выполненной итерации цикла. Если теперь счетчик в регистре СХ равен 0, программа продолжает выполнять команды после LOOP. Если счетчик не равен 0, управление возвращается к началу цикла, чтобы совершить еще один проход по телу цикла. Тело цикла выполняется столько раз, сколько было сначала задано содержимым регистра СХ.
Замечание: Если программа внутри цикла изменяет регистр СХ, число итераций не будет соответствовать начальному значению в регистре СХ.
Если СХ не был инициализирован или в него не была занесена величина 0, то команда loop вызовет повторение цикла 65536 раз. Существует специальная команда, позволяющая проверить содержимое счетчика СХ на 0 и передавать управление в точку , где обрабатывается эта ситуация:
jcxz label_ ERROR
Эту команду целесообразно использовать перед циклом, когда содержимое регистра СХ формируется программным путем, Эта команда проверяет текущее содержимое регистра СХ и делает переход, если оно равно 0. Команда не проверяет ни одного флага и не влияет ни на один из них.
В следующем примере регистр СХ загружается из ячейки памяти, содержимое которой вычисляется во время выполнения программы. Может оказаться, что счетчик циклов нулевой, поэтому в примере используется команда JCХZ, чтобы проверить, нужно ли полностью пропустить тело цикла:
MOV CX, LOOP_COUNT_WORD
JCXZ END_OF_LOOP
BEGIN_LOOP:
; . . . тело цикла
LOOP BEGIN_LOOP
END_OF_LOOP
Оставшиеся две команды цикла предоставляют еще больше возможностей при управлении циклами. Если команда LOOP выходит из цикла только когда в регистре СХ оказывается 0 , то команда LOOPE ( цикл, пока равно) выходит из цикла, если установлен флаг нуля или если в регистре СХ получился 0. Тем самым становится возможным двойственное завершение цикла. Программа может загрузить в регистр СХ максимальное число итераций цикла, а затем проверять флаг нуля в конце каждого цикла на условие завершения. Команда LOOPNE (цикл, пока не равно) выполняет обратную проверку флага нуля: цикл здесь завершается, если регистр СХ достиг 0 или если установлен флаг нуля.
Лекция №5 Работа с массивами
Основные понятия. Массив. Элемент массива.
Массив это совокупность элементов одинакового типа. Массив состоит из фиксированного числа элементов. Размерность массива фиксируется при объявлении его и при исполнении программы не меняется.
Объявление массива
В языке высокого уровня PASCAL объявление массива имеет вид
Имя_массива :array[тип индекса] of тип элемента
Например, объявления массива констант и массива переменных могут иметь вид:
Const
D:array[1..5] of integer=(10,-4,1234,0,-5);
Var
A:array[1..5] of integer;
Тип целочисленной переменной может быть задан ключевыми словами: integer/ Byte/Word/Shortint.
Все элементы массива располагаются в оперативной памяти. Размер области, отводимой под один элемент массива, зависит от указанного типа: для integer/Word выделяется по 2 байта, а для Byte/Shortint по 1 байту.
На ассемблере объявления массива констант и массива переменных могут иметь вид:
D DW 10,-4,1234,0,-5); массив констант
A DW 5 dup(?) ;резервировано 5 слов по 2 байта.
Как видно из примера, на ассемблере явно указан размер элемента массива, но не указано, числа со знаком (integer/ Shortint) или без знака (Byte/Word). Программист должен сам контролировать предполагаемый диапазон значений элементов.
Положение элемента в массиве определяется набором индексов или координат. Доступ к элементу одномерного массива (вектора) указывается с помощью индексной переменной.
На Pascal элемент вектора А обозначается A[i] или A[j], адреса соседних элементов массива отличаются на размер поля, занимаемого одним элементом. Если тип Integer/ Word, то разница равна 2, а для типов Byte/ Shortint разница равна 1. Переадресация элементов на языке высокого уровня выполняется «автоматически»( транслятор предусматривает нужные операции), а на ассемблере необходимые действия кодируются программистом.
При работе с массивами в Ассемблере используется косвенная адресация полей памяти.
косвенная регистровая: [BX], [BP], [DT], [SI]
MOV BX, offset A ; в BХ заносится смещение переменной А, внутри сегмента.
MOV AX, [BX] Эффективный адрес вычисляется : Ea = (DS)*16 + (BX)
MOV DI, offset B
ADD AX, [DI]
По умолчанию DS – регистр сегмента данных. Если имеется другой регистр, то его записываем явно [ES] : [DI]
регистровая базовая
[BХ] ± выражение
[BХ] + смещение
Примеры записи X[BX] , X + [BX] , [BX] – 2, [BX -2]
В случае базового регистра ВХ регистром сегмента считается регистр DS.
Ea = (DS) * 16 + (BX) + offset X ± константа выражения.
Если данные находятся в стеке, то используемый регистр ВР, который по умолчанию формирует адрес относительно регистра SS ( SS:[ВР] )
Ea = (SS) * 16 +(BP)
[BP] + 2 ; [BP -2] ;
Обычно регистр ВР используется при извлечении параметров процедуры, передаваемых через стек.
регистровая индексная [DI] и [SI]
A [SI] Ea =A + [SI]
B [DI] Ea =B + [DI]
Исполнительный адрес Ea = (DS) * 16 + смещение переменной + содержание регистра индекса.
Базовая индексная со смещением .
A [BX] [DI]
A + [BX] +[DI]
A + 4 [BX] [DI]
Нельзя одновременно в одном операнде использовать два (2) индексных или базовых регистра.
Еа = (DS)* 16 – (Р.И.) + смещение.
Примеры составления программ работы с массивами
Пример 1.
Дан массив из 10-ти элементов целого типа. Найти:
Реализация программы на Паскале :
Program p1;
Const
a:array[1..10] of integer=(-10, 3, 7, 0, 10, 0, -4, -8, 1, 1);
Var
S: integer;
I:integer;
Begin
{}
S: = 0;
begin
For i: = 1 to 10 do S: = S + a[i] * a[i]
end;
end.
Реализация программы на Ассемблере:
Используются регистры:
АX, BX, DX, CX, DI.
BX – для накопления суммы
AX, DX – для вычисления квадрата . A2j
CX – счетчик цикла.
Каждый элемент массива типа integer занимает слово или 2 байта. Элемент A1 расположен по адресу A+0, элемент A2 на 2 байта дальше то есть, A+2.
Для адресации элемента массива A[i] применим индексную адресацию: A[i] ≈ A[DI] Исполнительный адрес A[DI] будет вычисляться процессором в виде суммы адреса начала массива (адрес A+0] и содержимого DI, который меняется от 0 с шагом 2.
В сегменте данных:
A DW -10, 3, 7, 0, 10, 0, -6, -8, 1, 1
S DW ?
Сегмент кода
…………………………………..
; подготовка к циклу
MOV CX, 10 ; инициализация счетчика циклов
MOV BX, 0 ;очистка суммы
MOV DI, 0 ;i=1
Metka:
MOV AX, A [DI] ; Ai ® AX
Imul AX ;AX = A2i
Add BX , AX ;прибавление к сумме
; переадресация i: = i+ 1.
Add DI, 2 ; или Add DI , type A;
; управление циклом
loop metka
MOV S, BX
Анализ работы программы:
Определить содержимое регистров BX , DX, CX, AX после цикла, DI.
DI – 20 ( 0014h)
AX – 1 ( 0001h)
DX – 0 ( 0000h)
CX – 0 ( 0000h)
BX –168h =36010
Пример 2.
Дан массив A[10] типа Integer . Ввести элементы массива с клавиатуры.
Реализация программы на Паскале:
Program p2;
Var
a:array[1..10] of integer;;
I:integer;
Begin
i : = 1;
while (i<=N do begin
write(‘введите элемент массива ’) ;
readln(a[i]);
i : = i + 1;
end;
writeln(‘ Масив введен’);
readln;
end.
Реализация программы на Ассемблере:
%nolist
include mac.lib
%list
A_Stack segment Stack `стек`
DW 256 dup (0)
A_STACK ENDS.
A_Data segment
A dw 10 dup(?)
Mes1 db 10,13, ’введите элемент массива $’
Meser db 10,13, ’ Ошибка ввода. Повторите! ‘,10, 13, ‘ $’
Mes2 db 10,13, ’ Массив введен $’
A_Data Ends
A_Code Segment PARA PABLIC
Assume DS: A_Data, SS: A_Stack, CS; A_Code
START: ; подготовка к циклу
mov cx, 10 ; число элементов массива.
mov di, 0 ; i: = 1
CIKL: lea dx, mes1
mov ah,9h
int 21h
; макрос ввода с клавиатуры
Key_$2bin ; ввод числа со знаком в регистр ax.
Jnc good
Lea dx, meser
Mov ah,9h
Int 21h
Jmp cikl
Good: Mov А[DI], ax ; AX-> A[i]
; переадресация
ADD DI, 2 ; i: = i + 1
until: dec cx ; cx=cx-1
jz final ; при cx=0 на метку final
jmp CIKL; если CX не 0 , то безусловный переход на метку CIKL
final: lea dx,mes2
mov ah,9h
int 21h
; exit;
Mov ah, 4ch
Int 21h
A_Code ends
End start
Комментарий
В тело цикла включена макрокоманда Key_$2bin. После подстановки ее макрорасширения тело цикла может оказаться по размеру длиннее 128 байт, что превышает возможности команды LOOP, и она в данной программе не использована для управления циклом
Лекция № 6 Прерывания
Прерывания(interruption) получили свое название по своей основной функции – приостановить процесс основных вычислений в ЦП для выполнения вспомогательных , технологических и сервисных действий ОС.
Процедуры обработки прерываний - это подпрограмма с обязательным обращением через косвенный межсегментный адрес, размещенный в фиксированной области памяти.
Прерывания принято классифицировать по трем типам:
• программные
• аппаратные
• отладочные
Если возникает прерывание ,то оно не может остановить микропроцессор во время выполнения им команды. Микропроцессор 8088 прежде всего, завершает выполнение текущей команды, затем, не обращая внимания на следующую команду, действует как в случае вызова подпрограммы. То есть он записывает адрес следующей команды в стек и переходит к специальной подпрограмме, которая называется обработчиком прерывания. Эта подпрограмма содержит команды, которые требуются для обслуживания устройства, вызвавшего прерывание.
После того, как подпрограмма обработки прерывания закончила свою работу с устройством она возвращает управление в точку программы, где произошло прерывание.
Векторы прерываний.
Важная составная часть микропроцессора 8088 – это механизм прерывания. Эта компонента встроена в микропроцессор и обеспечивает эффективное обслуживание прерываний.
Когда МП 8088 получает сигнал о необходимости прерывания ,он определяет какое из устройств требует обслуживания посредством аппаратной процедуры, известной как цикл подтверждения прерывания.
Контроллер 8259 фирмы Intel
Контроллер прерываний программируется так, чтобы выдавать 1-байтовое число в ответ на цикл подтверждения прерывания микропроцессора 8088. Это число лежит в диапазоне от 0 до 255 и показывает номер прерывания внешнего прерывающего устройства. В ПЭЦМ контроллер прерывания обслуживает восемь внешних прерываний, которым соответствуют номера от 8 до 15.
Первые 1024=256*4 байт памяти МП8088 зарезервированы для векторов прерывания, где каждому из прерываний отводится 4-байтовая область:
№ прерывания
Адрес
0 – 3
1
4 – 7
2
8 – 11
...
...
...
...
255
1021 – 1023
Каждая 4-байтовая ячейка содержит указатель на обработчик прерывания с номером N.
к + 0, к + 1 - смещение
к + 2, к + 3 - сегмент
DS_VEC SEGMENT PARA AT 0h
VECTOR DD 256 dup(?)
DS_VEC ENDS
Как только МП8088 получает номер прерывания, он передает управление соответствующему обработчику. Обработчик прерывания должен обслужить прерывание как вызов дальнего типа FAR, поэтому прежде чем передать управление обработчику прерывания, он должен сохранить как сегмент, так и смещение текущей команды. Возврат из программы обработки прерывания должен произойти так, чтобы машина вернулась в то же состояние, в котором она была в тот момент, когда возникло прерывание. Поэтому МП сохраняет также регистр флагов. Обработчик прерываний не будет производить эти действия. При сохранении регистра флагов сохраняется также и текущее состояние флага разрешения прерываний. Программа обработки не может быть прервана другим прерыванием. Команда возврата из прерывания восстанавливает регистр флагов, то есть возвращает предыдущее состояние флагу прерывания.
Итак, возникло прерывание- выполняется следующая цепочка действий:
1) регистр флагов заносится в стек
2) CS:IP ® стек
3) № прерывания = VECTN
4) адрес подпрограммы = VECT(N * 4)
5) CS := VECT(N * 4)
IP := VECT(N * 4) + 2
6) подпрограмма сохраняет регистры в стеке
7) обработка
8) восстановление регистров
9) возврат IRET:
IP, CS, регистр флагов
Флаг специального прерывания TF
Флаг TF позволяет отлаживать программы. Этот флаг не устанавливается в результате работы процессора, а устанавливается программно с помощью специальной команды. Этот флаг называется также флагом трассировки или пошаговой работы.
Ввод-вывод на языке Ассемблера
Осуществляется с помощью процедур прерывания (аппаратные и программные). Процедуры обработки аппаратных прерываний расположены в оперативной памяти в блоке F. Они составлены разработчиками аппаратных средств BIOS.
Процедуры программных прерываний составлены разработчиками операционной системы. В нулевом блоке оперативной памяти находится Таблица Векторов Прерываний. Это область длиной 1024 байта или 256 * 4 :
0000 : 0000 прерывание 0 - адрес обработки процедуры прерывания:
0000 : 0004
. . . . . . . . . .
0000: 03FB - вектор прерывания
Таблица векторов прерываний представляет собой таблицу дальних переходов.
В таблице векторов прерываний не все 256 элементов содержат адреса. Векторы прерываний DOS занимают следующие номера в этой таблице:
20h – завершение программы
21h – запрос функций DOS
22h – адрес окончания
23h – адрес обработки Ctrl - Break
24h – обработка неустранимой ошибки
25h – абсолютные режимы чтения
26h – и записи диска.
27h – программа завершена, но остаётся резидентной в памяти.
Процедуры обработки прерывания в отличие от обычных процедур заканчиваются командой IRET. Вызов процедур прерывания выполняется командой
INT номер прерывания.
Команда INT № вызывает следующие действия:
1. помещает в стек три слова: регистр IP,CS и регистр флагов;
2. заменяет регистр IP, CS на соответствующий вектор прерывания;
3. выполняет процедуру обработки прерывания;
4. команда IRET восстанавливает регистр флагов, регистры CS и IP - т.е. осуществляет возврат в точку вызова.
Прерывание DOS int 21h:
Ah
Действие int 21h
00h
Завершение программы
01h
Ввод с клавиатуры с эхо-символов
02h
Вывод на экран символа из регистра DL
07h
Прямой ввод без эхо-вывода (нет реакции на Ctrl -break)
08h
Ввод с клавиатуры без эхо-вывода, но с реакцией на
Ctrl -break
09h
Вывод строки, завершающийся знаком $, адрес начала в регистре DX
0Bh
Проверка состояния клавиатуры. Результат в Аh.
Если Ah > 00, то ввод невозможен Если Ah = FF , то ввод возможен
0Аh
Буферизованный ввод с клавиатуры
0Ch
Очистка буфера клавиатуры. Выполнение функции, номер которой хранится в регистре АL
0Dh-24h
Процедуры работы с файлами.
2Ah-2Dh
Работа с датами и временем.
Пример использования прерывания 21h
Вывод символа «W» на дисплей состоит из трех команд
Mov DL,’ W’ ;занести символ W в регистр DL
Mov AH, 02h ; указать нужную функцию AH
INT 21h ; вызов прерывания DOS 21H
Команды ввода и вывода
Языки ассемблера обычно не содержат специальных средств операций ввода исходных данных и вывода из нее результатов. Выполнение даже простой операции вывода целого числа из оперативной памяти на экран требуется множество трудоемких действий. Сначала число должно быть преобразовано из двоичного кода в десятичное число, которое потом должно быть преобразовано в строку символов (обычно в коде ASCII). Строка символов в коде ASCII должна быть передана на терминал.
Для выполнения простых операций ввода и вывода вводится некоторое расширение языка ассемблера. Это дополнительные команды языка называются макрокомандами. Они представляют собой комбинации команд базового набора, оформленные в виде так называемого «макроопределения». Макрокоманды обрабатываются на этапе трансляции подобно директивам языка ассемблера: происходит обращение к макроопределению и соответствующий текст (так называемое макрорасширение )помещается на место вызывавшей макрокоманды. Исходный текст программы, естественно, увеличивается в длине.
Необходимые команды собраны в текстовом файле MAC.lib.
Для их применения необходимо подключить библиотеку MAC.lib.
Include mac.lib
Отключить печать содержимого библиотеки директивой % nolist.
Иначе файл листинга будет очень большим.
% nolist
Include mac.lib
% list
После подключения библиотеки вновь включить вывод листинга.
Макрокоманды
KEY_$2BIN
ДЕЙСТВИЕ Преобразует последовательность набранных на клавиатуре символов в число со знаком, помещаемое в регистр AX.
ВХОДНЫЕ ЗНАЧЕНИЯ Отсутствуют.
ВЫХОДНЫЕ ЗНАЧЕНИЯ Если последовательность символов допустима, то CF=0 и (AX)=полученное число. Если недопустима, то СF=1.
ПРИМЕР KEY_$2BIN ; Ввести число с клавиатуры
JC PRINT ERROR
MESSAGE ИМЯ-СТРОКИ
ДЕЙСТВИЕ Изображает на экране строку символов, находящуюся
в сегменте данных.
ВХОДНЫЕ ЗНАЧЕНИЯ ИМЯ-СТРОКИ.
ФОРМАТ СТРОКИ Строка должна заканчиваться символом $.
Например ILLEGAL DB ‘Ошибочное значение $’ .
ВЫХОДНЫЕ ЗНАЧЕНИЯ Отсутствуют.
ПРИМЕЧАНИЕ Аналогично макроопределению MESSAGE_DX, но MESSAGE
берет указатель строки по имени, заданному пользователем,
а не из регистра.
ПРИМЕР MESSAGE ILLEGAL ; Изобразить сообщение ILLEGAL
PRINT_NUMBER
ДЕЙСТВИЕ Изображает число со знаком, содержащимся в регистре AX.
ВХОДНЫЕ ДАННЫЕ (AX) =изображаемое число.
ВЫХОДНЫЕ ЗНАЧЕНИЯ Отсутствуют ; содержимое регистра AX не изменяется.