У вас вопросы?
У нас ответы:) SamZan.net

Лабораторная работа 2 Изучение команд пересылки данных Цель работы- изучить способы адресации данн

Работа добавлена на сайт samzan.net:

Поможем написать учебную работу

Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.

Предоплата всего

от 25%

Подписываем

договор

Выберите тип работы:

Скидка 25% при заказе до 28.12.2024

Лабораторная работа №2

«Изучение команд пересылки данных»

Цель работы: изучить способы адресации данных микропроцессором i8x86 и применение этих методов при пересылке данных.

Оборудование: IBM - совместимый персональный компьютер, работающий под управлением операционной системы, совместимой с MS-DOS®.

Программное обеспечение: Программа DEBUG

Краткие теоретические сведения.

  1.  Методы адресации данных
  2.  Команды пересылки данных

Режимы адресации данных

Микропроцессор 8x86 предоставляет Вам множество способов доступа к операндам, с которыми должна работать Ваша программа. Операнды могут содержаться в регистрах, в самих командах, в памяти или в портах ввода-вывода. В рекламных проспектах производителей оборудования утверждается, что микропроцессор 8x86 имеет 24 режима адресации операндов. Пожалуй, так оно и есть, если рассматривать все возможные комбинации. Здесь мы разделяем режимы адресации на семь групп:

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

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

3. Прямая адресация.

4. Косвенная регистровая адресация.

5. Адресация по базе.

6. Прямая адресация с индексированием.

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

Микропроцессор выбирает один из семи режимов адресации по значению поля режима команды. Ассемблер присваивает то или иное значение полю режима в зависимости от того, какой вид имеют операнды в исходной программе. Например, если вы написали

MOV АХ,ВХ

то Ассемблер закодирует оба операнда (АХ и ВХ) для регистровой адресации. Однако если Вы заключили операнд-источник в квадратные скобки:

MOV AХ,[ВХ]

то Ассемблер закодирует операнд-источник для косвенной регистровой адресации.

В табл. 1 приведены форматы операндов языка ассемблера для всех семи режимов адресации, реализуемых микропроцессором 8x86, и для каждого формата указано, какой из регистров сегмента используется для вычисления физического адреса. Обратите внимание, что во всех режимах предполагается доступ к сегменту данных (т. е. регистром сегмента служит регистр DS), и только в тех случаях, когда используется регистр ВР, предполагается доступ к сегменту стека (т. е. регистром сегмента служит регистр SS).

Важное замечание: при исполнении команд микропроцессора 8x86, манипулирующих строками, предполагается, что регистр DI указывает на ячейку дополнительного сегмента, а не сегмента данных. Таким образом, в качестве регистра сегмента эти команды используют регистр ES. Все другие команды исполняются по правилам, описанным в табл.1.

Таблица 1. Режимы адресации микропро     цессора 8x86

Режим адресации

Формат операнда

Регистр сегмента

Регистровый

регистр

Не используется

Непосредственный

данное

Не используется

Прямой

сдвиг

метка

DS

DS

Косвенный регистровый

[ВХ]

[ВР]

[DI]

[SI]

DS

SS

DS

DS

По базе

[ВХ] + сдвиг

[ВР] + сдвиг

DS

CS

Прямой с индексированием

[DI] + сдвиг

[SS] + сдвиг

DS

DS

По базе с индексированием

[BX][SI] + сдвиг

[ВХ] [DI] + сдвиг

[ВР] |S1] + сдвиг

[ВР] [DI] + сдвиг

DS

DS

SS

SS

Примечания к таблице:

1. Компонент сдвиг при адресации по базе с индексированием необязателен.

2. Операнд регистр может быть любым 8-ми 16-и битовым регистром, кроме регистра IP.

3. Операнд данное может быть 8- или 16-битовым значением константы.

4. Компонент сдвиг может быть 8- или 16-битовым значением смещения со знаком.

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

Каждое описание режима адресации, приведенное в данном разделе, сопровождается примерами его применения. В большинстве случаев для этого используется команда MOV микропроцессора 8x86.

Регистровая и непосредственная адресация

При регистровой адресации микропроцессор 8x86 извлекает операнд из регистра (или загружает его в регистр). Например, команда

MOV AХ,СХ

копирует 16-битовое содержимое регистра счетчика СХ в аккумулятор АХ. Содержимое регистра СХ не изменяется. В данном примере микропроцессор 8x86 использует регистровую адресацию для извлечения операнда-источника из регистра СХ и загрузки его в регистр-приемник АХ.

Непосредственная адресация позволяет Вам указывать 8- или 16-битовое значение константы в качестве операнда-источника. Эта константа содержится в команде (куда она помещается Ассемблером), а не в регистре или в ячейке памяти. Например, команда

MOV СХ,500

загружает значение 500 в регистр СХ, а команда

MOV CL,-30

загружает значение - 30 в регистр CL.

Чтобы избежать трудностей, помните, что допустимые значения для 8-битовых чисел со знаком ограничены диапазоном от -128 (80Н) до 127 (7FH), а допустимые значения 16-битовых чисел со знаком — диапазоном от —32768 (8000Н) до 32767 (7FFFH). Максимальные значения 8-битовых чисел без знака равны соответственно 255 (OFFH) и 65535 (OFFFFH).

Расширение знакового бита непосредственных значений

Ассемблер всегда расширяет знак при пересылке непосредственных значений в операнд-приемник. Это означает, что он дублирует старший значащий бит значения источника до тех пор, пока не будут заполнены все 8 или 16 битов операнда-приемника.

Например, операнд-источник нашего первого примера, десятичное число 500, может быть записано в виде 10-битового двоичного значения 0 111 110 100. Когда Ассемблер устанавливает, что Вы требуете загрузить это значение в 16-битовый регистр СХ, то он расширяет его до 16-битового, записав перед ним шесть копий "знакового" бита (со значением 0). Поэтому в регистр СХ попадает двоичное значение 0 000 000 111 110 100. Во втором примере микропроцессор 8x86 загружает в регистр CL 8-битовое двоичное представление 11 100 010 десятичного числа –30.

Режимы адресации памяти

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

Исполнительный адрес

Смещение, которое вычисляется операционным блоком для доступа к находящемуся в памяти операнду, называется исполнительным адресом операнда. Исполнительный адрес показывает, на каком расстоянии (в байтах) располагается операнд от начала сегмента, в котором он находится. Будучи 16-битовым числом без знака, исполнительный адрес позволяет получить доступ к операндам, находящимся выше начала сегмента на расстоянии до 65535 (или 64К) байтов.

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

Прямая адресация

При прямой адресации исполнительный адрес является составной частью команды (так же, как значения при непосредственной адресации). Микропроцессор 8x86 добавляет этот исполнительный адрес к сдвинутому содержимому регистра сегмента данных DS и получает 20-битовый физический адрес операнда.

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

MOV AX,TABLE

загружает содержимое ячейки памяти TABLE в регистр АХ. На рис. 1 показана схема исполнения этой команды. Обратите внимание на то, что против ожидания микропроцессор 8x86 заполняет данные в памяти в обратном порядке. Старший байт слова следует за младшим байтом, а не предшествует ему. Чтобы усвоить это, запомните, что старшая часть (старшие биты) данных располагается в ячейках памяти со старшими адресами.

 

Рис. 1. Прямая адресация                      Рис. 2. Косвенная регистровая адресация

Косвенная регистровая адресация

При косвенной регистровой адресации исполнительный адрес операнда содержится в базовом регистре ВХ, регистре указателя базы ВР или индексном регистре (SI или DI). Косвенные регистровые операнды надо заключать в квадратные скобки, чтобы отличить их от регистровых операндов. Например, команда

MOV AХ,[ВХ]

загружает в регистр АХ содержимое ячейки памяти, адресуемой значением регистра ВХ (рис. 2).

Как поместить смещение адреса в регистр ВХ? Один из методов состоит в применении команды LEA (Загрузить исполнительный адрес). Например, для загрузки слова из ячейки TABLE в регистр АХ можно воспользоваться последовательностью команд

LEA BX, TABLE

MOV AХ,[ВХ]

Эти две команды выполняют те же действия, что и одна команда

MOV AX,TABLE

с той лишь разницей, что в первом случае предыдущее содержимое регистра ВХ уничтожается. Если Вам нужен доступ лишь к одной ячейке памяти (в данном случае TABLE), то разумнее воспользоваться одной командой. Однако для доступа к нескольким ячейкам, начиная с данного базового адреса, гораздо лучше иметь исполнительный адрес в регистре. Почему? Потому что содержимым регистра можно манипулировать, не извлекая каждый раз новый адрес.

Адресация по базе

При адресации по базе Ассемблер вычисляет исполнительный адрес с помощью сложения значения сдвига с содержимым регистров ВХ или ВР.

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

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

MOV AХ,[ВХ]+4

загрузит в регистр АХ номер отдела, в котором служит данный работник (рис. 3). (Сдвиг равен 4, а не 5, потому что первый байт записи имеет номер 0.)

Ассемблер позволяет указывать адресуемые по базе операнды тремя разными способами. Следующие команды эквивалентны:

MOV AХ,[ВР]+4      ;3то стандартная форма записи,

MOV AХ,4[ВР]       ; но сдвиг можно указать на первом месте

MOV AХ,[ВР+4]      ; или внутри скобок

    Рис. 3. Адресация по базе                     Рис. 4. Прямая адресация с индексированием

Прямая адресация с индексированием

При прямой адресации с индексированием исполнительный адрес вычисляется как сумма значений сдвига и индексного регистра (DI или SI). Этот тип адресации удобен для доступа к элементам таблицы, когда сдвиг указывает на начало таблицы, а индексный регистр – на ее элемент.

Например, если B_TABLE — таблица байтов, то последовательность команд

MOV DI,2

MOV AL,В_TABLE[DI]

загрузит третий элемент таблицы в регистр AL.

В таблице слов соседние элементы отстоят друг от друга на два байта, поэтому при работе с ней надо удваивать номер элемента при вычислении значения индекса. Если TABLE — таблица слов, то для загрузки в регистр АХ ее третьего элемента надо использовать последовательность команд

MOV DI,4

MOV AХ,TABLE[DI]

(рис. 4).

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

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

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

Предположим, например, что Ваша ЭВМ следит за шестью предохранительными клапанами на химическом предприятии. Она считывает их состояния каждые полчаса и запоминает в ячейках памяти. За неделю эти считывания образуют массив, состоящий из 336 блоков (48 считываний в течение семи дней) по шесть элементов в каждом, а всего — 2016 значений.

Если начальный адрес массива загружен в регистр ВХ, сдвиг блока (номер считывания, умноженный на 12) - в регистре DI, а номер клапана задан в переменной VALVE, то команда

MOV AX ,VALVE[BX][DI ]

загрузит требуемое считывание состояния клапана в регистр АХ. На рис. 5 изображен процесс извлечения результата третьего считывания (с номером 2) для клапана 4 из массива, у которого смещение в сегменте данных равно 100Н.

Приведем несколько допустимых форматов операндов, адресуемых по базе с индексированием:

MOVE AX,[BX+2+DI]

MOVE AX,[DI+BX+2]

MOVE AX,[BX+2][DI]

MOVE AX,[BX][DI+2]

КОМАНДЫ ПЕРЕСЫЛКИ ДАННЫХ

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

Команды общего назначения

Основная команда общего назначения MOV (move - переслать) может пересылать байт или слово между регистром и ячейкой памяти или между двумя регистрами. Она может также пересылать непосредственно адресуемое значение в регистр или в ячейку памяти.

Команда MOV имеет следующий формат:

MOV приемник, источник

В ней допустимо большинство из возможных сочетаний операндов.

Приведем несколько примеров:

MOV AX,TABLE  ; Пересылка иэ памяти в регистр

MOV TABLE,AX  ; и наоборот

MOV ES:[BX],АХ  ; Можно заменить используемый регистр сегмента

MOV DS,AХ   ; Пересылка между 16-битовыми регистрами

MOV BL.AL   ; Пересылка между 8-битовыми регистрами

MOV CL,-30  ; Пересылка константы в регистр

MOV DE5T,25H  ; или в память

В команде MOV исключаются следующие сочетания операндов:

1. Вы не можете осуществить непосредственную пересылку данных из одной ячейки памяти в другую. Чтобы выполнить такую пересылку, данные источника надо загрузить в регистр общего назначения, а затем запомнить содержимое этого регистра в приемнике. Например, если POUNDS и WEIGHT - переменные, находящиеся в памяти, то для пересылки значения из одной переменной в другую можно воспользоваться командами

MOV AX,POUNDS

MOV WEIGHT,AX

2. Вы не можете загрузить непосредственно адресуемый операнд в регистр сегмента. Как и в случае 1, сначала надо загрузить его в регистр общего назначения. Например, следующие команды загружают номер блока сегмента данных (DATA_SEG) в регистр DS:

MOV HX,DATA_SEG

MOV DS,AX

Подобные команды обычно сопутствуют оператору ASSUME в сегменте команд. Они указывают Ассемблеру, где размещен сегмент данных.

3. Вы не можете непосредственно переслать значение одного регистра сегмента в другой. Делайте подобные пересылки через регистр общего назначения. Например, чтобы регистр DS указывал на тот же сегмент, что и регистр ES, воспользуйтесь командами

MOV AX,ES

MOV DS,AX

(Для выполнения этой операции можно воспользоваться командами PUSH и POP, которые будут описаны в следующем разделе.)

4. Вы не можете использовать регистр CS в качестве приемника в команде пересылки.

Команда обмена XCHG

Команда обмена XCHG (exchange - обменять) меняет между собой значения двух регистров или регистра и ячейки памяти. Однако она не может выполнить обмен значений регистров сегмента.

Приведем несколько примеров команд XCHG:

XCHG AX,BX           ;Обменять значения двух регистров (слова

XCHG AL,BH           ; или байты

XCHG WRD_LOC,DX      ;Обменять значения ячейки памяти

ХСНG DL,BYTE_LOC     ; и регистра

Команды ввода-вывода

Команды ввода-вывода используются для взаимодействия с периферийными устройствами системы. Они имеют формат

IN аккумулятор, порт

OUT порт, аккумулятор

где аккумулятор – регистр AL при обмене байтами или регистр АХ при обмене словами. Операндом порт может быть десятичное значение от 0 до 255, что позволяет адресоваться к 256 устройствам.

В качестве операнда порт можно использовать регистр DX, что позволяет легко изменять номер порта, например при необходимости пересылать одни и те же данные в несколько различных портов.

Приведем несколько примеров команд IN и OUT:

IN AL,200             ;Ввести байт из порта 200

IN AL,PORT_VAL        ; или из порта, указанного константой

OUT ЗОН,AХ              ; Вывести слово в порт ЗОН

OUT DX,AX               ; или в порт, указанный в ОХ

Команды пересылки адреса

Команды пересылки адреса передают не содержимое переменных, а их адреса.

Команда загрузки исполнительного адреса

Команда LEA (load effective address — загрузить исполнительный адрес) пересылает смещение ячейки памяти в любой 16-битовый регистр общего назначения, регистр указателя или индексный регистр. Она имеет формат

LEA регистр16,память16

где операнд память16 должен иметь атрибут типа WORD.

Операнд память16 в команде LEA может быть индексирован, что дает возможность осуществить гибкую адресацию. Например, если регистр DI содержит 5, то команда

LEA  BX,TABLE[DI]

загрузит смещение адреса TABLE+5 в регистр ВХ.

Команда загрузки указателя и регистра сегмента данных LDS

Команда LDS (load pointer using DS — загрузить указатель с использованием регистра DS) считывает из памяти 32-битовое двойное слово и. загружает первые 16 битов в заданный регистр, а следующие 16 битов - в регистр сегмента данных DS. Она имеет формат

LDS регистр16,память32

где регистр 16 - любой 16-битовый регистр общего назначения, а память32 — ячейка памяти с атрибутом типа DOUBLEWORD.

Команда загрузки указателя и регистра дополнительного сегмента LES

Команда LES (load pointer using ES - загрузить указатель с использованием регистра ES) идентична команде LDS, но загружает номер блока в регистр ES, а не в DS.

Команды помещения флагов в стек PUSHF и извлечения флагов из стека POPF

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

Как и в случае команд PUSH и POP, команды PUSHF и POPF всегда используются парами. Другими словами, каждой команде PUSHF должна соответствовать исполняемая позже команда POP.


Индивидуальное задание.

1. Объявить массив заданного размера и с заданным количеством элементов (табл. 1).

2. Проинициализировать массив 0, используя произвольный метод адресации.

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

4. Вычислить сумму элементов массива согласно варианту и переслать результат в элемент массива с заданным номером (табл.3 выполнять в лабораторной № 3).

5. Вычислить произведение элементов с заданием согласно варианту и результат поместить в элемент с заданным номером (для вариантов с 32-битными числами берутся младшие части элементов) (табл.4 выполнять в лабораторной № 4).

Таблица 1.

1-я цифра варианта

Массив

Число

Количество элементов

Размер

Знак*

1

16

-

1878h

11

2

8

+

02h

14

3

32

+

12223278h

17

4

8

+

05h

17

5

16

-

1912h

12

6

32

+

11236897h

18

7

8

+

12h

13

8

8

+

19h

12

9

16

-

0813h

17

10

8

+

08h

25

11

16

-

1461h

13

12

32

-

03389769h

15

13

8

+

18h

19

14

16

-

0511h

11

15

32

+

13458799h

14

Примечание: (+) со знаком

 (-) без знака

Таблица 2

2-ая цифра варианта

Вид адресации

0

Непосредственная

1

По база

2

Косвенная регистровая

3

Регистровая

4

По базе

5

Косвенная регистровая

6

По базе с индексированием

7

Непосредственная

8

По базе

9

Косвенная регистровая \

Таблица 3

3-я цифра варианта

Элементы массива

результат в эл-т №

с

до

0

1

3

8

1

2

5

7

2

3

5

4

3

5

9

4

4

6

11

10

5

3

10

5

6

7

10

6

7

2

11

8

8

4

9

1

9

4

7

3

Таблица 4

4-я цифра варианта

Множимое

Множитель

Результат

Старшая часть

Младшая часть

0

1

3

2*

5

1

2

7

 1*

3

2

6

4

3*

2

3

3

2

7*

10

4

3

2

7*

10

5

5

5

9*

8

6

6

1

2*

8

7

8

2

4*

5

8

2

5

5*

11

9

3

5

8*

1

 

Содержание отчета:

  1.  Название работы
  2.  Цель работы
  3.  Приборы и оборудование
  4.  Краткие теоретические сведения
  5.  Индивидуальное задание
  6.  Распечатанный текст программы
  7.  Выводы.

Вопросы к защите лабораторной работы.

  1.  Режимы адресации МП 8086
  2.  Команды пересылки данных общего назначения
  3.  Команды пересылки адреса


Лабораторная работа №3

«Изучение команд сложения и вычитания»

Цель работы: изучить форматы и правила работы с командами сложения и вычитания микропроцессора i8086.

Оборудование: IBM - совместимый персональный компьютер, работающий под управлением операционной системы, совместимой с MS-DOS®.

Программное обеспечение: Программа DEBUG.

Краткие теоретические сведения.

  1.  Форматы арифметических данных
  2.  Команды сложения
  3.  Команды вычитания
  4.  Команда обращения знака
  5.  Команды расширения знака

Форматы арифметических данных.

Двоичные числа могут иметь 8 или 16 битов и могут быть со знаком или без знака. У числа без знака все 8 или 16 битов представляют его значение. Следовательно, двоичные числа без знака могут принимать значения от 0 до 255 (8-битовые) или до 65535 (16-битовые). У числа со знаком старший бит (7 или 15) указывает его знак, а остальные биты содержат значение числа. Следовательно, числа со знаком могут принимать значения от -128 до 127 (8-битовые) или от -32768 до 32767 (16-битовые).

Десятичные числа

Микропроцессор 8x86 хранит десятичные числа в виде последовательностей байтов без знака в упакованном или неупакованном формате. Каждый байт упакованного десятичного числа содержит две цифры а двоично-десятичном коде BCD (binary-coded decimal). При этом код старшей цифры числа занимает четыре старших бита байта. Следовательно, один упакованный десятичный байт может содержать значения от 00 до 99.

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

Как же микропроцессор 8x86 узнает, с каким видом данных он имеет дело? Пусть требуется сложить два байта. Как он определяет, какие числа они представляют (двоичные числа со знаком, двоичные числа без знака, упакованные десятичные числа или неупакованные десятичные числа)? На самом деле микропроцессор 8x86 об этом совершенно не заботится и трактует все операнды только как двоичные числа.

Это хорошо в том случае, когда Ваши операнды и в самом деле являются двоичными числами, но если они оказались десятичными, то результаты, конечно, будут ошибочными. Для компенсации таких ошибок микропроцессор 8x86 имеет группу команд коррекции, которые обеспечивают получение правильного результата после выполнения операций над десятичными числами. Эти команды будут обсуждаться далее.

Хранение чисел в памяти

Как уже упоминалось, микропроцессор 8x86 хранит 16-битовые числа в порядке, противоположном естественному представлению, а именно он хранит младшие биты числа в байте с меньшим адресом. Например, при запоминании числа 1234Н в ячейке по имени NUM он размещает 34Н по адресу NUM, a 12H — по адресу NUM+1. При чтении изображения (или дампа) содержимого памяти учитывайте эту схему свертки байтов. Запомните фразу: "младший байт — младший адрес, старший байт — старший адрес".

Команды сложения.

Команда сложения ADD и команда сложения с добавлением переноса ADC.

Команды ADD (add - сложить) и ADC (add with carry - сложить с переносом) могут складывать как 8-, так и 16-битовые операнды. Команда ADD складывает содержимое операнда-источника и операнда-приемника и помещает результат в операнд-приемник. В символической нотации ее действия можно описать как

приемник = приемник + источник

Команда ADC делает то же, что и команда ADD, но при сложении использует также флаг переноса CF, что можно записать следующим образом:

приемник = приемник + источник + перенос

Перенос при сложении двоичных чисел аналогичен переносу при сложении десятичных чисел в столбик. Например, пои сложении

 98

+ 13

 79

190

возникает два переноса: сложение единиц вызывает добавление 2 к десяткам, а сложение десятков и перенос из столбца единиц вызывает другой перенос, а именно числа 1 в столбец сотен. Перенос возникает тогда, когда сумма цифр столбца в нем не помещается.

Аналогичным образом возникает перенос, когда ЭВМ складывает двоичные числа: если сумма не помещается в операнде-приемнике, то генерируется перенос. Как известно, 8-битовый регистр может содержать значения без знака в диапазоне от 0 до 255. Если мы, например, выполним двоичное сложение чисел 250 и 10, то получим

 1111 1010   (двоичное представление числа 250)

+ 0000 1010   (двоичное представление числа 10)

1 0000 01000 (ответ: десятичное значение 260)

Результат верен, но занимает 9 двоичных битов! Если при выполнении этой операции мы использовали 8-битовые регистры, то младшие 8 битов будут занесены в регистр-приемник, а девятый бит - во флаг переноса CF.

Теперь Вам нетрудно понять, почему микропроцессор 8x86 имеет две разные команды сложения. Одна из них (ADD) может складывать значения, представляемые байтами или словами, а также младшие части значений повышенной точности. Другая команда (ADC) используется для сложения старших частей значений повышенной точности.

Например, команда

ADD AX,CX

складывает 16-битовые значения регистров АХ и СХ и возвращает результат в регистр АХ. Если Ваши операнды имеют длину более 16 битов, то можно воспользоваться последовательностью команд вида

ADD АХ,СХ     ; Сначала сложить младшие 16 битов, а затем

ADC BX,DX     ; старшие 16 битов

которая складывает 32-битовое число, находящееся в регистрах СХ и DX, с 32-битовым числом, находящимся в регистрах АХ и ВХ. Использованная здесь команда ADC добавляет к (DX)+(BX) любой перенос от сложения (СХ)+(АХ).

Вы можете также добавлять находящийся в памяти операнд к регистру и наоборот или добавлять непосредственный операнд к регистру или операнду, находящемуся в памяти. Приведем несколько примеров:

ADD AX,MEM_WORD   ;Добавить значение ячейки памяти к регистру

ADD MEM_WORD,AX   ;или наоборот

ADD АL,10    ;Добавить константу к регистру

ADD MEM_BYTE,OFH   ;или к ячейке памяти

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

Команды ADD и ADC могут воздействовать на шесть флагов:

Флаг переноса CF равен 1, если результат сложения не помещается в операнде-приемнике; в противном случае он равен 0.

Флаг четности PF равен 1, если результат имеет четное число битов со значением 1; в противном случае он равен 0.

Вспомогательный флаг переноса AF равен 1, если результат сложения десятичных чисел требует коррекции; в противном случае он равен 0.

Флаг нуля ZF равен 1, если результат равен 0; в противном случае он равен 0.

Флаг знака SF равен 1, если результат отрицателен (старший бит равен 1); в противном случае он равен 0.

Флаг переполнения OF равен 1, если сложение двух чисел одного знака (оба положительные или оба отрицательные) приводит к результату, который превышает диапазон допустимых значений приемника в обратном коде, а сам приемник при этом меняет знак. В противном случае флаг OF равен 0.

Флаги SF и OF имеют смысл только при сложении чисел со знаком, а флаг AF -только при сложении десятичных чисел.

Микропроцессор 8x86 имеет команды, которые проверяют флаги и на основе результатов проверки принимают решение о том, куда передать управление. Например, при отрицательном результате (SF=1) должна исполняться одна группа команд, а при положительном (SF=0) — другая. Эти команды "принятия решения" будут обсуждаться ниже.

Коррекция результата сложения для представления в кодах ASCII и в упакованном десятичном формате (команды AAA и DAA).

Как уже упоминалось, при выполнении сложения микропроцессор 8x86 рассматривает операнды как двоичные числа. Что же произойдет, если они будут двоично-десятичными кодами чисел (кратко десятичными или BCD-числами)? Разберемся в этом на примере. При сложении упакованных BCD-чисел 26 и 55 микропроцессор 8x86 выполнит следующее двоичное сложение:

    00100110 (BCD-число 26)

   +01010101 (BCD-число 55)

    01111011 (??)

Вместо правильного значения (BCD-число 81) мы получим результат, у которого старшая цифра 7, а младшая - шестнадцатеричная цифра В. Означает ли это, что нельзя складывать десятичные числа? Нет, это означает лишь то, что результат должен быть скорректирован для представления в десятичной форме.

Коррекция результата сложения десятичных чисел осуществляется командами ААА (ASCII adjust for addition - скорректировать результат сложения для представления в кодах ASCII) и DAA (Decimal adjust for addition - скорректировать сложение для представления в десятичной форме). В них не требуется наличия операнда: предполагается, что корректируемое значение находится в регистре AL.

Команда ААА преобразует содержимое регистра AL в правильную неупакованную десятичную цифру в младших четырех битах регистра AL (и заполняет нулями старшие четыре бита). Она используется в следующем контексте:

ADD AL,BL    ;Сложить неупакованные числа, находящиеся в AL и BL 

ААА                ; и преобразовать результат в неупакованное число

Если результат превышает 9, то команда ААА добавляет 1 к содержимому регистра АН (чтобы учесть избыточную цифру) и полагает флаг CF равным 1; в противном случае она обнуляет флаг CF. Кроме того, команда ААА изменяет состояние флага AF и оставляет значения флагов PF, ZF, SF и OF неопределенными. Но так как в данном случае только флаг CF имеет смысл, то считайте значения остальных флагов уничтоженными.

Команда DAA преобразует содержимое регистра AL в две правильные упакованные десятичные цифры. Она используется в следующем контексте:

ADD AL,BL       ;Сложить упакованные BCD-числа в AL и BL

DAA                    ; и преобразовать результат в упакованное число

Если результат превышает предельное значение для упакованных BCD-чисел (99), то команда DAA добавляет 1 к содержимому регистра АН и полагает флаг CF равным 1. Кроме того, команда DAA изменяет состояния флагов PF, AF, ZF и CF и оставляет значение флага OF неопределенным. Но так как в данном случае только флаг CF имеет смысл, то считайте остальные пять флагов уничтоженными.

Команда приращения значения приемника на единицу

Команда INC (increment - прирастить) добавляет 1 к содержимому регистра или ячейки памяти, но в отличие от команды ADD не воздействует на флаг переноса CF. Команда INC удобна для приращения значений счетчиков в циклах команд. Ее можно использовать и для приращения значения индексного регистра или указателя при доступе к последовательно расположенным ячейкам памяти.

Приведем несколько примеров:

INC CX         ;Прирастить значение 16-битового

INC AL              ;или 8-битового регистра

INC MEM_ВYТЕ       ;Прирастить значение байта

INC MEM_WORD[BX]  ;или слова памяти

Как ни странно, приращение значения 8-битового регистра отнимает у микропроцессора 8x86 больше времени, чем приращение значения 16-битового регистра. Это вызвано тем, что разработчики фирмы Intel предполагали, что программисты будут чаще пользоваться счетчиками размером в слово, а не байт, и предусмотрели специальную однобайтовую версию команды INC для 16-битовых регистров.

Команды вычитания. Выполнение вычитания микропроцессором 8086.

Внутри микропроцессора 8x86, как и любого другого микропроцессора общего назначения, нет устройства вычитания. Однако он имеет устройство сложения (сумматор) и может вычитать числа путем сложения. Хотя это и может показаться странным, тем не менее это концепция, как сказал бы Шерлок Холмс, "элементарна".

Чтобы понять, как можно вычитать путем сложения, посмотрим, как вычесть 7 из 10. В начальной школе учат записывать это как

10-7,

но в старших классах (скажем, в курсе алгебры) учат и другому способу записи:

10+(-7).

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

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

Применяя это к нашему примеру, получаем 8-битовые представления чисел 10 и 7: 00001010В и 00000111В соответственно. Затем дополним двоичное представление 7 до двух:

1111 1000 (обратить все биты)

 +_____1 (добавить 1)

 1111 1001 (дополнение до двух числа 7, или - 7).

Теперь операция вычитания примет следующий вид:

    0000 1010 (10)

   +1111 1001 (-7)

    0000 0011 (Ответ: 3)

Эврика! Мы получили правильный ответ!

Так как микропроцессор 8x86 выполняет дополнение до двух автоматически, то Вам эта операция понадобится в редких случаях. Позже в этом разделе мы рассмотрим команду NEG, посредством которой можно выполнить дополнение до двух, если оно когда-либо Вам понадобится.

Команда вычитания SUB и вычитания с заемом SBB.

Команды SUB (substract - вычесть) и SBB (substract with borrow - вычесть с заемом) аналогичны соответственно командам сложения ADD и ADC, только при вычитании флаг переноса CF действует как признак заема. Команда SUB вычитает операнд-источник из операнда-приемника и возвращает результат в операнд-приемник, т.е.

приемник = приемник — источник

Команда SBB делает то же самое, но дополнительно вычитает значение флага переноса CF:

приемник = приемник - источник - перенос

Как и в случае сложения, команды вычитания выполняют две отдельные функции. Первая команда SUB вычитает числа размером в байт или слово, а также младшие биты чисел повышенной точности. Другая команда SBB вычитает старшие биты чисел повышенной точности. Например, команда

SUB AХ,СХ

вычитает содержимое регистра СХ из содержимого регистра АХ и возвращает результат в регистр АХ.

Если размеры операндов превышают 16 битов, то пользуйтесь последовательностью команд вида

SUB AX,BX    ;Вычесть младшие 16 битов,

SBB BX,DX    ; а затем — старшие 16 битов

Здесь мы вычитаем 32-битовое число, помещенное в регистры СХ и DX, из 32-битового числа, помещенного в регистры АХ и ВХ. При вычитании содержимого регистра DX из содержимого регистра ВХ команда SBB учитывает возможность заема при выполнении первого вычитания.

Можно вычитать из содержимого регистра содержимое ячейки памяти (и наоборот) или вычитать из содержимого регистра либо ячейки памяти непосредственное значение. Ниже приведены примеры допустимых команд:

SUB AХ,MEM_WORD      ; Вычесть из регистра содержимое ячейки памяти

SUB MEM_WORD[BX],AХ   ; или наоборот

SUB AL,10              ; Вычесть константу из регистра

SUB MEM_BYTE,OFH      ; или из ячейки памяти

Нельзя непосредственно вычесть значение одной ячейки из другой или использовать непосредственное значение как приемник.

Команды SUB и SBB могут воздействовать на шесть флагов следующим образом:

Флаг переноса CF равен 1, если требуется заем; в противном случае он равен 0.

Флаг четности PF равен 1, если результат вычитания имеет четное число битов со значением 1; в противном случае он равен 0.

Вспомогательный флаг переноса AF равен 1, если результат вычитания десятичных чисел требует коррекции; в противном случае он равен 0.

Флаг нуля ZF равен 1, если результат равен 0; в противном случае он равен 0.

Флаг знака SF равен 1, если результат отрицателен (старший бит равен 1); в противном случае он равен 0.

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

Флаги SF и OF имеют смысл только при вычитании чисел со знаком, а флаг AF – только при вычитании десятичных чисел.

 Коррекция результата вычитания для представления в кодах ASCII и в упакованном десятичном формате (команды AAS и DAS).

При вычитании, как и при сложении, микропроцессор 8x86 рассматривает операнды как двоичные числа. Поэтому вычитание чисел, представленных в двоично-десятичном коде (BCD-чисел), может привести к неправильным результатам. Предположим, например, что надо вычесть BCD-число 26 из BCD-числа 55. Микропроцессор 8x86 выполнит двоичное вычитание следующим образом: дополнит до двух двоично-десятичное представление числа 26, а затем выполнит сложение:

   0101 0101 (BCD-число 55)

+ 1101 1010 (дополнение до двух BCD-числа 26)

 1 0010 1111 (??).

Вместо правильного значения (BCD-числа 29) мы получили результат, у которого старшая цифра 2, младшая цифра - шестнадцатеричная цифра F, и при этом бит переноса равен 1. Конечно, этот результат требует коррекции.

Коррекция результата вычитания двух десятичных чисел осуществляется командами AAS (ASCII adjust for substraction - скорректировать вычитание для представления в кодах ASCII) и DAS (Decimal adjust for substraction - скорректировать вычитание для представления в десятичной форме). При их исполнении предполагается, что корректируемое число находится в регистре AL.

Команда AAS преобразует содержимое регистра AL в правильную неупакованную десятичную цифру в младших четырех битах регистра AL (и обнуляет старшие четыре бита). Она используется в следующем контексте:

SUB AL,BL    ; Вычесть BCD-число (содержимое BL) из AL 

AAS          ; и преобразовать результат в неупакованное число

Если результат превышает 9, то команда AAS вычитает 1 из содержимого регистра АН и полагает флаг CF равным 1, в противном случае она обнуляет флаг CF. Кроме того, команда AAS изменяет состояние флага AF и оставляет значения флагов PF, ZF, SF и OF неопределенными. Но так как в данном случае только флаг CF имеет смысл, то считайте значения остальных флагов уничтоженными.

Команда DAS преобразует содержимое регистра AL в две правильные упакованные десятичные цифры. Она используется в следующем контексте:

SUB AL,BL     ;Вычесть упакованное BCD-число(содержимое) BL из AL

DAS           ; и преобразовать результат в упакованное число

Если результат превышает предельное значение для упакованных BCD-чисел (99), то команда DAS вычитает 1 из содержимого регистра АН и полагает флаг CF равным 1; в противном случае она обнуляет флаг CF. Кроме того, команда DAS изменяет состояния флагов PF, AF, ZF и SF, а значение флага OF оставляет неопределенным. Но так как в данном случае только флаг CF имеет смысл, то считайте остальные упомянутые флаги уничтоженными.

Команда уменьшения содержимого приемника на единицу DEC

Команда DEC (decrement - уменьшить) вычитает 1 из содержимого регистра или ячейки памяти, но при этом (в отличие от команды SUB) не воздействует на флаг переноса CF. Команда DEC часто используется в циклах для уменьшения значения счетчика до тех пор, пока оно не станет нулевым или отрицательным. Ее можно использовать также для уменьшения значения индексного регистpa или указателя при доступе к последовательно расположенным ячейкам памяти.

Приведем несколько примеров:

DEC CX              ;Уменьшить знамение 16-битового

DEC AL              ; или 8-битового регистра

DEC MEM_BYTE        ;Уменьшить значение байта

DEC MEM_WORD[BX]    ;или слова памяти

Команда обращения знака NEG.

Команда NEG вычитает значение операнда-приемника из нулевого значения и тем самым формирует его дополнение до двух. Команда NEG оказывает на флаг то же действие, что и команда SUB. Но поскольку один из операндов равен 0, то можно точнее описать условия изменения состояний флагов. Итак, при исполнении команды NEG флаги изменяются следующим образом:

Флаг переноса CF и флаг знака SF равны 1, если операнд представляет собой ненулевое положительное число; в противном случае они равны 0.

Флаг четности PF равен 1, если результат имеет четное число битов, равных 1; в противном случае он равен 0.

Флаг нуля ZF равен 1, если операнд равен 0; в противном случае он равен 0.

Флаг переполнения OF равен 1, если операнд-байт имеет значение 80Н или операнд-слово имеет значение 8000Н; в противном случае он равен 0.

Команда NEG полезна для вычитания значения регистра или ячейки памяти из непосредственного значения. Например, Вам нужно вычесть значение регистра AL из 100. Так как непосредственное значение не может служить приемником, то команда SUB 100, AL недопустима. В качестве альтернативы можно обратить знак содержимого регистра AL и добавить к нему 100:

NEG AL 

ADD AL,100

Команда расширения знака.

Существуют две команды, позволяющие выполнять операции над смешанными данными за счет удвоения размера операнда со знаком. Команда CBW (convert byte to word — преобразовать байт в слово) воспроизводит 7-й бит регистра AL во всех битах регистра AH.

Команда CWD (convert word to double word — преобразовать слово в двойное слово) воспроизводит 15-й бит регистра AX во всех битах регистра DX.

Таким образом, команда CBW позволяет сложить байт и слово, вычесть слово из байта и т. д. Аналогично, команда CWD позволяет разделить слово на слово.

Приведем несколько примеров:

CBW   ;Сложить байт в AL со словом в BX

ADD AX,BX

CBW   ;Умножить байт в AL на слово в BX

IMUL BX

CWD   ;Разделить слово в AX на слово в BX

IDIV BX

Индивидуальное задание.

1 Вычислить сумму элементов массива согласно варианту и переслать результат в элемент массива с заданным номером (табл.3  Лабораторная работа №2).

2. Каждому студенту выдается 4-х значный вариант. Согласно этого варианта вычислить следующее выражение:

 F = КОН1 оп1 (КОН2 оп2 Х оп3 Y) оп4 Z оп5 КОН3

где

    КОН1, КОН2, КОН3 – числовые константы, согласно табл. 1

 оп1, оп2, оп3, оп4, оп5 – операции сложения и вычитания согласно табл. 2

 X, Y – переменные, тип которых определяется согласно табл. 3

Числовые константы из табл. 1 берутся согласно первой цифре варианта, операции сложения и вычитания из табл. 2 – согласно второй цифре варианта, а размер и тип переменных – из табл. 3 согласно третьей цифре варианта.

Исходные данные хранятся в памяти с адреса 0900H, вычисление выражения производится на Ассемблере, выводимые результаты — располагаются в памяти с адреса 1000Н.

Таблица 1.

Первая цифра варианта

0

1

2

3

4

5

6

7

8

9

КОН1

12

12569

87935

12

78

4596

12597563

4589

369

458

КОН2

1369

12

588

96385

47

589

78

29

3856

481

КОН3

3699

4589

12

3698

4589632

2385

2852

562235

336

36

Таблица 2.

Вторая цифра варианта

0

1

2

3

4

5

6

7

8

9

оп1

    +

    —

   —

   +

 

     +

    +

    +

    —

    —

    —

оп2

    +

   +

   +

   —

 

     —

    +

    —

    —

    +

    +

оп3

    —

    +

   —

   —

 

     +

    —

    +

    +

    —

    +

оп4

    +

    +

   —

   —

 

     +

    —

    —

    +

    +

    +

оп5

    —

    +

   +

   +

 

     —

    +

    +

    +

    +

    —

Таблица 3.

Третья цифра варианта

0

1

2

3

4

5

6

7

8

9

X

Char

un char

   int

un int

int

un long

 int

char

char

un long

   Y

 Int

un int

  long

un char

long

un int

int

long

char

un char

Z

Char

un long

   int

un int

char

un char

char

char

long

un int

Примечания:  – char   – 8 битн. со знаком

– un. char  – 8 битн. без знака

  – int   – 16 битн. со знаком

un. int  – 16 битн. без знака

  – long   – 32 битн. со знаком

un. long  – 32 битн. без знака

Пример. У студента индивидуальный вариант 990. Строим индивидуальное выражение для вычисления:   F=458 – (481 + X + Y) + Z — 36

Согласно варианту переменные X, Y и Z должны быть описаны следующим образом

 char x, z;

 int y,f;

 Ассемблерный фрагмент выглядит следующим образом:

 mov bx, 481h  // Пересылаем константу в регистр AX

 mov al,x  

 cbw   // Расширяем число X до 16 бит

 add bx,ax  // 481h + X

 add bx, y  // 481h + X + Y

mov al,z

 cbw   // Расширяем число Z до 16 бит

 add bx,ax  // (481h + X + Y) +Z

 sub bx,36h // (481h + X + Y) +Z - 36h

mov cx, 458h

  sub cx, ax

 mov f,cx

Содержание отчета:

  1.  Название работы
  2.  Цель работы
  3.  Приборы и оборудование
  4.  Краткие теоретические сведения
  5.  Индивидуальное задание
  6.  Распечатанный текст программы
  7.  Выводы.

Вопросы к защите лабораторной работы.

  1.  Форматы арифметических данных.
  2.  Формат и правила применения команд ADD и ADC.
  3.  Воздействие на флаги команд ADD и ADC.
  4.  Формат и правила применения команд SUB и SBB.
  5.  Воздействие на флаги команд SUB и SBB.
  6.  Команды обращения знака.
  7.  Команды расширения знака.


Лабораторная работа №4

«Изучение команд умножения и деления»

Цель работы: изучить форматы и правила работы с командами умножения и деления микропроцессора i8086.

Оборудование: IBM - совместимый персональный компьютер, работающий под управлением операционной системы, совместимой с MS-DOS®.

Программное обеспечение: Программа DEBUG.

Краткие теоретические сведения.

  1.  Команды умножения
  2.  Команды деления

Команды умножения чисел без знака MUL и целого умножения чисел со знаком IMUL.

Если Вам когда-либо приходилось терпеть муки составления программы умножения для микропроцессоров Z80, 6502 или для каких-либо других распространенных 8-битовых микропроцессоров, то Вы будете рады узнать, что микропроцессор 8x86 имеет встроенные команды умножения. Команда MUL (multiply – умножить) умножает числа без знака, a IMUL (integer multiply – умножить целые числа) – числа со знаком. Обе команды могут умножать как байты, так и слова.

Эти команды имеют формат:

MUL источник

IMUL источник

где источник - регистр общего назначения или ячейка памяти размером в байт или слово. В качестве второго операнда команды MUL и IMUL используют содержимое регистра AL (при операциях над байтами) или регистра АХ (при операциях над словами). Произведение имеет двойной размер и возвращается следующим образом:

Умножение байтов возвращает 16-битовое произведение в регистрах АН (старший байт) и AL (младший байт).

Умножение слов возвращает 32-битовое произведение в регистрах DX (старшее слово) и АХ (младшее слово).

По завершении исполнения этих команд флаги переноса CF и переполнения OF показывают, какая часть произведения существенна для последующих операций. После исполнения команды MUL флаги CF и OF равны 0, если старшая половина произведения равна 0; в противном случае оба этих флага равны 1. После исполнения команды IMUL флаги CF и OF равны 0, если старшая половина произведения представляет собой лишь расширение знака младшей половины. В противном случае они равны 1.

Приведем несколько примеров умножения:

MUL ВХ          ;Умножить ВХ на АХ без знака

MUL MEM_BYTE.   ;Умножить содержимое ячейки памяти на AL без знака

IMUL DL         ;Умножить DL на AL со знаком

IMUL MEM WORD   ;Умножить содержимое ячейки памяти на АХ со знакам

Команды MUL и IMUL не ^позволяют в качестве операнда использовать непосредственное значение. Такое значение-перед умножением надо. загрузить в регистр или в ячейку памяти. Например, в результате исполнения команд

MOV  DX,10

MUL  DX

содержимое регистра АХ будет умножено на 10.

Коррекция результатов умножения  для представления в кодах ASCII (команда AAM)

Команда ААМ (ASCII adjust for multiplication - скорректировать умножение для представления в кодах ASCII) преобразует результат предшествующего умножения байтов в два правильных неупакованных десятичных операнда. Она считает, что произведение двойного размера находится в регистрах АН и AL, и возвращает неупакованные операнды в регистрах АН и AL. Чтобы команда ААМ работала правильно, исходные множимое и множитель должны быть правильными неупакованными байтами.

Для выполнения преобразования команда ААМ делит значение регистра AL на 10 и запоминает частное и остаток в регистрах АН и AL соответственно. Кроме того, она модифицирует флаг четности. PF, флаг нуля ZF и флаг знака SF в зависимости от полученного значения регистра AL. Состояние флага переноса CF, вспомогательного флага AF и флага переполнения становятся неопределенными.

Рассмотрим действие команды 'ААМ на примере. Пусть регистр AL содержит 9 (0000 1001В), а регистр BL — 7 (0000 0111В). Команда

MUL BL

умножит значение регистра AL на значение регистра BL и возвратит 16-битовый результат в регистрах АН и AL. В нашем случае она возвратит 0 в регистре АН и 00111111В (десятичное 63) в регистре AL. Следующая за ней команда

AAM

поделит значение регистра AL на 10 и возвратит частное 0000 0110В в регистре АН, а остаток 0000 0011В в регистре AL. Тем самым мы получаем правильный результат: BCD-число 63 в неупакованном формате. У микропроцессора 8x86 нет команды умножения упакованных десятичных чисел. Для выполнения этой операции сначала распакуйте эти числа, перемножьте их и воспользуйтесь командой ААМ, а затем упакуйте результат.

Команда деления числа без знака DIV и деления числа со знаком IDIV

Имея две отдельные команды умножения, микропроцессор 8x86 имеет и две отдельные команды деления. Команда DIV (divide - разделить) выполняет деление чисел без знака, а команда IDIV (integer divide - разделить целые числа) выполняет деление чисел со знаком. Эти команды имеют формат

DIV источник

IDIV источник

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

Если операнд-источник представляет собой байт, то частное возвращается в регистре AL, а остаток в регистре АН.

Если операнд-источник представляет собой слово, то частное возвращается в регистре АХ, а остаток - в регистре DX.

Обе команды оставляют состояние флагов неопределенными, но если частное не помещается в регистре-приемнике (AL или АХ), то микропроцессор 8x86 сообщает Вам об этом весьма драматическим образом: он генерирует прерывание типа 0 (деление на 0).

Переполнение результата деления возникает при следующих условиях:

1. Делитель равен 0.

2. При делении байтов без знака делимое по меньшей мере в 256 раз превышает делитель.

3. При делении слов без знака делимое по меньшей мере в 65 536 раз превышает делитель.

4. При делении байтов со знаком частное лежит вне диапазона от -128 до +127.

5. При делении слов со знаком частное лежит вне диапазона от -32768 до 32767. Приведем несколько типичных примеров операций деления:

DIV BX           ;Разделить DX:AX на ВХ , без знака

DIV MEM_BYTE     ;Разделить AH:AL на байт памяти, без знака

IDIV DL          ;Разделить АН:AL на DL со знаком

IDIV MEM_WORD    ;Разделить DX:AX на слово памяти, со знаком

Команды DIV и IDIV не позволяют прямо разделить на непосредственное значение; его надо предварительно загрузить в регистр или ячейку памяти. Например, команды

MOV  ВХ,20

DIV  ВХ

разделят объединенное содержимое регистров DX и АХ на 20.

Команда коррекции деления для представления в кодах ASCII (команда AAO )

Все ранее описанные команды десятичной коррекции (ААА, DAA, AAS, DAS и ААМ) выполняли действия над результатом операции. В противоположность им команда AAD (ASCII adjust for division - скорректировать деление для представления в кодах ASCII) должна исполняться непосредственно перед операцией деления.

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

Приведем типичный пример применения команды AAD:

AAD            ; Скорректировать неупакованное делимое в АН:АL,

DIV BL         ; а затем выполнить деление


Индивидуальное задание.

  1.  Вычислить произведение элементов с заданием согласно варианту и результат поместить в элемент с заданным номером (для вариантов с 32-битными числами берутся младшие части элементов) (табл.4 из лабораторной № 2).

2. Каждому студенту выдается 4-х значный вариант.  Согласно этого варианта вычислить следующее выражение:

 F = (КОН1 оп1 КОН2) оп2 Х оп3 (Y оп4 КОН3)

где

    КОН1, КОН2, КОН3 – числовые константы, согласно табл. 1

 оп1, оп2, оп3, оп4 – операции сложения, вычитания, умножения и деления согласно табл. 2

 X, Y – переменные, тип которых определяется согласно табл. 3

Числовые константы из табл. 1 берутся согласно первой цифре варианта, операции сложения и вычитания из табл. 2 – согласно второй цифре варианта, а размер и тип переменных – из табл. 3 согласно третьей цифре варианта.

Таблица 1.

Первая цифра варианта

0

1

2

3

4

5

6

7

8

9

КОН1

12

12569

8735

12

78

4596

12563

4589

369

458

КОН2

1369

12

588

96385

47

589

78

29

3856

481

КОН3

3699

4589

12

3698

4862

2385

2852

5625

336

36

Таблица 2.

Вторая цифра варианта

0

1

2

3

4

5

6

7

8

9

оп1

    /

    *

   —

   +

 

     *

    +

    —

    —

    /

    —

оп2

    *

   /

   *

   /

 

     —

    +

     /

    *

    +

    +

оп3

    +

    +

   /

   *

 

     +

    *

    +

    /

    —

    /

оп4

    —

    +

   —

   —

 

     /

    /

    *

    +

    *

    *

Таблица 3.

Третья цифра варианта

0

1

2

3

4

5

6

7

8

9

X

char

un char

   int

un int

int

un char

 int

char

char

un int

   Y

 int

un int

  char

un char

 int

un int

  int

 int

char

un char

Примечания:  – char   – 8 битн. со знаком

– un. char  – 8 битн. без знака

  – int   – 16 битн. со знаком

– un. int  – 16 битн. без знака

  

Пример. У студента индивидуальный вариант 990. Строим индивидуальное выражение для вычисления:

  F=(458 – 481) + X / (Y * 36)

Согласно варианту переменные X, Y и Z должны быть описаны следующим образом

 char x;

 int y;

Ассемблерный фрагмент выглядит следующим образом:

 mov bx, 458h  // Пересылаем константу в регистр AX

 sub bx, 481h  // Вычитаем константу

 mov ax,y

 mov cx,36h

 imul cx  // Пренебрегаем старшей частью 32-б рез-та

 mov cx,ax

 mov al,x  

 cbw   // Расширяем число X до 16 бит

 cwd   // расширяем x до 32 бит

 idiv cx  // результат в ax

 add bx,ax

 mov f,cx

Содержание отчета:

  1.  Название работы
  2.  Цель работы
  3.  Приборы и оборудование
  4.  Краткие теоретические сведения
  5.  Индивидуальное задание
  6.  Распечатанный текст программы
  7.  Выводы.

Вопросы к защите лабораторной работы.

  1.  Форматы арифметических данных.
  2.  Формат и правила применения команд MUL и IMUL.
  3.  Воздействие на флаги команд MUL и IMUL.
  4.  Формат и правила применения команд DIV и IDIV.
  5.  Воздействие на флаги команд DIV и IDIV.
  6.  Правила применения команд AAO и AAM.


Лабораторная работа №5

«Изучение команд манипулирования битами»

Цель работы: изучить форматы и правила работы с командами манипулирования битами микропроцессора i8086.

Оборудование: IBM - совместимый персональный компьютер, работающий под управлением операционной системы, совместимой с MS-DOS®.

Программное обеспечение: Программа DEBUG.

Краткие теоретические сведения.

  1.  Логические команды
  2.  Команды сдвига и циклического сдвига

Команды манипулирования битами.

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

Логические команды

Эти команды названы логическими потому, что они действуют по правилам формальной логики, а не арифметики. Например, логическое утверждение "если А истинно и В истинно, то С истинно" находит свое отражение в команде AND (и) микропроцессора 8x86, которая применяет его к соответствующим битам двух операндов.

Точнее говоря, команда AND полагает равным 1 все те биты операнда приемника, в позициях которых содержится 1 у обоих операндов. А в те биты приемника, в позициях которых содержится любая другая комбинация значении (или 00, или О и 1), полагаются равными нулю.

Так как логические операции манипулируют битами операндов, то обычно при записи значений таких операндов используют шестнадцатеричную систему счисления. Логические команды микропроцессора 8x86 могут оперировать байтами или словами, поэтому обычно приходится иметь дело с двузначными или четырехзначными шестнадцатеричными числами.

Логические команды OR, AND и XOR.

Операндами команд AND, OR и XOR могут быть байты или слова. В этих командах можно сочетать два регистра, регистр с ячейкой памяти или непосредственное значение с регистром или ячейкой памяти.

Команда AND маскирует (обнуляет) некоторые биты, после чего можно выполнить дальнейшую обработку остальных битов. Как уже упоминалось, в каждой позиции бита, где оба операнда содержат 1, операнд-приемник также будет содержать 1. В тех же позициях, где операнды имеют любую другую комбинацию значений, операнд-приемник будет содержать 0. Запомните, что при исполнении команды AND биты операнда-приемника становятся, равны 0 всюду, где операнд-источник содержит 0, и сохраняются там, где операнд-источник содержит 1.

Приведем несколько примеров команд AND:

AND АХ,ВХ             ;Выполнить AND над двумя регистрами

AND AL,MEM_BYTE     ;Выполнить AND над регистром и ячейкой памяти

AND MEM_BYTE        ; или наоборот

AND BL,1101В        ;Выполнить AND над константой и регистром

AND TABLE[BX],MASK3 ; или ячейкой памяти

Рассмотрим следующий пример применения команды AND. Пусть порт 200 соединен с 16-битовым регистром состояния внешнего устройства системы и бит 6 показывает, включено (1) или выключено (0) устройство. Если Ваша программа может продолжать работу только в случае, когда устройство включено, то она должна содержать следующий цикл:

CHK_PWR:   IN AХ,200         ;Прочитать состояние устройства

AND AX,1000000B   ;Изолировать индикатор включения

JZ CHK_PWR        ;Подождать включения питания, ...                ; а затем продолжить работу

Команда JZ (jump if zero - перейти если нуль), которая нами еще не рассматривалась, заставляет микропроцессор 8x86 вернуться к команде IN с меткой CHK_PWR, если флаг нуля ZF равен 1, и перейти к следующей команде в противном случае. В нашем примере флаг ZF равен 1 только в том случае, когда индикатор включения (бит 6) равен 1, так как команда AND обнуляет все остальные биты регистра АХ.

Команда OR полагает равным 1 те биты операнда-приемника, в позициях которых хотя бы один из операндов содержит 1. Эта команда обычно используется для принудительного присваивания 1 заданным битам. Например, команда

OR BX,OCOOH

полагает два старших бита (14 и 15) регистра ВХ равными 1 и оставляет другие биты не измененными.

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

Например, команда

XOR BX,0C000H

обращает состояния двух старших битов регистра ВХ (14 и 15) и сохраняет остальные биты неизмененными.

Команда логического отрицания NOT.

Команда NOT (HE) обращает состояние каждого бита регистра или ячейки памяти и ни на какие флаги не воздействует. Таким образом, команда NOT заменяет каждый 0 на 1, а каждую 1 – на 0. Другими словами, она выполняет для операнда дополнение до единицы.

Команда проверки TEST.

Команда TEST (test — проверить) выполняет операцию AND над операндами, но воздействует только на флаги и не изменяет значения операндов. Команда TEST изменяет флаги точно так же, как команда AND: она обнуляет флаги CF и OF, изменяет флаги PF, ZF и SF, а флаг AF оставляет неопределенным.

Когда вслед за командой TEST указана команда JNZ (jump if not zero - перейти, если не нуль), переход произойдет только в том случае, если хотя бы в одной позиции бита оба операнда содержат 1.

Команды сдвига и циклического сдвига

У микропроцессора 8x86 есть семь команд, осуществляющих сдвиг 8-или 16-битового содержимого регистров или ячеек памяти на одну или несколько позиций влево или вправо. Три из них сдвигают операнд, а остальные четыре его вращают или циклически сдвигают.

Для всех семи команд флаг переноса CF является как бы расширением операнда битом 9 или битом 17. Иначе говоря, флаг CF приобретает значение бита, сдвинутого за один из концов операнда. Команды сдвига и циклического сдвига вправо помещают во флаг CF значение нулевого бита. Команды сдвига и циклического сдвига влево помещают в него значение бита 7 (при операциях над байтом) или бита 15 (при операциях над словом).

Команды сдвига и циклического сдвига распадаются на две группы. Логические команды сдвигают операнд, не считаясь с его знаком; они используются для действий над числами без знака или над нечисловыми значениями, например над масками. Арифметические команды сохраняют старший, знаковый бит операнда; они используются для действий над числами со знаком. На рис. 1 показано действие этих команд.

Команды сдвига и циклического сдвига имеют два операнда: приемник и счетчик. Приемником может быть 8- или 16-битовый регистр общего назначения или ячейка памяти. Счетчик может быть цифрой 1 или значением без знака в регистре CL.

Рис. 1. Команды сдвига и циклического сдвига

Команды сдвига

Команды SAL (shift arithmetic left - сдвинуть влево арифметически) и SAR (shift arithmetic right - сдвинуть вправо арифметически) сдвигают числа со знаком. Команда SAR сохраняет знак операнда, репродуцируя его при выполнении сдвига. Команда SAL не сохраняет знак, но заносит 1 во флаг переполнения OF в случае изменения знака операнда. При каждом сдвиге операнда команда SAL заносит 0 в вакантный нулевой бит этого операнда.

Команды SHL (shift logical left - сдвинуть влево логически) и SHR (shift logical right - сдвинуть вправо логически) сдвигают числа без знака. Команда SHL идентична команде SAL. Команда SHR аналогична команде SHL, но сдвигает операнд не влево, а вправо. При каждом сдвиге операнда команда SHR заносит 0 в вакантный старший бит этого операнда (бит 7 при сдвиге байта, бит 15 при сдвиге слова).

Помимо флагов CF и OF команды сдвига изменяют флаги PF, ZF и SF, а флаг AF оставляют неопределенным.

Чтобы познакомиться с работой команд сдвига, предположим, что регистр AL содержит ОВ4Н, а флаг переноса CF равен 1. В двоичном коде

AL = 10110100 CF = 1

Команды сдвига воздействуют на регистр AL и флаг CF следующим образом:

После SAL AL,1 :

AL = 01101000 CF = 1

После SAR AL,1:

AL = 11011010 CF = О 

После SHL AL,1:  

AL = 01101000 CF = 1

После SHR AL,1:

AL = 01011010 CF = 0

Имеется несколько интересных приложений команд сдвига. Например, в следующем фрагменте команд команда SHL используется для преобразования двух неупакованных BCD-чисел (старшая цифра извлекается из регистра BL, младшая - из регистра AL) в упакованное BCD-число в регистре AL:

MOV CL,4    ;3агруэить счетчик сдвига в CL

SHL BL,CL   ;Сдвинуть старшую цитру в старшие четыре бита BL

OR  AL,BL   ;Получить упакованное BCD-число слиянием AL и BL

Поскольку сдвиг операнда на один бит влево удваивает значение операнда (умножает на 2), а сдвиг на один бит вправо уменьшает значение операнда вдвое (делит на 2), то команды сдвига можно использовать в качестве команд быстрого умножения и деления.

Следующие команды сдвига показывают, каким образом можно разделить на четыре содержимое регистра АХ. Во всех случаях предполагается, что регистр CL содержит 2.

SHL AX,CL    ;Умножить число без знака на 4

SAL AX,CL    ;Умножить число со знаком на 4

SHR AX,CL    ;Разделить число без знака на 4

SAR AX,CL    ;Разделить число со знаком на 4

Применяя команды сдвига вместо команд умножения и деления, можно сэкономить немало времени. Каждая из предыдущих команд сдвига выполняется за 16 тактов. Еще 4 такта требуется для загрузки значения в регистр CL, итого - 20 тактов. Сравнивая это время с минимальными временами исполнения команд MUL (118 тактов), IMUL (l28 тактов), DIV (144 такта) и IDIV (165 тактов), мы видим, что команды сдвига выполняют эти действия в шесть-восемь раз быстрее, чем команды умножения и деления!

В то время как отдельная команда сдвига может умножить или разделить только на степень числа 2, манипулирование несколькими регистрами позволяет выполнить умножение или деление на другие числа. Например, приведенная ниже последовательность команд умножает содержимое регистра АХ на 10:

MOV ВХ,10     ;Сохранить содержимое в ВХ

SHL АХ,1      ;Сдвинуть AХ  (умножить на 2)

SHL AХ,1      ;Сдвинуть AХ еще раз (умножить на 4)

ADD АХ,ВХ     ;Сложить с исходным, значением АХ (умножить на 5)

SHL АХ,1      ;Сдвинуть AХ еще раз (умножить на 10)

Хотя в этой последовательности пять команд, но выполняется она в 11 раз быстрее одной команды MUL!

Команды  циклического сдвига

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

При исполнении команды ROL (rotate left - сдвинуть влево циклически) и ROR (rotate right - сдвинуть вправо циклически) вышедший за пределы операнда бит входит в него с противоположного конца. При исполнении команд RCL (rotate left through carry - сдвинуть влево циклически вместе с флагом переноса) и RCR (rotate right through carry - сдвинуть вправо циклически вместе с флагом переноса) в противоположный конец операнда помещается значение флага переноса CF. Все команды циклического сдвига воздействуют только на флаги CF и OF.

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

AL  =  10110100    CF  =   1

Команды циклического сдвига воздействуют на регистр AL и флаг CF следующим образом:

После ROL AL,1:

AL = 01101001 CF = 1

После ROR AL,1:

AL = 01011010 CF = 0

После RCL AL,1:

AL = 01101001 CF = 1

После RCR AL,1:

AL = 11011010 CF = 0

Индивидуальное задание.

 Каждому студенту выдается 4-х значный вариант. Согласно этого варианта вычислить следующее выражение и определить, четное полученное число или нечетное и отрицательное оно или положительное:

F = Y оп1 КОН1 оп2 Х оп3 КОН2

КОН1, КОН2 – числовые константы, согласно табл. 1

оп1, оп2, оп3 – операции сложения, вычитания, умножения и деления согласно табл. 2

 X, Y – переменные, тип которых определяется согласно табл. 3

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

Числовые константы из табл. 1 берутся согласно первой цифре варианта, операции сложения и вычитания из табл. 2 – согласно второй цифре варианта, а размер и тип переменных – из табл. 3 согласно третьей цифре варианта.

Если размер результат будет более 16 бит – результат преобразовывать в 16-битный.

Таблица 1.

Первая цифра варианта

0

1

2

3

4

5

6

7

8

9

КОН1

10

96

 20

  12

130

24

 64

32

6

40

КОН2

32

16

 8

  4

  128

  64

  36

 22

  14

  72

Таблица 2.

Вторая цифра варианта

0

1

2

3

4

5

6

7

8

9

оп1

    /

    /

   *

   *

 

     /

   *

    —

    +

    /

    *

оп2

    –

   +

   –

   +

 

     %

    %

     *

    *

    +

    +

оп3

    *

    *

   /

   /

 

     *

    /

    /

    /

    –

    –

Таблица 3.

Третья цифра варианта

0

1

2

3

4

5

6

7

8

9

X

char

un char

   int

un int

int

un char

 int

char

char

un int

   Y

 int

un int

  char

un char

 int

un int

  int

 int

char

un char

Примечания:  – char   – 8 битн. со знаком

– un. char  – 8 битн. без знака

  – int   – 16 битн. со знаком

– un. int  – 16 битн. без знака

  

Пример. У студента индивидуальный вариант 990. Строим индивидуальное выражение для вычисления:   F = Y * 40 + X — 72

Согласно варианту переменные X и Y  должны быть описаны следующим образом

 char x;

 int y;

Программа выглядит следующим образом:

  ;y*40=y*32+y*8;

 ;  адрес у = 300, адрес x= 400

 ; Первоначально исходные данные заносятся на стартовые адреса памяти

 mov ax,[y]

  mov bx,ax

  mov cl,3

  shl ax,cl    ;y*8

  mov cl,5

  shl bx,cl   ; y*32

  add bx,ax

  mov al,[x]

  cbw         ;преобразуем 8-битное x в 16 битное

  add bx,ax   ;y*40+x

  sub bx,72   ;y*40+x-72

  mov f,bx

  ; проверяем на четность

  mov iChet,bx

  and iChet,0001h

  ; проверяем на знак

  mov iSign,bx

  and iSign,8000h

; результаты сохраняем с адесов Y=500, X=600 четность, 506 и 606 – знаковость

 Содержание отчета:

  1.  Название работы
  2.  Цель работы
  3.  Приборы и оборудование
  4.  Краткие теоретические сведения
  5.  Индивидуальное задание
  6.  Распечатанный текст программы
  7.  Выводы.

Вопросы к защите лабораторной работы.

  1.  Логические команды: формат и правила применения
  2.  Команды сдвига: формат и правила применения.
  3.  Команды циклического сдвига: формат и правила применения.

Лабораторная работа №6

«Создание простейших .СОМ и .ЕХЕ программ»

Цель работы: изучить форматы и правила работы транслятором ТАSM.

Оборудование: IBM - совместимый персональный компьютер, работающий под управлением операционной системы, совместимой с MS-DOS®.

Программное обеспечение: TASM4

Программа типа СОМ

Традиционно первая программа для освоения нового языка программирования — программа, выводящая на экран текст «Hello world!».

Итак, наберите в любом текстовом редакторе, который может записывать файлы как обычный текст (например: EDIT.COM в DOS, встроенный редактор в Norton Commander или аналогичной программе, NOTEPAD в Windows), следующий текст:

; hello-l.asm

; Выводит на экран сообщение "Hello World!" и завершается

       .model     tiny              ; модель памяти, используемая для СОМ

       .code                        ; начало сегмента кода

       org        100h              ; начальное значение счетчика - 100h

start:  mov        ah,9              ; номер функции DOS - в АН

       mov        dx,offset message ; адрес строки - в DX

       int        21h               ; вызов системной функции DOS

       ret                          ; завершение СОМ-программы

message db         "Hello World!",0Dh,0Ah,'$' ; строка для вывода

       end        start             ; конец программы

и сохраните его как файл hello-l.asm. Можно также использовать готовый файл с этим именем. Чтобы превратить программу в исполнимый файл, сначала надо вызвать ассемблер, для того чтобы скомпилировать ее в объектный файл с именем hello-1.obj, набрав в командной строке следующую команду:

Для TASM:

tasm hello-1.asm

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

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

Для TLINK:

tlink /t /x hello-1.obj

Теперь получился файл HELLO-1.COM размером 23 байта. Если его выполнить, на экране появится строка «Hello World!» и программа завершится.

Рассмотрим исходный текст программы, чтобы понять, как она работает.

Первая строка определяет модель памяти TINY, в которой сегменты кода, данных и стека объединены. Эта модель предназначена для создания файлов типа СОМ.

Директива .CODE начинает сегмент кода, который в нащем случае также должен содержать и данные.

ORG 100h устанавливает значение программного счетчика в 100h, так как при загрузке СОМ-файла в память DOS занимает первые 256 байт (100h) блоком данных PSP и располагает код программы только после этого блока. Все программы, которые компилируются в файлы типа СОМ, должны начинаться с этой директивы.

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

Команда MOV АН,9 помещает число 9 в регистр АН. Это — номер функции DOS «вывод строки».

Команда MOV DX,OFFSET MESSAGE помещает в регистр DX смешение метки MESSAGE относительно начала сегмента данных, который в нашем случае совпадает с сегментом кода.

Команда INT 21h вызывает системную функцию DOS. Эта команда — основное средство взаимодействия программ с операционной системой. В нашем примере вызывается функция DOS номер 9 — вывести строку на экран. Эта функция выводит строку от начала, адрес которого задается в регистрах DS:DX, до первого встреченного символа $. При загрузке СОМ-файла регистр DS автоматически загружается сегментным адресом программы, а регистр DX был загружен предыдущей командой.

Команда RET используется обычно для возвращения из процедуры. DOS вызывает СОМ-программы так, что команда RET корректно завершает программу.

DOS при вызове СОМ-файла помещает в стек сегментный адрес программы и ноль, так что RET передает управление на нулевой адрес текущего сегмента, то есть на первый байт PSP. Там находится код команды INT 20h, которая и используется для возвращения управления в DOS. Можно сразу заканчивать программу командой INT 20h, хотя это длиннее на 1 байт.

Следующая строка программы HELLO-1.ASM определяет строку данных, содержащую текст «Hello World!», управляющий символ ASCII «возврат каретки» с кодом 0Dh, управляющий символ ASCII «перевод строки» с кодом 0Ah и символ «$», завершающий строку. Эти два управляющих символа переводят курсор на первую позицию следующей строки точно так же, как в строках на языке С действует последовательность «\n».

И наконец, директива END завершает программу, одновременно указывая, с какой метки должно начинаться выполнение программы.

Программа типа ЕХЕ

ЕХЕ-программы немного сложнее в исполнении, но для них отсутствует ограничение размера в 64 килобайта, так что все достаточно большие программы используют именно этот формат. Конечно, ассемблер позволяет уместить и в 64 килобайтах весьма сложные и большие алгоритмы, а все данные хранить в отдельных файлах, но ограничение размера все равно очень серьезно, и даже чисто ассемблерные программы могут с ним сталкиваться.

; hello-2.asm

; Выводит на экран сообщение "Hello World!" и завершается

       .model     small             ; модель памяти, используемая для ЕХЕ

       .stack     100h              ; сегмент стека размером в 256 байт

       .code

start:  mov        ax,DGROUP         ; сегментный адрес строки message

       mov        ds,ax             ; помещается в DS

       mov        dx,offset message

       mov        ah,9

       int        21h               ; функция DOS "вывод строки"

       mov        ax,4C00h

       int        21h               ; функция DOS "завершить программу"

       .data

message db         "Hello World!",0Dh,0Ah,'$'

       end        start

В этом примере определяются три сегмента — сегмент стека директивой .STACK размером в 256 байт, сегмент кода, начинающийся с директивы .CODE, и сегмент данных, начинающийся с .DATA и содержащий строку. При запуске ЕХE-программы регистр DS уже не содержит адреса сегмента со строкой message (он указывает на сегмент, содержащий блок данных PSP), а для вызова используемой функции DOS этот регистр должен иметь сегментный адрес строки. Команда MOV AX,DGROUP загружает в АХ сегментный адрес группы сегментов данных DGROUP, a MOV DS,AX копирует его в DS. Для ассемблеров MASM и TASM можно использовать вместо DGROUP предопределенную метку «@data», но единственная модель памяти, в которой группа сегментов данных называется иначе, — FLAT (ей мы пока пользоваться не будем). И наконец, программы типа ЕХЕ должны завершаться системным вызовом DOS 4Ch: в регистр АН помещается значение 4Ch, в регистр AL помещается код возврата (в данном примере код возврата 0 и регистры АН и AL загружаются одной командой MOV AX,4C00h), после чего вызывается прерывание 21h.

Компиляция hello-2.asm:

Для TASM:

tasm hello-2.asm

tlink /x hello-2.obj

Размер получаемого файла hello-2.exe — 559 байт.

 Содержание отчета:

  1.  Название работы
  2.  Цель работы
  3.  Приборы и оборудование
  4.  Краткие теоретические сведения
  5.  Индивидуальное задание
  6.  Распечатанный текст программы
  7.  Выводы.

Вопросы к защите лабораторной работы.

1. Этапы получения  .СОМ и .ЕХЕ файлов.

Лабораторная работа № 7

Изучение команд условной передачи управления

Цель работы: научиться применять команды условной передачи управления при написании программ

Приборы и оборудование: IBM-совместимый компьютер, QC 2.00 w ASM.

Вычислить выражение

1 вариант

     x+13        15<x

z=  y*35+5             5<x<=15    

  x+y+5    x<=5

 x – int

 y – char

2 вариант

     x*3+18        25<=y

z=  y*3+5*x            17<=y<25    

  x*y+7    y<17

 x – unsigned long

 y – unsigned char

3 вариант 

     y–12        35<x

z= x/3+5*y             –7<=x<=35    

  x%y+5    x<– 7

 x – char

 ylong

4 вариант

     x*18        12<=x

z= y*35+5             2<x<12    

  x+y%5    x<=2

 x – unsigned int

 y – unsigned long

5 вариант 

     y%10        105 <= x

z= y*7+x*2            –15 <= x< 105    

  y+15     x < –15

 x – int

 yint

6 вариант

     y+10%x        17 <= y

z= x – 35+y            10 < y < 17    

  y*7+5    y <= 10

 x – unsigned char

 y – unsigned long

7 вариант 

     y–13        –15 < x

z= y+x+50             –50 < x <= –15    

  x*y+1    x <= –50

 x – int

 y – char

8 вариант 

     y%13        150 <= y

z= y/5+50             50 < y < 150    

  x/3+y+5    y <= 50

 x – unsigned int

 y – unsigned long

9 вариант 

     y / 13        155 < y

z= x+35+y%5        –5 < y <= 155    

  x+y     y <= –5

 x – long

 y – long

10 вариант

     x+13        15<x

z= y/5+x/5             5 < x <= 15    

  x+y–5    x <= 5

 x – unsigned int

 y – unsigned long

11 вариант 

     y%7+130        121 < y

z= y+35+x*5          –17 < y <= 121    

  x+2     y <= –17

 x – int

 y – long

12 вариант 

     y+13        88 < y

z= x/5+y%5            32 < y<= 88   

  x+y     y <= 32

 x – unsigned char

 y – unsigned int

13 вариант 

     x+y+13        –15 < x

z= x*3+y/5             –25 < x <= –15    

  x/y+5    x <= –25

 x – char

 ychar

14 вариант

     (x+y)%7        159 <= x

z= y*(35+x)           7 <= x <159    

  (x+y)*5    x < 7

 x – unsigned char

 y – unsigned long

15 вариант 

     x+13%y        150 < y+x

z= y*35%x             57 < y+x <= 150    

  x+y+2    y+x <= 57

 x – long

 y – int

Содержание отчета

  1.  Титульный лист
  2.  Наименование работы
  3.  Цель работы
  4.  Приборы и оборудованеи
  5.  Индивидуальное задание
  6.  Исходный модуль программы
  7.  Отладка на конкретном примере

Лабораторная работа №8

«Изучение команд управления циклами»

Цель работы: научиться испоьзовать команды управления циклами при написании ассемблерных программ.

Индивидуальные задания


  1.  y=
  2.  y=
  3.  y=
  4.  y=
  5.  y=
  6.  y=
  7.  y=
  8.  y=
  9.  y=
  10.  y=
  11.  y=
  12.  y=
  13.  y=
  14.  y=
  15.  y=

Для четных вариантов   i – char

Для нечетных вариантов   iunsigned char

Лабораторная работа №9

«Изучение команд обработки строк»

Цель работы: научиться испоьзовать команды обработки строк при написании ассемблерных программ.

Замечания: реализовать работу со строками при помощи команд обработки строк

Индивидуальные задания

  1.  Написать процедуру копирования строки.
  2.  Написать процедуру объединения двух строк.
  3.  Дана строка. Преобразовать строчные буквы в прописные. Рассмотреть только латинский алфавит
  4.  Дана строка. Преобразовать строчные буквы в прописные. Рассмотреть только русский алфавит
  5.  Дана строка. Преобразовать прописные буквы в строчные. Рассмотреть только латинский алфавит.
  6.  Дана строка. Преобразовать прописные буквы в строчные. Рассмотреть только русский алфавит.
  7.  Написать процедуру, осуществляющую сравнение строк. Рассмотреть только латинский алфавит.
  8.  Написать процедуру, осуществляющую сравнение строк. Рассмотреть только русский алфавит.
  9.  Написать процедуру, выводящую строку на экран путем прямого доступа к видеопамяти.
  10.  Зашифровать и расшифровать исходную строку.
  11.  Написать процедуру копирования массива типа char. Во входных параметрах необходимо задать количество элементов массива.
  12.  Написать процедуру копирования массива типа long. Во входных параметрах необходимо задать количество элементов массива.
  13.  Обменять между собой содержимое 0-й и 1-й страниц видеопамяти.
  14.  Сохранить содержимое 0-й страницы видеопамяти в файле на диске.
  15.  Очистить экран заданным цветом путем прямого доступа к видеопамяти.




1. Аутентификация и идентификация пользователей в сети при помощи паролей
2. Вариант I Часть 1 Пачка чипсов стоит 15 рублей
3. МЕДИЦИНА МОСКВА 1971 УДК 616
4. Дети с небес Ее любовь жизнерадостность и свет озарили благодатью мою жизнь и жизнь наших детей
5. . Поняття та ознаки держави Держава ~ це особлива політична організація публічної влади яка виражає інте
6.  Задачи решаемые при планировании финансов предприятия
7. второй полный выходной марта CW второй полный выходной апреля
8. Буревестник состоялись традиционные соревнования по спортивным танцам Российский студенческий бал2013
9. На тему- Планирование прибыли на предприятии и рентабельности производства
10. Сущность и роль предпринимательства в микроэкономике
11. печет прогревая кожу головы и вызывая прилив крови к волосяным луковицам- 2 столовые ложки сухого горчи
12. ТЕМА 6 ВАЛЮТНИЙ РИНОК І ВАЛЮТНІ СИСТЕМИ СУТНІСТЬ ВАЛЮТИ І ВАЛЮТНОГО КУРСУ
13. Планирование музыкальной работы с детьми дошкольного возраста
14.  Соціокультурна зумовленість філософії
15. заочного отделения Факультет Учетнофинансовый; Специальность 0801
16. Анжелика 511 Расширение ассортиментных групп товаров Комплексный экономический анализ деятельности
17. герб цифра на верхней ее стороне.html
18. Конспект лекций Содержание Введение4 1
19. ПОСОБИЕ ПО ВЫПОНЕНИЮ НАУЧНОЙ РАБОТЫ для студентов средних профессиональных образовательных учреждени
20.  О предметах ведения верховных органов власти СоюзаСоветских Социалистических РеспубликГлава 2