МП 68000 позволяет использовать почти все режимы адресации и размеры операндов с любой командой ("Справочное пособие программиста МП 68000" исчерпывающе описывает все допустимые сочетания; наиболее полезная информация собрана в табл. 11.2). В результате написание изящных и эффективных программ на языке ассемблера оказывается относительно простой задачей. Например, работая с МП 8086 и желая проанализировать состояние флага порта ввода-вывода, вы должны будете сохранить и восстановить содержимое регистра AL и в сумме использовать 5 команд (PUSH, IN, TEST, POP, Jcc). МП 68000 позволяет выполнить ту же операцию с помощью всего двух команд: BTST и Всс; никакие регистры не нужны, потому что бит памяти (и, следовательно, регистры порта) можно проанализировать непосредственно. Более того, "автоинкрементный" режим адресации вроде "(А2) +" дает возможность работать с массивами. Хотя мы еще не описали все режимы адресации и команды, вы вполне сможете выполнить следующее упражнение.
Упражнение 11.1. Скопировать массив длиной $100 байт из таблицы, начинающейся в ячейке $А0000 в таблицу, начинающуюся в ячейке SA8000. При решении этой задачи будет полезна команд WGT метка (переход если больше нуля).
Режимы адресации. В приведенных выше примерах команд операции выполнялись над константами, содержимым регистров и содержимым ячеек памяти (или портов). Архитектура МП 68000 предусматривает богатый набор "режимов адресации" для определения этих операндов. В табл. 11.3 перечислены 12 режимов адресации, которые рассматриваются фирмой Motorola как 14. Вот что они значат:
Регистровая прямая адресация
Синтаксис: Dn (или An)
Пример: MOVE.W D0,D1
Операндом является содержимое указанного регистра
Непосредственная адресация
Синтаксис: #хххх
Пример: MOVE.B #$FF,D0
Операндом является указанная константа
Абсолютная адресация к памяти
Синтаксис: xxxx.W или xxxx.L
Пример: ADD.W D0JB000.W
Адрес операнда указан как непосредственная константа
Косвенная адресация
Синтаксис: (An)
Пример: SUB.W D0, (А0)
Указанный регистр содержит адрес операнда
Косвенная постинкрементная адресация
Синтаксис: (Аn) +
Пример: MOVE.B (А0) +, (А1) +
Аналогична косвенной, но после выполнения операции An инкрементируется на величину размера
Косвенная предекрементная адресация
Синтаксис: - 1Аn)
Пример: MOVE.W D0,-(A7)
An сначала декрементируется на величину размера, затем выполняется косвенная адресация
Косвенная адресация со смещением
Синтаксис: d16(An)
Пример: MOVE.L (А0),100(А0)
Адрес операнда определяется как (An) плюс 16-разрядное знаковое смещение d16
Косвенная индексная адресация со смещением
Синтаксис: d8(An,Xn.W [или. L]) (Хn может быть либо Dn, либо An)
Пример: MOVE.L 100(A0),100(A0,D7)
Адрес операнда определяется как (An) плюс (Хп) плюс 8-разрядное знаковое смещение d8
PC-относительная адресация со смещением
Синтаксис: d16(PC)
Пример: LEA 100(РС), АЗ
Адрес операнда отличается от адреса этой команды на величину 16-разрядного знакового смещения
PC-относительная адресация с индексом и смещением
Синтаксис: d8(PC,Xn.W или. L)
Пример: MOVE.W 100(PC,D0.W),D1
Адрес операнда отличается от адреса этой команды на величину суммы 8-разрядного знакового смещения и содержимого Хn.
Несколько пояснений: в первых двух режимах не адресуется память; адресуются регистры или непосредственные константы (т. е. константы, включенные в поток команд; они могут быть только источниками, но никогда не приемниками). Все остальные режимы служат для адресации памяти. Абсолютная адресация удобна для обращения к портам ввода- вывода или к отдельным ячейкам памяти.
Косвенная (особенно с постинкрементом или предекрементом) хороша для работы с массивами или стеком; кроме того, если адрес уже находится в адресном регистре, такая адресация быстрее абсолютной, так как при выполнении команды адрес (абсолютный) не требуется извлекать из памяти. PC-относительные режимы адресации особенно удобны при написании "позиционно-независимых" программ, поскольку все адреса определяются относительно самих программных строк; заметьте, что 8- и 16-разрядные смещения представляют собой знаковые целочисленные дополнения до 2, позволяя описывать ячейки, отстоящие от точки отсчета на ±127 или ±32767 байт соответственно. Обратите еще внимание на то, что непосредственные или РС-относительные операнды нельзя модифицировать (они "неизменяемы").
11.03. Представление команд на машинном языке
Как уже упоминалось выше, язык ассемблера, использованный нами в примерах, не является "объектным кодом", фактически выполняемым микропроцессором. Скорее это мнемоническое представление, удобное для написания программ. Последовательность команд языка ассемблера, составляющая программу, должна быть преобразована в последовательность двоичных байт, выполняемых процессором. Как и в случае МП 8086, каждая команда языка ассемблера МП 68000 преобразуется (ассемблируется) в несколько байт машинного кода. Код операции (коп) всегда занимает 2 байт, но в тех случаях, когда требуется определить режимы адресации, к нему могут добавляться дополнительные слова (двухбайтовые). В зависимости от вида операции и режимов адресации команда может иметь длину от 2 до 10 байт. Например, команда
ADD.W (A1) +,D3
ассемблируется в код минимальной длины (2 байта), именно (D6 59)н, причем и номера регистров, и режимы адресации указываются (вместе с кодом операции) в самой 2-байтовой команде. С другой стороны, команда MOVE.W $FFFF,$A0000 ассемблируется в 8-байтовый код, а именно (33 FC FF FF 00 0А 00 00)н, причем в первых двух байтах указываются операция и режимы адресации, в следующих двух байтах - непосредственная константа, а в последних четырех байтах - абсолютный адрес (длинный) приемника.
ЦП, естественно, по самой своей конструкции умеет интерпретировать этот результирующий машинный код. Рассмотрение структуры машинного кода конкретной команды может помочь вам в понимании логики работы ЦП. На рис. 11.2 развернута структура самой употребительной команды МП 68000 MOVE.