ВІКІСТОРІНКА
Навигация:
Інформатика
Історія
Автоматизація
Адміністрування
Антропологія
Архітектура
Біологія
Будівництво
Бухгалтерія
Військова наука
Виробництво
Географія
Геологія
Господарство
Демографія
Екологія
Економіка
Електроніка
Енергетика
Журналістика
Кінематографія
Комп'ютеризація
Креслення
Кулінарія
Культура
Культура
Лінгвістика
Література
Лексикологія
Логіка
Маркетинг
Математика
Медицина
Менеджмент
Металургія
Метрологія
Мистецтво
Музика
Наукознавство
Освіта
Охорона Праці
Підприємництво
Педагогіка
Поліграфія
Право
Приладобудування
Програмування
Психологія
Радіозв'язок
Релігія
Риторика
Соціологія
Спорт
Стандартизація
Статистика
Технології
Торгівля
Транспорт
Фізіологія
Фізика
Філософія
Фінанси
Фармакологія


Сегменты, принцип сегментации

Архитектура процессора 8086

Центральный процессор (ЦП) в современных персональных компьютерах выполнен в виде одной сверхбольшой интегральной микросхемы (СБИС). ЦП выполняет машинные команды, выбирая их в заданной последовательности из оперативной памяти. Работа всех электронных устройств компьютера координируется сигналами управления, вырабатываемыми ЦП и некоторыми другими СБИС, сигналами тактового генератора, с помощью которых синхронизируются действия всех сигналов.

Возможности компьютера в большей степени зависят от типа установленного процессора и его тактовой частоты. Семейство процессоров 80х86 корпорации Intel включает в себя микросхемы: 8086, 80186, 80286, 80386, 80486, Pentium, Pentium II, Pentium III и т.д. Совместимые с 80х86 микросхемы выпускают также фирмы AMD, IBM, Cyrix. Особенностью этих процессоров является преемственность на уровне машинных команд: программы, написанные для младших моделей процессоров, без каких-либо изменений могут быть выполнены на более старших моделях. При этом базой является система команд процессора 8086, знание которой является необходимой предпосылкой для изучения остальных процессоров.

Структуру центрального процессора Intel 8086 можно разделить на два логических блока (рис.1.1):

- блок исполнения (EU:Execution Unit);

- блок интерфейса шин (BIU:Bus Interface Unit).

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

В состав EU входят: арифметическо-логическое устройство ALU, устройство управления CU и десять регистров. Устройства блока EU обеспечивают обработку команд, выполнение арифметических и логических операций.

Три части блока BIU - устройство управления шинами, блок очереди команд и регистры сегментов – предназначены для выполнения следующих функций:

- управление обменом данными с EU, памятью и внешними устройствами ввода/вывода;

- адресация памяти;

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

 

 

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

Микропроцессор оперирует с двоичной системой счисления (двоичной системой представления данных). Символьная информация кодируется в соответствии с кодом ASCII (Американский стандартный код для обмена информацией). Числовые данные кодируются в соответствии с двоичной арифметикой. Отрицательные числа представляются в дополнительном коде.

Минимальная единица информации, соответствующая двоичному разряду, называется бит (Bit). Группа из восьми битов называется байтом Byte и представляет собой наименьшую адресуемую единицу – ячейку памяти. Биты в байте нумеруют справа налево цифрами 0...7.

 

BYTE

 

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

 

WORD

 

Четырехбайтовое поле образует двойное слово (Double Word), а шестнадцатибайтовое – параграф (Paragraph).

Таким образом, с помощью 16-разрядной шины данных можно передавать числа от 0 (во всех проводниках сигнал 0) до 65535 (во всех проводниках сигнал 1). Несмотря на то, что двоичная система обладает высокой наглядностью, она имеет существенный недостаток – числа, записанные в двоичной системе, слишком громоздки. С другой стороны, привычная для нас десятичная система слишком сложна для перевода чисел в двоичную систему счисления и обратно. Поэтому наибольшее распространение в практике программирования получила шестнадцатеричная система счисления.

При написании программ принято двоичные числа сопровождать латинской буквой B или b, (например, 101B), а шестнадцатеричные – буквой H или h на конце. Если число начинается с буквы, то обязательной является постановка нуля впереди, например, 0BA8H. Кроме того, Ассемблер позволяет использовать числа представленные в десятичной и восьмеричной системах счисления, которые соответственно сопровождаются латинскими буквами D и O.

Регистры

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

Регистры общего назначения. К ним относятся 16-разрядные регистры АХ, ВХ, СХ, DX, каждый из которых разделен на две части по восемь разрядов:

АХ состоит из АН (старшая часть) и AL (младшая часть);

ВХ состоит из ВH и BL;

СХ состоит из СН и CL;

DX состоит из DH и DL;

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

- регистр АХ служит для временного хранения данных (регистр аккумулятор), часто используется при выполнении операций сло­жения, вычитания, сравнения и других арифметических и логиче­ских операций;

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

- регистр СХ иногда используется для временного хранения дан­ных, но в основном служит счетчиком, в нем хранится число повто­рений одной команды или фрагмента программы;

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

Регистры для адресации. В микропроцессоре существуют четыре 16-битовых (2 байта или 1 слово) регистра, которые могут принимать участие в адресации операндов. Один из них одновременно является и регистром общего назначения — это регистр ВХ, или базовый регистр. Три другие регистра — это указатель базы ВР, индекс источника SI и индекс результата DI (два последних еще называются индексными регистрами). Отдельные байты этихтрех регистров недоступны.

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

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

- CS – регистр программного сегмента (сегмента кода) определяет местоположение части памяти, содержащей программу, то есть выполняемые процессором команды;

- DS – регистр информационного сегмента (сегмента данных) идентифицирует часть памяти, предназначенной для хранения данных;

- SS – регистр стекового сегмента (сегмента стека) определяет часть памяти, используемой как системный стек;

- ES – регистр расширенного сегмента (дополнительного сегмента) указывает дополнительную область памяти, используемую для хранения данных.

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

Регистр указателя стека. Указатель стека SP – это 16-битовый регистр, который определяет смещение текущей вершины стека. Указатель стека SP вместе с сегментным регистром стека SS используются микропроцессором для формирования физического адреса стека. Стек всегда растет в направлении меньших адресов памяти, то есть когда слово помещается в стек, содержимое SP уменьшается на 2, когда слово извлекается из стека, микропроцессор увеличивает содержимое регистра SP на 2.

Регистр указателя команд IP. Регистр указателя команд IP, иначе называемый регистром счетчика команд, имеет размер 16 бит и хранит адрес ячейки памяти, содержащей начало следующей команды. Микропроцессор использует регистр IP совместно с регистром CS для формирования 20-битового физического адреса очередной выполняемой команды, при этом регистр CS задает сегмент выполняемой программы, а IР – смещение от начала сегмента. По мере того, как микропроцессор загружает команду из памяти и выполняет ее, регистр IP увеличивается на число байт в команде. Для непосредственного изменения содержимого регистра IP служат команды перехода.

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

 

 

Биты регистра флагов имеют следующее назначение:

OF (признак переполнения) – равен единице, если возникает арифметическое переполнение, то есть когда объем результата превышает размер ячейки назначения;

DF (признак направления) – устанавливается в единицу для автоматического декремента в командах обработки строк, и в ноль – для инкремента;

IF (признак разрешения прерывания) – прерывания разрешены, если IF=1. Если IF=0, то распознаются лишь немаскированные прерывания;

TF (признаков трассировки) – если TF=1, то процессор переходит в состояние прерывания INT 3 после выполнения каждой команды;

SF (признак знака) – SF=1, когда старший бит результата равен единице. Иными словами, SF=0 для положительных чисел, и SF=1 для отрицательных чисел;

ZF (признак нулевого результата) – ZF=1, если результат равен нулю;

AF (признак дополнительного переноса) – этот флаг устанавливается в единицу во время выполнения команд десятичного сложения и вычитания при возникновении переноса или заема между полубайтами;

PF (признак четности) – этот признак устанавливается в единицу, если результат имеет четное число единиц;

CF (признак переноса) – этот флаг устанавливается в единицу, если имеет место перенос или заем из старшего бита результата, он полезен для произведения операций над числами длиной в несколько слов, которые сопряжены с переносами и заемами из слова в слово;

X – зарезервированные биты.

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

Стек

