литература / Пухальский Проектирование микропроцессорных систем 2001
.pdf404 Глава 4. Микропроцессоры 8086/8088 и сопроцессор 8087
го перехода JMP L1 и три ячейки памяти для далекого перехода JMP far ptr L1. Машинный код 90h соответствует команде NOP — лишние команды. Для команд перехода назад ассемблеру уже известен адрес перехода, поэтому он исправляет ошибочное указание атрибута far в пред последней команде. Таким образом, неправильное задание атрибутов команд безусловных пе реходов транслятор не обнаруживает — не выводит предупреждения об ошибке, что может привести к увеличению длины программы.
Трансляция команд прямого межсегментного перехода JMP far ptr L1 была бы выполнена в соответствии с атрибутом far, если бы метка L1 находилась в другом сегменте кода:
IP <— смещение L1 в сегменте, CS <— сегментный адрес L1.
Команды JMP выполняются за 15 тактов (внутрисегментный и межсегментный прямой переходы), за 11 тактов (внутрисегментный косвенный переход через регистр), за 18 + еа (внутрисегментный косвенный переход через память) и за 24 + еа (межсегментный косвенный переход).
Команды условных переходов. Все эти команды двухбайтовые. Второй байт представля ет собой смещение dispS — число со знаком. Переходы могут быть только типа short (корот кие) в диапазоне адресов -128 ... +127 байт относительно адреса следующей команды. Перехо ды осуществляются только по меткам. Описание команд условных переходов приведено в табл. 4.15 (большинство команд имеют один или два синонима). Выполняется переход или не выполняется, зависит от состояния флагов. При переходе выполняется действие:
IP <— IP + dispft.
Если указанный в программе условный переход выходит из диапазона -128 ... +127 байт, то при трансляции ассемблер выдаст сообщение об ошибке. В этом случае команду условного перехода необходимо заменить двумя командами: командой условного перехода с альтерна тивным условием перехода и следующей за ней командой безусловного перехода типа near.
Пример 22:
JZ |
L2 |
; Если расстояние до метки L2 превышает+127 байт, то команду JZ |
MOV |
[ВХ], AL |
; необходимо заменить двумя командами JNZ и JMP |
|
|
(длина программы увеличивается на три байта) |
JNZ |
L0 |
|
JMP |
L2 |
|
L0: MOV |
[ВХ], AL |
|
|
|
; л — другие команды |
L2: |
|
|
Мнемоника команд условных переходов начинается с буквы J (jump), а остальные буквы содержат информацию об условии перехода (см. табл. 4.13). Последние восемь команд услов ных переходов в табл. 4.15 ориентированы на использование после команд сравнения СМР src{, src2, выполняющих операцию сравнения src-] - src2-чисел без знака и со знаком. Эти команды реализуют решения (переходы), опирающиеся на операторы отношений “<”, “<” и
Команды условных переходов выполняются за 16 тактов (переход есть) и за 4 такта (пере хода нет).
I
|
|
4.3. Система команд М П 8086/8088 |
405 |
|
|
Таблица 4.15. Команды условных переходов и циклов |
|
Команды |
|
Назначение команды |
Условие |
переходов |
|
перехода |
|
|
|
||
JE/JZ |
Перейти, если нуль/если равно |
ZF = 1 |
|
JNE/JNZ |
Перейти, если не нуль/если не равно |
ZF = 0 |
|
JS |
Перейти, если знак установлен |
SF = 1 |
|
JNS |
Перейти, если знак сброшен |
SF = 0 |
|
JO |
Перейти, если есть переполнение |
OF = 1 |
|
JNO |
Перейти, если нет переполнения |
OF = 0 |
|
JP/JPE |
Перейти, если есть паритет/если четный паритет |
PF = 1 |
|
JNP/JPO |
Перейти, если нет паритета/если нечетный паритет |
PF = 0 |
|
JB/JNAE/JC Перейти, если ниже/если не выше и не равно (без знака) |
CF = 1 |
||
JNB/JAE/JNC |
Перейти, если не ниже/если выше или равно (без знака) |
CF = 0 |
|
JBE/JNA |
Перейти, если ниже или равно/если не выше (без знака) |
CF v ZF = 1 |
|
JNBE/JA |
Перейти, если не ниже и не равно/если выше (без знака) |
CF v ZF = 0 |
|
JL/JNGE |
Перейти, если меньше/если не больше и не равно (со знаком) |
SF ® OF = 1 |
|
JNL/JGE |
Перейти, если не меньше/если больше или равно (со знаком) |
SF ® OF = 0 |
|
JLE/JNG |
Перейти, если меньше или равно/если не больше (со знаком) |
S F ® O F v Z F = l |
|
JNLE/JG |
Перёйти, если не меньше и не равно/если больше (со знаком) |
SF © OF v ZF = 0 |
|
Команды |
|
Назначение команды |
Условие |
циклов |
|
перехода |
|
|
|
||
LOOP |
|
Зациклить СХ раз (перейти, если СХ / 0) |
cx*o |
LOOPZ/LOOPE |
Зациклить, пока нуль/равно |
CX 9b 0 и ZF = 1 |
|
LOOPNZ/LOOPNE Зациклить, пока не нуль/не равно |
CX Ф0 и ZF = 0 |
||
JCXZ |
|
Перейти, если СХ = 0 |
CX = 0 |
Команды циклов LOOP, LOOPZ/LOOPE и LOOPNZ/LOOPNE. В этих командах в ка честве счетчика циклов используется регистр СХ. Команды двухбайтовые — второй байт пред ставляет собой смещение dispS (число со знаком). Переходы могут быть только типа short (ко роткие) в диапазоне адресов -128 ...+127 байт относительно адреса следующей команды. Пе реходы осуществляются только по меткам. Описание команд циклов приведено в табл. 4.15. Выполняется переход или не выполняется, зависит от состояния счетчика циклов СХ и флага ZF. При переходе выполняются действия:
СХ <— СХ - 1, IP <- IP + dispS.
Команда LOOP выполняется за 17/5 тактов (переход есть/перехода нет), команда
LOOPZ/LOOPE — за 18/6 тактов, команда LOOPNZ/LOOPNE — за 19/5 тактов.
Команды циклов LOOPZ/LOOPE и LOOPNZ/LOOPNE обычно используются после команд СМР и SUB. Применение команды LOOP было дано в задачах 3, 7, 9, 10, 29 и 35.
Команда JCXZ. Эта команда является по существу командой условного перехода, которая проверяет на 0 содержимое регистра СХ. Эта команда отнесена к командам циклов (табл. 4.15), поскольку обычно она применяется в начале цикла, чтобы пропустить тело цикла, когда на чальное содержимое регистра СХ рабно нулю.
Команда JCXZ выполняется за 18/6 тактов (переход есть/перехода нет).
406 |
Глава 4. Микропроцессоры 8086/8088 и сопроцессор 8087 |
|
6. Команды управления процессором |
Команды управления ф лагами CF, DF и IF. Описание семи команд управления флагом переноса CF, флагом направления DF и флагом прерываний IF приведено в табл. 4.13. Флаг направления DF используется в командах манипуляции цепочками, а флаг прерываний IF раз решает (IF = 1) или запрещает (IF - 0) обслуживание запросов прерываний, поступающих на вход 1NTR МП (рис. 4.27).
Изменять состояния флагов SF, ZF, AF, PF и CF (рис. 4.28) можно также с помощью ко манд LAHF и SAHF, выполняющих операции:
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
АН <-~low byte PSW (команда LAHF), |
SF |
ZF |
0 |
AF |
0 |
PF |
1 |
CF |
low byte PSW <r- АН (команда SAHF). |
Рис. 4.28. Младший байт флагов |
|
|||||||
|
Загрузив |
командой LAHF младший |
байт регистра признаков PSW в аккумулятор АН, |
с помощью логических операций AND, OR и XOR можно задать значения любого из пяти фла гов: 0, 1, инверсное либо исходное значение. Затем командой SAHF модифицированные значе ния флагов возвращаются в регистр признаков PSW.
Выполняются команды управления флагами за 2 такта, а команды LAHF и SAHF — за 4 такта.
Команда HLT. Эта команда производит останов МП, переводя его в состояние ожидания сигнала сброса RESET = 1 или сигнала немаскируемого прерывания NMI = 1. После выполне ния команды HLT содержимое регистров CS:IP указывает на команду, следующую за командой HLT. Если в состоянии ожидания значение флага прерываний IF - 1, то работу МП возобнов ляет и по запросу по входу маскируемых прерываний INTR. Команда HLT часто используется в диагностических программах МП-систем.
Команда HLT выполняется за 2 такта.
Команда W AIT. Эта команда переводит МП 8086/8088 в состояние ожидания от арифме тического сопроцессора 8087 активного уровня (0) сигнала TEST = BUSY (см. рис. 4.15). Ко манда WAIT используется для обеспечения синхронизации совместной работы МП 8086/8088 и
NDCP 8087.
Команда выполняется за 3 + 5 х п тактов (п — число циклов ожидания значения сигнала
TEST = 0).
Команда ESC. Данная команда используется для передачи управления от МП 8086/8088 арифметическому сопроцессору 8087. Машинный код команды ESC = llO llx x x является пер вым байтом команд сопроцессора 8087, содержащих от двух до четырех байт. Для обеспечения синхронизации совместной работы МП 8086/8088 и 8087 программист должен перед каждой командой ESC помещать команду WAIT (либо автоматически добавляет транслятор).
Команда ESC выполняется за 2 такта (регистр) и 8 + еа тактов (память).
Команда LOCK . Эта команда является однобайтовым префиксом, который может пред шествовать любой команде. По префиксу LOCK микропроцессор вырабатывает активный уро вень (0) сигнала блокировки шины LOCK на время выполнения команды, непосредственно сле дующей за префиксом. Сигнал LOCK используется в мультипроцессорных системах для аппа ратного управления доступом нескольких МП к общим ресурсам (обычно к общей памяти).
4.4. Директивы ассемблера |
407 |
Вэтом случае сигнал LOCK подается на арбитр системной шины 8289, который запрещает
ееиспользование другими МП до тех пор, пока значение сигнала LOCK - 0.
Воднопроцессорных системах команда с префиксом LOCK делает системную шину на время ее выполнения недоступной для любого внешнего устройства или события, включая за просы прерывания и передачи данных по прямому доступу к памяти.
Команда LOCK выполняется за 2 такта.
Описание системы команд МП 8086/8088 и дополнительные примеры программ на языке ассемблера можно найти в [13 ■+■15].
4.4. Директивы ассемблера
Текст исходной программы на языке ассемблера, называемый исходным модулем, подго тавливается с помощью обычного текстового редактора, имеющегося в дисковой операционной системе {DOS — Disk Operating System). Все символы такого текста представлены вЛ5С//-кодах (см. табл. 1.9 на с. 51). Файлу исходного модуля обычно присваивается имя name.asm (пате — имя, составленное не более чем из 8 допустимых символов).
Общие сведения о язы ке ассемблера. В настоящее время различными фирмами создано много версий ассемблера как программного продукта. Все версии имеют много общего, так как они являются диалектами одного языка ассемблера. Здесь будет кратко рассмотрен Turbo As sembler (TASM) Version 3.2 фирмы Borland International.
Текст исходного модуля на языке ассемблера состоит из операторов ассемблера, каждый из которых занимает отдельную строку этого текста, содержащую не более 128 символов. Име ется два типа операторов: инструкции и директивы. Инструкции при трансляции преобразуют ся в машинные коды, которые исполняются после загрузки в память компьютера загрузочного модуля программы, имеющего расширение .сот или .ехе (сот-программы и ехе-программы или com-файлы и ехе-файлы). Директивы (псевдокоманды) языка ассемблера не преобразуются в машинные коды, а только управляют процессом ассемблирования (трансляции) — преобразо вания текста исходной программы в коды объектного модуля (расширение .obj). Ассемблер интерпретирует и обрабатывает операторы один за другим, генерируя последовательность из машинных кодов команд МП и байтов данных.
Запись инструкции на языке ассемблера состоит из четырех полей в свободном формате: поля метки, поля кода операции (КОП), поля операндов и поля комментария:
[Метка:] |
КОП |
[Операнд 1 [, Операнд2]] |
[; Комментарий] |
<- |
Инструкции ассемблера |
[Имя] |
Директива |
[Выражение] |
[; Комментарий] |
<— |
Директивы ассемблера |
(элементы, указанные в квадратных скобках, могут отсутствовать). Метка — это идентифика тор, присваиваемый первому байту того оператора, в котором она появляется, а КОП — это мнемоническое обозначение инструкций (команд) МП. Для директив ассемблера эти ноля на зываются полем имени, полем директивы, полем выражения и полем комментария соответст венно. Операнды M oiyr описываться выражениями, составленными из чисел и символических имен с помощью операторов выражений. Пробелы вводятся произвольно (свободный формат), но минимум один пробел должен быть после кода операции. В двухоперандных командах опе ранды должны быть разделены запятой, а поле комментария должно начинаться с точки с запя той.
Директивы ассемблера действуют лишь во время компиляции программы и позволяют устанавливать режимы трансляции, задавать структуру сегментирования программы, опреде
408 Глава 4. Микропроцессоры 8086/8088 и сопроцессор 8087
лять содержимое полей данных, управлять печатью листинга программы, обеспечивать услов ную трансляцию и выполнять некоторые другие функции.
Конструкции языка ассемблера содержат идентификаторы и ограничители. Идентифика тор представляет собой набор букв, цифр и символов ?, $, % или &, не начинающийся
сцифры. Идентификатор должен полностью размещаться на одной строке и может содержать от 1 до 31 символа. Друг от друга идентификаторы отделяются пробелом или ограничителем, которым считается любой недопустимый в идентификаторе символ (например, запятая, точка
сзапятой, двоеточие, круглые и квадратные скобки). Посредством идентификаторов представ ляются переменные, метки и имена.
Переменные идентифицируют хранящиеся в памяти данные. Все переменные имеют три атрибута: SEGMENT — сегмент, соответствующий тому сегменту, который ассемблировался, когда была определена переменная; OFFSET — смещение, являющееся адресом данного поля памяти относительно начала сегмента (относительным адресом); TYPE — тип данных, опреде ляющий число байтов, с которыми производятся операции при использовании переменной.
Метка является частным случаем переменной, когда известно, что определяемая ею па мять содержит машинный код инструкции МП. На нее можно ссылаться в командах переходов и вызовов процедур. Метка имеет два атрибута: SEGMENT и OFFSET. Метка для команд пере
ходов в поле метки должна заканчиваться двоеточие^. ; Имена не идентифицируют данных в памяти, а используются в программе только для ука
зания замены их при трансляции присвоенным им директивами = или EQU значением. Некоторые идентификаторы, называемые ключевыми словами, имеют фиксированный
смысл и должны употребляться только в соответствии с этим. Такими словами являются: ди рективы ассемблера, инструкции и имена регистров МП, операторы выражений и типы данных (табл. 4.16 — инструкции МП не включены). Ключевые слова нельзя использовать для иденти фикации переменных, меток и имен.
Операнды, представляющие собой числа, должны обязательно начинаться с цифры (на пример, 0Е8431г), а идентификаторы операндов (символические имена) — с буквы. Для обозна
чения систем счисления служат буквы: |
|
|
|
. |
- |
|
||||
|
|
|
Таблица 4.16. Зарезервированные имена |
|
|
|
||||
|
Имена регистров, мнемоники директив, операторов и атрибутов |
|
||||||||
.8086 |
and |
CS |
dx |
.errb |
far |
ifidn |
local |
org |
seg |
tbyte |
.186 |
assume |
cx |
else |
.errdef |
ge |
ifnb |
low |
%out |
segment |
.tfcond |
.286 |
ах |
db |
end |
.errdif |
group |
ifndef |
It |
page |
.sfcond |
this |
.386 |
bh |
dd |
endif |
.erre |
gt |
include |
macro |
proc |
shl |
title |
.486 |
bl |
dh |
endm |
.erridn |
high |
irp |
mask |
ptr |
short |
type |
.8087 |
bp |
di |
endp |
.ermb |
if |
irpc |
mod |
public |
shr |
.type |
.287 |
bx |
dl |
ends |
.ermdef |
ifl |
label |
name |
purge |
si |
width |
.387 |
byte |
dq , |
eq |
..errnz |
if2 |
.lall |
ne |
qword |
size |
word |
.487 |
ch |
ds |
equ |
es |
ifb |
le |
near |
.radix |
sp |
.xall |
= |
cl |
dt |
.err |
even |
ifdef |
length |
not |
record |
ss |
•xcref |
ah |
comment |
dw |
.errl |
exitm |
ifdif |
.lfcond |
offset |
rept |
struc |
.xlist |
al |
.cref |
dword |
.err2 |
extm |
ife |
.list |
6r |
sail |
subttl |
xor |
4.4. Директивы ассемблера |
409 |
Вили b — двоичная система счисления,
Оили Q (о или q) — восьмеричная система счисления, D w m d — десятичная система счисления,
Н или h —■16-ричная система счисления
(по умолчанию принимается десятичная система счисления, т. е. указатель d можно опускать). В тексте программы на языке ассемблера можно использовать как прописные, так и строчные буквы — ассемблер их не различает.
Ассемблирование, компоновка и отладка программ. Для преобразования исходного модуля в загрузочный модуль, выполнимый на персональном компьютере IBM PC, можно ис пользовать, например, системный программный пакет Turbo Assembler Version 3.2 фирмы Bor
land International. В этот пакет входят программы: |
|
tasm.exe (Turbo Assembler) — ассемблер, транслирующий |
исходный модуль name.asm |
в машинные коды и генерирующий файлы name.obj, пате.1st |
и пате.тар ; файл name.ob] |
(объектный модуль) используется программой tlink.exe для создания загрузочного модуля; файл пате.1st — листинг результата трансляции с указанием всех обнаруженных ошибок, по могающий исправить текст исходного модуля (листинг содержит и текст исходной програм мы); файл пате.тар содержит карту распределения памяти, используемой создаваемой про граммой;
tlink.exe (Turbo Link) — компоновщик, создающий из одного или нескольких объектных модулей загрузочный модуль пате.ехе или пате.сот;
td.exe (Turbo Debugger) — отладчик, позволяющий выполнять программу частями и в пошаговом режиме для обнаружения неуловимых другими средствами ошибок в разрабаты ваемой программе (доступно для анализа — выводится на экран — содержимое всех регистров, флагов и используемой памяти).
Объектный модуль генерируется при запуске из командной строки команды tasm.exe name.-dsm /L
(генерируются файлы пате.оЬ], пате.Ы и п яте.тар ; при отсутствии параметра /L файл пате.1st не создается). Загрузочные модули пате.ехе и пате.сот генерируются при запуске из команд ной строки команд
tlink.exe name.oh) [/Tde] и tlink.exe пате.оЦ /Tdc
соответственно (для генерации загрузочных модулей пате.ехе и name.com исходные модули name.asm должны быть подготовлены в различных формах). Если вместо параметра /Tdc задать параметр /Tdd, то будет создан файл name.dll (dll — Dynamic Link Library — динамически под ключаемая библиотека для программ, выполняемых под управлением Windows). Для запуска отладчика необходимо последовательно выполнить команды
tlink.exe name.obj N и td.exe name.ext
(первая команда генерирует файл пате.ехе, а вторая запускает отладчик; параметр N дает ука зание компоновщику ввести в файл пате.ехе дополнительную информацию, необходимую для работы отладчика).
Исходный модуль и листинг ехе-программы. В примере 1 приведен отредактированный (исключена несущественная информация и добавлен заголовок) листинг программы, не содер жащей ошибок. Из полученного при ассемблировании объектного модуля может быть получен загрузочный модуль — ехе-файл, выполнимый на персональном компьютере IBM PC.
Пример 1. Программа вычисления суммы и разности 8-разрядных десятичных чисел X и У, вводимых с клавиатуры, с выводом результата Z на дисплей: