Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Тема лекции 3. Язык Ассемблер. Структура программы на ассемблере. Использование сегментов в микропроцессоре I 8086.






Ассемблер - это машинно-ориентированный язык представления программ, написанных в машинных кодах. Он дает программисту следующие возможности:

-использовать символические обозначения машинных команд (мнемокоды);

-присваивать символические имена регистрам и ячейкам памяти;

-использовать различные системы счисления и арифметические и логические

выражения для записи чисел и др.

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

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

делятся на две группы: команды и директивы (псевдокоманды). При

трансляции команды переводятся в машинный код, трансляция директивы сводится к ее выполнению в ходе трансляции.

Команда, записанная на языке Ассемблера, имеет следующий вид: [Метка: ] Мнемокод [Операнды] [; Комментарии],

где в квадратные скобки помещены необязательные поля команды. Приведенные поля команд отделяются друг от друга пробелами, либо знаками табуляции - Tab. Поле метки служит для присваивания команде имени, по которому на нее могут ссылаться другие команды, например, команды передачи управления. Метка должна заканчиваться двоеточием, состоять из латинских букв, цифр и специальных символов "? ", " @", " _" и " $", при этом первым символом не может быть цифра. Поле мнемокода содержит название команды ЦП. Поле операндов содержит информацию о местонахождении данных, подлежащих обработке. В некоторых случаях, когда операнды заданы по умолчанию (строковые команды, XLAT и др.) или вовсе не нужны (команда NOP), это поле пустое. В командах с двумя операндами первый является приемником результата, второй - источником информации. Поле комментариев содержит текст, поясняющий работу программы. Комментарий может занимать всю строку, если в первой позиции указать точку с запятой. Псевдокоманды записываются в следующем виде:

[Идентификатор] Псевдокоманда [Операнды] [; Комментарии], где в квадратные скобки помещены необязательные поля псевдокоманды. Приведенные поля псевдокоманд отделяются друг от друга пробелами либо знаками табуляции.

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

Физическая память, к которой микропроцессор имеет доступ по шине адреса, называется оперативной памятью (или оперативным запоминающим устройством — ОЗУ). На самом нижнем уровне память компьютера можно рассматривать как массив битов. Один бит может хранить значение О или 1. ОЗУ организовано как последовательность ячеек — байтов. Один байт состоит из 8 бит. Каждому байту соответствует свой уникальный адрес (его номер), называемый физическим. Диапазон значений физических адресов зависит от разрядности шины адреса

микропроцессора. Для i486 и Pentium он находится в пределах от 0 до 2 - 1 (4

Гбайт).

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

Каждая программа в общем случае может состоять из любого количества сегментов, но непосредственный доступ она имеет только к трем основным: кода, данных и стека, — и от одного до трех дополнительных сегментов данных. Операционная система размещает сегменты программы в оперативной памяти по определенным физическим адресам, после чего помещает значения этих адресов в определенные места. Куда именно, зависит от режима работы микропроцессора. Так, в реальном режиме эти адреса помещаются непосредственно в соответствующие сегментные регистры, а в защищенном режиме они размещаются в элементы специальной системной дескрипторной таблицы. Внутри сегмента программа обращается к адресам относительно начала сегмента линейно, то есть начиная с 0 и заканчивая адресом, равным размеру сегмента. Этот относительный адрес, или смещение, который микропроцессор использует для доступа к данным внутри сегмента, называется эффективным.

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

Формирование физического адреса в реальном режиме

В реальном режиме механизм адресации физической памяти имеет следующие характеристики:

- диапазон изменения физического адреса от 0 до 1 Мбайт. Эта величина определяется тем, что шина адреса i8086 имела 20 линий;

- максимальный размер сегмента 64 Кбайт. Это объясняется 16­разрядной архитектурой i8086. Таким образом максимальное значение, которое могут содержать 16-разрядные регистры, составляет 216 - 1, что применительно к памяти и определяет величину 64 Кбайт;

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

(паpагpаф - объем памяти pазмеpом в 16 байт), поэтому в адресе начала сегмента последняя цифра равна нулю. Напpимеp: 10000h, 1FFF0h. (Таким образом, в сегментном регистре достаточно хранить только старшие 16 бит физического адреса начала сегмента. Недостающие младшие нулевые четыре бита 20-битного адреса получаются сдвигом значения в сегментном регистре влево на 4 разряда. Эта операция сдвига выполняется аппаратно и для программного обеспечения абсолютно прозрачна. Получившееся 20-битное значение и является настоящим физическим адресом, соответствующим началу сегмента. Что касается второго компонента, участвующего в образовании физического адреса некоторого объекта в памяти, — смещения, — то оно представляет собой 16-битное значение. Это значение может содержаться явно в команде либо косвенно в одном из регистров общего назначения. В микропроцессоре эти две составляющие складываются на аппаратном уровне, в результате чего получается физический адрес памяти размерностью 20 бит. Данный механизм образования физического адреса позволяет сделать программное обеспечение перемещаемым, то есть не зависящим от конкретных адресов загрузки его в оперативной памяти.)

(Следует заметить следующее о несоответствии размеров шины адреса микропроцессора i486 или Pentium (32 бита) и 20-битного значения физического адреса реального режима. Пока микропроцессор находится в реальном режиме, старшие 12 линий шины адреса недоступны, хотя при определенных условиях и существует возможность работы с первыми 64 Кбайт оперативной памяти, лежащими сразу после первого мегабайта.)

Так как в реальном режиме адреса сегментов хранятся в сегментных pегистpах, а адреса смещений - в pегистpе IP для сегмента кода, в одном из pегистpов BX, SI, DI для сегмента данных, в одном из pегистpов SP, BP для сегмента стека и в pегистpе DI для дополнительного сегмента данных, то микpопpоцессоp вычисляет адреса памяти доступа к сегменту данных по формулам:

(DS)x16 + BX или (ds)x16 + S1 или (ds)x16 + D1 к сегменту кода:

(CS)x16 + (IP) к сегменту стека:

(SS)x16 + SP или (SS)x16 + BP

к дополнительному сегменту данных:

(ES)x16 + DI.

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

Слова в памяти располагаются в обратном порядке, по правилу младший байт находится по младшему адресу.

Например: Задан массив слов DW 0110h, 0220H, 0330h, 0440h В памяти он будет представлен: DS: 0000 10 01 20 02 30 03 40 04 Основная литература: 5[46, 120-125], 8[21-32]7 [40-50].

Контрольные вопросы:

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

2. Какой вид имеет команда, записанная на языке Ассемблера?

3. Какой вид имеет псевдокоманда на языке Ассемблера?

4. Как определяется эффективный адрес?

5. Как вычисляется физический адрес в реальном режиме?

Тема лекции 4.Описание данных. Режимы адресации.

Описание данных

Для определения данных используются, главным образом, три директивы ассемблера: db (define byte, определить байт) длёя записи байтов, dw (define word, определить слово) для записи слов и dd (define double, определить двойное слово) для записи двойных слов:

size dw 256; В ячейку size записывается

; десятичное число 256

setb7 db 80h; Bячейку setb7записывается

; 1б-ричное число 80h

Для резервирования места под массивы используется оператор dup (duplicate, дублировать), который позволяет «размножить» байт, слово или двойное слово заданное число раз:

rawdata dw 300 dup (1); Резервируются 300 слов,

; заполненных числом 1

string db 80 dup (") /Резервируются 80 байтов,

; заполненных знаком "

Кроме перечисленных, имеются и другие директивы, например df (define farword, определить поле из 6 байт), dq (define quadword, определить четверное слово) или dt (define teraword, определить 10-байтовую переменную), но они используются значительно реже.

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

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

Способы задания операндов команды определяют режимы адресации.

Все обращения к данным делятся на три типа:

• Обращения к непосредственным данным

• Обращения к данным в регистрах

• Обращения к данным в памяти

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

В двухоперандной машинной команде возможны следующие сочетания операндов:

- регистр—регистр;

- регистр—память;

- память—регистр;

- непосредственный операнд—регистр;

- непосредственный операнд—память.

Непосредственная адресация (непосредственный операнд) - операнд задается в самой команд, т.е его значения записываются прямо в машинном коде команд.

Например: mov ах, 5

-ассемблер генерирует машинный код, соответствующий команде mov, которая загружает в регистр ах непосредственное значение 5. Значение 5 записывается в ассемблированном машинном коде команды mov. В большинстве случаев непосредственные данные являются либо единственным операндом, либо вторым из двух операндов.

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

Например: mov ax, bx

В качестве регистров могут использоваться:

- 32-разрядные регистры ЕАХ, ЕВХ, ЕСХ, EDX, ESI, EDI, ESP, EBP; - 16­разрядные регистры АХ, ВХ, СХ, DX, SI, DI, SP, ВР; - 8-разрядные регистры АН, AL, BH, BL, CH, CL, DH, DL; -

сегментные регистры CS, DS, SS, ES, FS, GS.

Основные виды адресации операндов в памяти. Цель всех разновидностей данной адресации- помочь процессору вычислить 16-битовое беззнаковое значение, называемое эффективным адресом, или ЭА. ЭА показывает смещение, начиная от базового сегмента, адресуемого одним из четырех сегментных регистров: cs, ds, es, ss. (Сегментный регистр и смещение образуют 32-битовый логический адрес, который в дальнейшем преобразуется в 20-битовый физический адрес, однозначно определяющий положение байта в памяти.) Общее число режимов адресации, т.е способов обращения к операндам определяется архитектурой микропроцессора (так по документации только микропроцессор 8088 имеет 24 режима адресации операндов!).

Основные виды адресации операндов в памяти: прямая, косвенная, базовая, индексная, базово-индексная.

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

; Сегмент данных

meml dw 0; слово памяти содержит 0 mem2 db 230; байт памяти содержит 230; Сегмент команд

inc meml; Содержимое слова meml увеличивается на 1 mov DX, meml; Содержимое слова с именем meml загружается в DX mov AL, mem2; Содержимое байта с именем mem2 загружается в AL При прямой адресации можно использовать выражение, состоящее из некоторой переменной или константы, которая добавляется к соответствующему смещению имени переменной. Таким образом можно обращаться к полям составной переменной (например, можно обеспечить доступ к полям сложной переменной, например, структуры).

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

SS. Процессор узнает, из какого регистра взять сегментный адрес с помощью префиксов замены сегмента (Имеется несколько групп префиксов: повторения, размера адреса, размера операнда, замены сегмента.)

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

ES

assume ES: data

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

Однако в ряде случаев префикс замены сегмента должен указываться в программе в явной форме. Такая ситуация возникает, например, если данные расположены в сегменте команд, что типично для резидентных обработчиков прерываний. Для обращения к таким данным можно, конечно, использовать регистр DS, если предварительно настроить его на сегмент команд, но проще выполнить адресацию через регистр CS, который и так уже настроен должным образом. Если в сегменте команд содержится поле данных с именем mem, то команда чтения из этого поля будет выглядеть следующим образом: mov АХ, С S: mem1

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

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

mov AX, 0B800h; Сегментный адрес видеобуфера

mov ES, AX; Отправим его в ES

mov byte ptr ES: 0, '! '; Отправим символ на 1-е

знакоместо экрана

mov byte ptr ES: 2, '! '; Отправил символ на 2-е

знакоместо экрана

Заметим, что команда mov ES: 0, '! '

вызовет ошибку трансляции, так как ассемблер не сможет определить, надо ли транслировать это предложение, как команду пересылки в видеобуфер байта 21h, или как команду пересылки слова 0021h.

При необходимости можно было воспользоваться для записи в видеобуфер регистром DS:

mov AX, 0B800h; Сегментный адрес

mov DS, AX; видеобуфера в DS

mov byte ptr DS: 0, '! '; Символ в видеобуфер

В код команды префикс замены сегмента не включается, но запись DS: необходима,

так как при записи mov 6, 10. будет ошибка (переслать число 10 в число 6),

команда mov DS: 6, 10 пересылает число 10 по относительному адресу 6, что имеет смысл.

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

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

Синтаксически в команде этот режим адресации выражается заключением имени регистра в квадратные скобки [ ].

команда mov ax, [ecx] помещает в регистр ах содержимое слова по адресу из сегмента данных со смещением, хранящимся в регистре есх.

Косвенной адресации для микропроцессора 18086 можно использовать только регистры [ВХ], [SI], [DI], [ВР]. Для первых трех регистров их содержимое является смещением по отношению к сегменту данных (т.е. текущее значение сегментного регистра DS определяет вторую составляющую адреса). Регистр [ВР] определяет смещение в сегменте стека (текущее содержимое сегментного регистра SS) для вычисления адреса. При использовании регистров ВХ или ВР адресацию называют базовой, при использовании регистров SI или DI — индексной.

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

mov AX, OB800h; Сегментный адрес

mov ES, AX; видеобуфера в ES

mov BX, 2 0 0 0; Смещение к середине экрана

mov byte ptr ES: [BX], ‘! ’; Символ на экран

Если косвенная адресация осуществляется через один из регистров ВХ, SI или DI, то подразумевается сегмент, адресуемый через DS, поэтому при адресации через этот регистр обозначение DS: можно опустить: mov AX, 0B800h; Сегментный адрес

mov DS, AX; Видеобуфера в DS

mov BX, 2000; Смещение к середине экрана

mov byte ptr [BX], '! '; Символ на экран

Этот фрагмент немного эффективнее предыдущего в смысле расходования памяти. Из-за отсутствия в коде последней команды префикса замены сегмента он занимает на 1 байт меньше места.

Регистры ВХ, SI и DI в данном применении совершенно равнозначны, и с одинаковым успехом можно воспользоваться любым из них: mov D1, 2 000; Смещение к середине экрана

mov byte ptr [DI], '! '; Символ на экран

Не так обстоит дело с регистром ВР. Этот регистр специально предназначен для работы со стеком, и при адресации через этот регистр в режимах косвенной адресации подразумевается сегмент стека; другими словами, в качестве сегментного регистра по умолчанию используется регистр SS.

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

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

Для микропроцессоров старше I80386 косвенная индексная адресация и косвенная адресация по базе расширена. В качестве индексных регистров можно использовать все регистры данных - ([ЕАХ], [ЕВХ], [ЕСХ], [EDX]), а так же три индексных регистра - ([ЕВР], [ESI], [ED1]). В этом случае константа может быть или байтом, или двойным словом, и эта константа рассматривается как число со знаком.

Для всех регистров, кроме [ЕВР], при расчете адреса используется текущее содержимое сегментного регистра DS, а для регистра [ЕВР] -содержимое сегментного регистра SS.

Регистровая косвенная адресация со сдвигом (базовая и индексная). Относительный адрес операнда определяется, как сумма содержимого регистра ВХ, ВР, SI или DI и указанной в команде константы, называемой сдвигом, смещением или перемещением. Сдвиг может быть числом или адресом. Так же, как и в случае базовой адресации, при использовании регистров ВХ, SI и DI подразумевается сегмент, адресуемый через DS, а при использовании ВР подразумевается сегмент стека и, соответственно, регистр SS.

Рассмотрим применение косвенной адресации со смещением на примере прямого вывода в видеобуфер.

mov AX, 0B800h; Сегментный адрес

mov ES, АХ; видеобуфера в ES

mov DI, 80*2*24; Смещение к нижней строке

экрана

mov byte ptr ES: [DI], 'О'; Символ на экран mov byte ptr ES: 2 [DI], 'К'; Запишем символ в следующую позицию

mov byte ptr ES: 4 [DI], '! '; Запишем символ в следующую позицию В этом примере в качестве базового выбран регистр DI; в него заносится базовый относительный адрес памяти, в данном случае смещение в видеобуфере к началу последней строки экрана. Модификация этого адреса с целью получить смещение по строке экрана осуществляется с помощью констант 2 и 4,

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

Вместо, 4[ВХ] можно с таким же успехом написать [ВХ+4], 4+[ВХ] или [BX]+4.

Рассмотрим пример, когда сдвиг задается адресом массива, а в регистре находится индекс адресуемого элемента в этом массиве. Пусть надо заполнить массив из 10000 слов натуральным рядом чисел.

; Сегмент данных array dw 10000 dup(0)

; Сегмент команд

mov S1, 0 Начальное значение индекса элемента в

массиве

mov AX, 0; Первое число-заполнитель

mov СХ, 10000; Число шагов в цикле (всегда в СХ)

fill: mov array[SI], AX; Занесение числа в элемент массива

inc AX Инкремент числа-заполнителя

add SI, 2; Смещение в массиве к следующему слову

loop fill; Возврат на метку fill (СХ раз)

Цикл начинается с команды, помеченной меткой fill (правила образования имен меток такие же, как и для имен полей данных). В этой команде содержимое АХ, сначала равное 0, переносится в ячейку памяти, адрес которой вычисляется, как сумма адреса массива array и содержимого индексного регистра SI, в котором в первом шаге цикла тоже 0. В результате в первое слово массива заносится 0. Далее содержимое регистра АХ увеличивается на 1, содержимое регистра SI — на 2 (из-за того, что массив состоит из слов), и командой loop осуществляется переход на метку fill, после чего тело цикла повторяется при новых значениях регистров АХ и SI. Число шагов в цикле, отсчитываемое командой loop, определяется исходным содержимым регистра СХ.

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

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

[ВХ] [SI] (подразумевается DS: [ВХ] [SI])

[ВХ] [DI] (подразумевается DS: [BX][DI])

[ВР] [SI] (подразумевается SS: [BP][SI])

[ВР] [DI] (подразумевается SS: [BP][DI])

В одном из регистров находится, как правило адрес массива, а в другом - индекс.

Рассмотрим предыдущий пример с введением в него базово-индексной адресации.

Сегмент данных

array dw 10000 dup(0)

; Сегмент команд

mov BX, offset array; Базовый адрес массива в; базовом регистре

mov SI, 0; Начальное значение индекса; элемента в массиве

mov AX, 0; Первое число-заполнитель

mov CX, 10000; Число шагов в цикле

fill: mov [BX][SI], AX; Отправим число в массив

inc AX Инкремент числа-заполнителя

add SI, 2; Смещение в массиве к следующему слову

loop fill; На метку fill (CX раз)

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

Базово-индексная адресация со сдвигом. Относительный адрес операнда определяется как сумма содержимого двух регистров и сдвига

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

Пусть в сегменте данных определен массив из 24 байтов, в котором записаны коды латинских и русских символов верхнего ряда клавиатуры: sims db ” QWERTYUIOP{}”

db " ЙЦУКЕНГШЩЗХЪ ”

Последовательность команд mov BX, 12; Число байтов в строке

mov SI, 6

mov DL, syms[BX][SI]

загрузит в регистр DL элемент с индексом 6 из второго ряда, т.е. код ASCII буквы Г. Тот же результат можно получить, загрузив в один из регистров не индекс, а адрес массива:

mov BX, offset sym

mov SI, 6

mov DL, 12 [BX] [SI]

Косвенная адресация с масштабированием (микропроцессор I80386 и старше)

Еще одна дополнительная возможность косвенной адресации используется в микропроцессорах I80386 и старше - при индексной адресации (простой и адресации по базе с индексированием) содержимое индексного регистра ([ЕАХ], [ЕВХ], [ЕСХ], [EDX], [EBP], [ESI], [EDI]) можно дополнительно умножить на масштабный множитель -число 1, 2, 4, 8. (Использование множителя 1 соответствует обычной индексной адресации). Такой подход позволяет упростить доступ к элементам массива, имеющих элементы, кратные множителю (например, к элементам массивов, состоящим


из слов и двойных слов). В таких случаях в индексный регистр просто записывается номер элемента и указывается необходимый множитель. Основная литература: 5[125-135], 7[74-82], 4[98-110], Дополнительная литература: 18[113-118]. Контрольные вопросы: 1 Какие три основные директивы ассемблера используются для определения данных?. 2. Как описать строку в ассемблере? 3. На какие типы делятся все обращения к данным? 4. Назовите основные виды адресации операндов в памяти. 5. Какие способы адресации удобно использовать для работы с массивами? Тема лекции 5. Команды микропроцессора. Классификация. Группа команд пересылки данных. Система команд микропроцессора содержит около 130 машинных команд. С появлением каждой новой модели микропроцессора их количество, как правило, возрастает.Классификация команд представлена на рисунке 2.

Пересылки Арифметичес Логические Передачи Цепочечные Управления
данных кие   управления   состоянием
          ЦП
Команды ассемблера

Общего назначения

Двоичной арифметики

Манипуляции битами

Безусловные

Десятичной арифметики

Рисунок 2. Машинные команды и их функциональные группы Группа команд пересылки данных. Включает 1. команды пересылки данных 2. команды ввода-вывода в порт;


Условные

Работы со стеком

Сдвига

Преобразование типов

 


1. команды работы с адресами и указателями;

2. команды преобразования данных;

3. команды работы со стеком.

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

К этой группе относятся следующие команды: mov < операнд назначения>, < операщ~источник> xchg < операнд 1>, < операнд2>

По команде mov на место первого операнда пересылается значение второго операнда. Флаги эта команда не меняет.

mov АХ, 500; АХ: =500 mov BL, DH; BL: =DH

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

Нельзя:

1 пересылать из одной области памяти в другую;

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

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

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

mov ax, ds mov es, ax

Но есть и другой, более красивый способ выполнения данной операции — использование стека и команд push и pop:

push ds; поместить значение регистра ds в стек pop es; записать в es число из стека

3. нельзя использовать сегментный регистр cs в качестве операнда назначения, так как пара cs: ip всегда содержит адрес команды, которая должна выполняться следующей. Изменение командой mov содержимого регистра cs фактически означало бы операцию перехода, а не пересылки, что недопустимо.

Как известно, в ПК числа размером в слово хранятся в памяти в " перевернутом" виде, а в регистрах - в нормальном, неперевернутом. Команда MOV учитывает это и при пересылке слов между памятью и регистрами сама " переворачивает" их:

Q dw 1234h; Q: 34h, Q+l: 12h MOV AX, Q.; AH-12h, AL-34h Пусть имеются такие описания переменных X DB?

YDW?

Как правило, в команде MOV легко узнается тип (размер) одного из операндов, он и определяет размер пересылаемой величины. Например:

MOV ВН, 0; пересылка байта (ВН - байтовый регистр)

MOV х, 0; то же самое (X описан как имя байтовой переменной)

MOV SI, 0; пересылка слова (SI - регистр размером в слово)

MOV Y, 0; то же самое (Y описан как имя переменной-слова)

Отметим, что здесь по второму операнду (0) нельзя определить, какого он размера: ноль может быть и байтом (00h), и словом (0000h).

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

MOV DI, ES; пересылка слова

MOV СН, Х; пересылка байта

MOV DX, AL; ошибка (DX - слово, AL - байт)

MOV BH, 300; ошибка (ВН - байт, а 300 не может быть байтом)

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

mov ax, word ptr [bx]; если [Ьх] адресует слово в памяти inc byte ptr [bx]; если [bx] адресует байт в памяти dec dword ptr [bx]; если [bx] адресует двойное слово в памяти mov word ptr [bx], 0; если [bx] адресует слово в памяти (PTR (от pointer, указатель) записывается следующим образом:

< тип> PTR < выражение>

где < тип> • это BYTE, WORD или DWORD (есть и другие варианты), а выражение может быть константным или адресным.

Если указано константное выражение, то оператор " говорит", что значение этого выражения (число) должно рассматриваться ассемблером как величина указанного типа (размера); например, BYTE PTR 0 - это ноль как байт, a WORD PTR 0 - это ноль как слово (запись BYTE PTR 300 ошибочна, т. к. число 300 не может быть байтом). Отметим, что в этом случае оператор PTR относится к константным выражениям.

Если же в PTR указано адресное выражение, то оператор " говорит", что адрес, являющийся значением выражения, должен восприниматься ассемблером как адрес ячейки указанного типа (размера); например: WORD PTR A - адрес А обозначает слово (байты с адресами А и А+1). В данном случае оператор PTR относится к адресным выражениям.

Также этот оператор нужно применять, когда требуется принудительно поменять размерность операндов. Например, требуется переслать значение 0ffh во второй байт поля flp:

; сегмент данных

flp dw 0

; сегмент кода

mov byte ptr (flp+1), 0ffh

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

Команды ввода-вывода в порт

Операнды машинной команды могут находиться в портах ввода-вывода. Каждое устройство ввода/вывода, каждое системное устройство имеет один или несколько регистров, доступ к которым осуществляется через адресное пространство ввода/вывода. Эти регистры имеют разрядность 8, 16 или 32 бит. Адресное пространство ввода/вывода физически независимо от пространства оперативной памяти и имеет ограниченный объем, составляющий 216, или 65536 адресов ввода/вывода. Таким образом, понятие порта ввода-вывода можно определить как 8, 16 или 32-разрядный аппаратный регистр, имеющий определенный адрес в адресном пространстве ввода/вывода. Вся работа системы с устройствами на самом низком уровне выполняется с использованием портов ввода-вывода. Упрощенная, концептуальная схема управления оборудованием компьютера имеет вид:

Рисунок3. Концептуальная схема управления оборудованием компьютера

 

Для работы с портами используются две команды: in и out.

in аккумулятор, номерпорта — ввод в аккумулятор из порта с номером номер_ порта;

out порт, аккумулятор - вывод содержимого аккумулятора в порт с номером номер_ порта.

Команды работы со стеком

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

Для работы со стеком предназначены три регистра: ss — сегментный регистр стека; sp/esp — регистр указателя стека;

bp/ebp — регистр указателя базы кадра стека.

Размер стека зависит от режима работы микропроцессора и ограничивается 64 Кбайт (или 4 Гбайт в защищенном режиме).

Особенности работы со стеком:

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

- по мере записи данных в стек последний растет в сторону младших адресов. Эта особенность заложена в алгоритм команд работы со стеком;

- при использовании регистров esp/sp и ebp/bp для адресации памяти ассемблер автоматически считает, что содержащиеся в нем значения представляют собой смещения относительно сегментного регистра ss.

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

push источник — запись значения источник в вершину стека. алгоритм работы этой команды:

1) (sp) = (sp) - 2; значение sp уменьшается на 2;

pop назначение — запись значения из вершины стека по месту, указанному операндом назначение. Значение при этом «снимается» с вершины стека

2) -значение из источника записывается по адресу, указываемому парой ss:

sp.

pop назначение — запись значения из вершины стека по месту, указанному операндом назначение. Значение при этом «снимается» с вершины стека алгоритм работы этой команды:

1) запись содержимого вершины стека по месту, указанному операндом назначение

2)(sp) = (sp) + 2; увеличение значения sp.

Основная литература: 5[129-152], 9[42-46]

Дополнительная литература: 19[78-88].

Контрольные вопросы:

1. Приведите классификацию команд ассемблера.

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

3. Назовите команды пересылки для работы со стеком.

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






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.