Во многих случаях программе требуется временно запомнить некоторую информацию. Эта проблема в персональном компьютере решена посредством реализации стека LIFO («последний пришел - первый ушел»), называемого также стеком включения/извлечения (stack). Стек – это область памяти для временного хранения данных, в которую по специальным командам можно записывать отдельные слова (но не байты); при этом для запоминания данных достаточно выполнить лишь одну команду и не нужно беспокоиться о выборе соответствующего адреса: процессор автоматически выделяет для них свободное место в области временного хранения. Наиболее важное использование стека связано с подпрограммами, в этом случае стек содержит адрес возврата из подпрограммы, а иногда и передаваемые в(из) подпрограмму(ы) данные. Стек обычно рассчитан на косвенную адресацию через регистр указатель стека SP. При включении элементов в стек производится автоматический декремент указателя стека, а при извлечении – инкремент, то есть стек всегда «растет» в сторону меньших адресов памяти. Адрес последнего включенного в стек элемента называется вершиной стека (TOS), а адрес сегмента стека – базой стека (обычно содержится в регистре SS).

Прерывания

Часто возникают ситуации, когда необходимо выполнить одну из набора специальных процедур, если в системе или в программе возникают определенные условия, например, нажата клавиша на клавиатуре или произошло деление на ноль. Действие, стимулирующее выполнение одной из таких процедур, называется прерыванием, поскольку основной процесс при этом приостанавливается на время выполнения этой процедуры. Существует два общих класса прерываний: внутренние и внешние. Первые инициируются состоянием ЦП или командой, а вторые – сигналом, подаваемым от других компонентов системы. Типичные внутренние прерывания: деление на нуль, переполнение и т.п., а типичные внешние – это запрос на обслуживание со стороны какого-либо устройства ввода/вывода.

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

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

- текущее значение регистра флагов включается в стек;

- текущее значение кодового сегмента CS включается в стек;

- текущее значение счетчика команд IP включается в стек;

- сбрасываются флаги IF и TF.

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

- счетчика команд IP;

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

- регистра флагов.

Двойное слово, в котором находится новое содержимое счетчика команд и сегмента кода, называется указателем прерывания или вектором прерывания. Каждому типу прерывания назначено число из диапазона 0...255 (номер прерывания), и адрес вектора прерывания находится путем умножения номера типа на четыре (размер вектора прерывания). Таким образом, все вектора прерываний образуют таблицу векторов прерываний, которая содержится в памяти по адресу 0000h:0000h и инициализируется при загрузке компьютера.

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

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

 

регистровая; прямая; непосредственная; косвенная; базовая; индексная; базово-индексная.

Регистровая адресация подразумевает использование в качестве операнда регистра процессора, например,

 

PUSH DS

MOV BP,SP

 

При прямой адресации один операнд представляет собой адрес памяти, второй – регистр:

 

MOV Data,AX

 

Непосредственная адресация применяется, когда операнд, длинной в байт или слово находится в ассемблерной команде:

 

MOV AH,4CH

 

При использовании косвенной адресации абсолютный адрес формируется исходя из сегментного адреса в одном из сегментных регистров и смещения в регистрах BX, BP, SI или DI:

 

MOV AL,[BX] ;База – в DS, смещение – в BX

MOV AX,[BP] ;База – в SS, смещение – в BP

MOV AX,ES:[SI] ;База – в ES, смещение – в SI

 

В случае применения базовой адресации исполнительный адрес является суммой значения смещения и содержимого регистра BP или BX, например,

 

MOV AX,[BP+6] ;База – SS, смещение – BP+6

MOV DX,8[BX] ;База – DS, смещение – BX+8

 

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

 

MOV DX,[SI+5] ;База – DS, смещение – SI+5

 

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

 

MOV BX,[BP][SI] ;База – SS, смещение – BP+SI

MOV ES:[BX+DI],AX ;База – ES, смещение – BX+DI

MOV AX,[BP+6+DI] ;База – SS, смещение - BP+6+DI

EXE- и COM-программы

DOS может загружать и выполнять программные файлы двух типов COM и EXE.

Ввиду сегментации адресного пространства процессора 8086 и того факта, что переходы (JMP) и вызовы (CALL) используют относительную адресацию, оба типа программ могут выполняться в любом месте памяти. Программы никогда не пишутся в предположении, что они будут загружаться с определенного адреса (за исключением некоторых самозагружающихся, защищенных от копирования программ).

Файл COM-формата – это двоичный образ кода и данных программы. Такой файл должен занимать менее 64K и не содержать перемещаемых адресов сегментов.

Файл EXE-формата содержит специальный заголовок, при помощи которого загрузчик выполняет настройку ссылок на сегменты в загруженном модуле.

Перед загрузкой COM- или EXE-программы DOS определяет сегментный адрес, называемый префиксом программного сегмента (PSP), как базовый для программы, а затем выполняет следующие шаги:

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

- помещает путь, откуда загружена программа, в конец окружения;

- заполняет поля PSP информацией, полезной для загружаемой программы (количество памяти, доступное программе, сегментный адрес окружения DOS, текущие векторы прерываний INT 22H INT 23H и INT 24H и т. д.).

EXE-программы

EXE-программы содержат несколько программных сегментов, включая сегмент кода, данных и стека. EXE-файл загружается, начиная с адреса PSP:0100h. В процессе загрузки считывается информация заголовка EXE в начале файла и выполняется перемещение адресов сегментов. Это означает, что ссылки типа

 

mov ax,data_seg

mov ds,ax

 

и

 

call my_far_proc

 

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

После перемещения управление передается загрузочному модулю посредством инструкции далекого перехода (FAR JMP) к адресу CS:IP, извлеченному из заголовка EXE.

В момент получения управления программой EXE -формата:

- DS и ES указывают на начало PSP;

- CS, IP, SS и SP инициализированы значениями, указанными в заголовке EXE;

- поле PSP MemTop (вершина доступной памяти системы в параграфах) содержит значение, указанное в заголовке EXE. Обычно вся доступная память распределена программе.

COM-программы

COM-программы содержат единственный сегмент (или, во всяком случае, не содержат явных ссылок на другие сегменты). Образ COM-файла считывается с диска и помещается в память, начиная с PSP:0100h. В общем случае, COM-программа может использовать множественные сегменты, но она должна сама вычислять сегментные адреса, используя PSP как базу.

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

После загрузки двоичного образа COM-программы:

- CS, DS, ES и SS указывают на PSP;

- SP указывает на конец сегмента PSP (обычно 0FFFEH, но может быть и меньше, если полный 64K сегмент недоступен);

- слово по смещению 06H в PSP (доступные байты в программном сегменте) указывает, какая часть программного сегмента доступна;

- вся память системы за программным сегментом распределена программе;

- слово 00H помещено (PUSH) в стек;

- IP содержит 100H (первый байт модуля) в результате команды JMP PSP:100H.

Выход из программы

Завершить программу можно следующими способами:

- через функцию 4CH (EXIT) прерывания 21H в любой момент, независимо от значений регистров;

- через функцию 00H прерывания 21H или прерывание INT 20H, когда CS указывает на PSP.

Функция DOS 4CH позволяет возвращать родительскому процессу код выхода, который может быть проверен вызывающей программой или командой COMMAND.COM «IF ERRORLEVEL».

Можно также завершить программу и оставить ее постоянно резидентной (TSR), используя либо INT 27H , либо функцию 31H (KEEP) прерывания 21H. Последний способ имеет те преимущества, что резидентный код может быть длиннее 64K, и что в этом случае можно сформировать код выхода для родительского процесса.

Ассемблер, редактор связей

Входной информацией для Ассемблера (TASM.EXE) является исходный файл – текст программы на языке Ассемблера в кодах ASCII. В результате работы Ассемблера может получиться до 3-х выходных файлов:

1) объектный файл – представляет собой вариант исходной программы, записанный в машинных командах;

2) листинговый файл – является текстовым файлом в кодах ASCII, включающим как исходную информацию, так и результат работы программы Ассемблера;

3) файл перекрестных ссылок – содержит информацию об использовании символов и меток в ассемблерной программе.

Передача параметров Ассемблеру осуществляется через командную строку. Командная строка вызова Turbo Assembler записывается в следующем формате:

 

TASM [options] source [,object] [,listing] [,xref]

где options - параметры ассемблирования;

source - файл, содержащий текст программы;

object - объектный файл;

listing - листинговый файл;

xref - файл перекрестных ссылок.

 

Предложения

Программа на языке Ассемблера – это последовательность предложений, каждое из которых записывается в отдельной строке:

 

<Предложение>

<Предложение>

...

<Предложение>

 

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

Все предложения языка Ассемблера делятся на директивы Ассемблера и инструкции (команды) процессора.

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

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

1) инструкции пересылки данных;

2) арифметические, логические и операции сдвига;

3) операции со строками;

4) инструкции передачи управления;

5) инструкции управления процессором.

Выражения

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

Арифметические операторы

выражение_1 * выражение_2

выражение_1 / выражение_2

выражение_1 MOD выражение_2

выражение_1 + выражение_2

выражение_1 – выражение_2

+ выражение

– выражение

Операторы сдвига

выражение SHR счетчик

выражение SHL счетчик

 

Операторы отношений

 

выражение_1 EQ выражение_2

выражение_1 NE выражение_2

выражение_1 LT выражение_2

выражение_1 LE выражение_2

выражение_1 GT выражение_2

выражение_1 GE выражение_2

 

Мнемонические коды отношений расшифровываются следующим образом: EQ – равно, NE – не равно, LT – меньше, LE – меньше или равно, GT – больше, GE – больше или равно.

Операции с битами

 

NOT выражение

выражение_1 AND выражение-2

выражение_1 OR выражение-2

выражение_1 XOR выражение-2

 

Оператор индекса

 

Оператор индекса [] складывает указанные выражения подобно тому, как это делает оператор +, с той разницей, что первое выражение необязательно, при его отсутствии предполагается 0 (двойные квадратные скобки указывают на то, что операнд не обязателен).

Оператор PTR

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

 

Оператор PTR обычно используется для точного определения размера, или расстояния, ссылки. Если PTR не используется, Ассемблер подразумевает умалчиваемый тип ссылки. Кроме того, оператор PTR используется для организации доступа к объекту, который при другом способе вызвал бы генерацию сообщения об ошибке (например, для доступа к старшему байту переменной размера Word).

Операторы HIGH и LOW

Операторы HIGH и LOW вычисляют соответственно старшие и младшие 8 битов значения выражения. Выражение может иметь любое значение.

Оператор SEG

SEG выражение

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

Оператор OFFSET

OFFSET выражение

 

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

Оператор SIZE

SIZE переменная

Оператор SIZE определяет число байтов памяти, выделенных переменной.

Приоритеты операций

При вычислении значения выражения операции выполняются в соответствии со следующим списком приоритетов (в порядке убывания)*:

1) LENGTH, SIZE, WIDTH, MASK, (), [], <>

2) Оператор имени поля структуры (.)

3) Оператор переключения сегмента (:)

4) PTR, OFFSET, SEG, TYPE, THIS

5) HIGH, LOW

6) Унарные + и –

7) *, /, MOD, SHR, SHL

8) Бинарные + и –

9) EQ, NE, LT, LE, GT, GE

10) NOT

11) AND

12) OR, XOR

13) SHORT, .TYPE

Ссылки вперед

Хотя Ассемблер и допускает ссылки вперед (то есть к еще необъявленным объектам программы), такие ссылки могут при неправильном использовании приводить к ошибкам. Пример ссылки вперед:

 

JMP MET

...

MET: ...

 

В приведенном выше примере предполагается, что MET – метка типа NEAR и для ее адресации используется регистр CS, в результате чего генерируется инструкция JMP, занимающая 3 байта.

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

1) если ссылка вперед является переменной, вычисляемой относительно регистров ES, SS или CS, следует использовать оператор переключения сегмента, если он не использован, делается попытка вычисления адреса относительно регистра DS;

2) если ссылка вперед является меткой инструкции в команде JMP и отстоит не далее, чем на 128 байтов, можно использовать оператор SHORT, если этого не делать, метке будет присвоен тип FAR, что не вызовет ошибки, но на 2-м проходе Ассемблер для сокращения размера содержащей ссылку инструкции вынужден будет вставить дополнительную и ненужную инструкцию NOP;

3) если ссылка вперед является меткой инструкции в командах CALL или JMP, следует использовать оператор PTR для определения типа метки, иначе Ассемблер устанавливает тип NEAR, и, если в действительности тип метки окажется FAR, будет выдано сообщение об ошибке.

4.7. Директивы определения данных

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

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

- скалярные данные, представляющие собой единичное значение или набор единичных значений;

- записи, позволяющие манипулировать с данными на уровне бит;

- структуры, отражающие некоторую логическую структуру данных.

Скалярные данные

Директивы определения скалярных данных приведены в таблице

 

Формат Функция
[[имя]] DB значение,... определение байтов
[[имя]] DW значение,... определение слов
[[имя]] DD значение,... определение двойных слов
[[имя]] DQ значение,... определение квадрослов
[[имя]] DT значение,... определение 10 байтов

 

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

 

счетчик DUP (значение,...)

 

Оператор DUP может использоваться не только при определении памяти, но и в других директивах.

Синтаксис директив DW, DD, DQ и DT идентичен синтаксису директивы DB.

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

 

integer1 DB 16

string1 DB 'abCDf'

empty1 DB ?

contan2 DW 4*3

string3 DD 'ab'

high4 DQ 18446744073709551615

high5 DT 1208925819614629174706175d

db6 DB 5 DUP(5 DUP(5 DUP(10)))

dw6 DW DUP(1,2,3,4,5)

Записи

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

- объявление шаблона или типа записи директивой RECORD;

- объявление собственно записи.

Формат директивы RECORD:

 

имя_записи RECORD имя_поля:длина[[=выражение]],...

 

Директива RECORD определяет вид 8- или 16-битовой записи, содержащей одно или несколько полей. Имя_записи представляет собой имя типа записи, которое будет использоваться при объявлении записи. Имя_поля и длина (в битах) описывает конкретное поле записи. Выражение, если оно указано задает начальное (умалчиваемое) значение поля. Описания полей записи в директиве RECORD, если их несколько, должны разделяться запятыми. Для одной записи может быть задано любое число полей, но их суммарная длина не должна превышать 16 бит.

Длина каждого поля задается константой в пределах от 1 до 16. Если общая длина полей превышает 8 бит, Ассемблер выделяет под запись 2 байта, в противном случае – 1 байт. Если задано выражение, оно определяет начальное значение поля. Если длина поля не меньше 7 бит, в качестве выражения может быть использован символ в коде ASCII. Выражение не должно содержать ссылок вперед. Например,

 

item RECORD char:7='Q',weight:4=2

 

Запись item будет иметь следующий вид:

 

  char weight

 

При обработке директивы RECORD формируется шаблон записи, а сами данные создаются при объявлении записи, которое имеет следующий вид

 

[[имя]] имя_записи <[[значение,...]]>

table item 10 DUP(<'A',2>)

 

Если для описания шаблона записи использовалась директива RECORD из предыдущего примера, то по этому объявлению создается 10 записей, объединенных именем table.

Структуры

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

Директивы STRUC и ENDS обозначают соответственно начало и конец описания шаблона (типа) структуры.

Пример:

table STRUC

count DB 10

value DW 10 DUP(?)

tname DB 'font'

table ENDS

 

Директива эквивалентности

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

имя EQU операнд

Директива ASSUME

С помощью директивы ASSUME Ассемблеру сообщается информация о соответствии между сегментными регистрами, и программными сегментами. Директива имеет следующий формат:

 

ASSUME пара [[, <пара>]]

ASSUME NOTHING

где пара - это <сегментный регистр> : <имя сегмента>

либо <сегментный регистр> : NOTHING

 

Например, директива

 

ASSUME ES:A, DS:B, CS:C

 

сообщает Ассемблеру, что для сегментирования адресов из сегмента А выбирается регистр ES, для адресов из сегмента В – регистр DS, а для адресов из сегмента С – регистр CS.

Таким образом, директива ASSUME дает право не ука­зывать в командах (по крайней мере, в большинстве из них) префиксы – опущенные префиксы будет самостоятельно восстанавливать Ассемблер.

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

Если в директиве ASSUME указано несколько пар с одним и тем же сегментным регистром, то последняя из них «отменяет» предыдущие, так как каждому сегментному регистру, можно поставить в соответствие только один сегмент. В то же время на один и тот же сегмент могут указывать разные сегментные регистры. Если в директиве ASSUME в качестве второго элемента пары задано служебное слово NOTHING (ничего), например, ASSUME ES: NOTHING, то это означает, что с данного момента сегментный регистр не указывает ни на какой сегмент, что Ассемблер не должен использовать этот регистр при трансляции команд.

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

Загрузка производится следующим образом. Пусть регистр DS необходимо установить на начало сегмента В. Для загрузки регистра необходимо выполнить присваивание вида DS:=B. Однако сделать это командой MOV DS,B нельзя, поскольку имя сегмента – это константное выражение, то есть непосредственный операнд, а по команде MOV запрещена пересылка непосредственного операнда в сегментный регистр (см. ниже). Поэтому такую пересылку следует делать через другой, несегментный регистр, например, через АХ:

 

MOV АХ,В

MOV DS,AX ;DS:=B

 

Аналогичным образом загружается и регистр ES.

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

Загрузить регистр SS можно двояко. Во-первых, его можно загрузить в самой программе так же, как DS или ES. Во-вторых, такую загрузку можно поручить операционной системе. Для этого в

© 2013 wikipage.com.ua - Дякуємо за посилання на wikipage.com.ua | Контакти