Глава 4. Обзор команд микропроцессора 8088/8086.

МЕФИСТОФЕЛЬ

О, все пойдет па лад: В редукцию лишь надо вникнуть К классификации привыкнуть.

Фауст. Гете.

Наберитесь терпения: данная глава будет посвящена обзору команд микропроцес­сора 8088/8086. Для тех, кто легко ориентируется в командах, приведенных в Прило­жении 1, эту главу можно опустить. Обзор будет достаточно кратким, т.к. о свойствах части команд Вы узнаете из приведенных далее программ. Сведения о командах, не нашедших отражения в главах, можно найти в Приложении 1. Впрочем, в данной гла­ве Вы сможете также найти полезные фрагменты и программы.

Еще раз напомню, что речь идет о множестве команд микропроцессора 8088/8086. О микропроцессорах 80386 и выше с 32-битной арифметикой Вы прочтете в главе 20. Однако все микропроцессоры указанного семейства работают с этим набором команд. Более того, в большинстве случаев 32-битную арифметику нет никакой нужды ис­пользовать, т.к. для большинства переменных целого типа 16 бит вполне достаточно.

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

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

В главе 2 мы уже познакомились с командами пересылки в память из регистров микропроцессора и обратно. Можно обмениваться данными между регистрами: MOV АХ,ВХ; MOV CL,DH и т.п. В регистры или память можно непосредственно загружать числа (байты или слова): MOVCX,2000; MOVM1,80. Относительно последней ко­манды надо сказать следующее: Вы должны четко представлять, куда засылается чис­ло 80 - в слово или в байт. Это зависит от того, как определена метка Ml - DB или DW

(говорят об атрибуте ячейки памяти, на которую указывает Ml). Если это слово, то

тогда старший байт будет автоматически обнуляться. А если Вам нужно переслать число так, чтобы не затронуть старший байт, тогда пишите MOV BYTE PTR Ml,80, если хотите переслать это число в старший байт, воспользуйтесь командой MOVBYTE PTRMl + 1,80.

В наших программах Вы встречали командутипа MOVAX,DSEG - DSEG - это метка начала сегмента. Здесь ассемблер знает, о чем идет речь, и в АХ загружается сегментный адрес,      то, что лежит по этому адресу. Получить сегментный адрес можно и другимспособом. Если метка THERE находится в некотором сегменте, то, для того чтобы полу­чить сегментный адрес, достаточно вьтолнить команду MOVAX,SEG THERE.

Для загрузки в регистр смещения какой-либо ячейки (адреса в сегменте) исполь­зуют команды LEAAX,THEREmh MOVAX,OFFSETTHERE. В программахя наме­ренно использую ту, и другую команды.

Очень удобна команда LES. Например, LES DX,KONEC заменяет сразу две ко­манды:

MOV

MOV ES,KONEC+2

Аналогично ведет себя команда но по отношению к регистру Б& Заметим, что в [3] дается неправильная трактовка двух последних команд.

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

П\Г   АЬ,15Н ; загрузить в АЬ байт из порта 15Н

ПЧ   АХ,БХ /загрузить в АХ слово из порта с номером из БХ

ОиТОХ,АХ /аналогично, но из порта в АХ

ОиТБХ,АЬ /загрузить байт в порт, адресуемый регистром БХ

и т.п. С портами мы еще встретимся в последующих главах. Описание портов и методов работы с ними см. в Приложении 9.

Со стековыми командами Выуже познакомились. Неупоминались только коман­ды РиЭНР - загрузить в стек регистр флагов, РОРР - выгрузить из стека регистр фла­гов. Интересно, что теперь появляется возможность загрузить свое слово в регистр флагов:

PUSH ВХ POPF

таким образом, содержимое регистра ВХ оказывается в регистре флагов. Но будь­те этим изучите, какой в этом регистре что отвечает. Су­ществуют еще команды ІАІТЕ и 8АНЕ (см. Приложение 1), но я не советовал бы их использовать. Они устарели даже для микропроцессора 8086/8088.

Команда ХЕАТ очень удобна для проведения табличных преобразований. Пусть в Б8:ВХ содержится указатель на некоторую таблицу байт. В АЕ помещается номер байта в таблице. В результате выполнения команды ХЕАТ в АЕ будет помещен байт с заданным номером.

II. Команды передачи управления.

К командам передачи управления относятся команды, меняющие региструказате-ля команд ІР. Другим способом изменить содержимое регистра ІР невозможно. Рас-сначала команды, не затрагивающие содержимое стека, это всевозможные переходы.

JMP SHORT L1 - короткий переход. Длина команды два байта. Поэтому переход осуществляется в пределах 128 байтов (ниже и выше команды).

JMP L1 - длинный переход. Осуществляется в пределах одного сегмента. Длина команды три байта. Возможен также косвенный переход типа JMP [ВХ]-переход по адресу, который лежит в ячейке, определяемый содержимым регистра ВХ. Такой пе­реход называется внутрисегментным.

Межсегментный переход. Работу такой команды демонстрирует программа на Рис. 4.1.

CODE SEGMENT ASSUME

ORG   100H . . .

BEG:

JMP  SHORT BEGIN ;короткий переход

; адрес в ПЗУ,   по которому ;находится программа  сброса системы LI      DW OFFFOH ;смещение

OFOOOH

BEGIN:

DWORD PTR переход

CODE ENDS END BEG

Рис. 4.1. Программа, демонстрирующая межсегментный переход.

После выполнения этой программы возникнет ситуация, аналогичная той, кото­рая создается при нажатии кнопки RESET. Возможен и косвенный межсегментный переход. Замените JMP DWORD PTR L1 на две команды:

LEA

JMP DWORD PTR CS:[DI]

и получившаяся программа будет приводить       же результатам,     и предыдущая.

Все команды условного перехода являются короткими. Они приведены в Прило­жении 1, и мы не будем их перечислять. Разберем лишь одну ситуацию. Рассмотрим

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

INT 21H

JC   ERROR ; перейти,, если функция DOS выполнилась с ошибкой

ERROR:

В процессе доработки программы количество байт между командой JC и меткой ERROR может увеличиться и превзойти 128 байт. Тогда ассемблер будет давать сообще­ние об ошибке. Такие ошибки могутдоставить Вам много беспокойства, если подобных меств программе несколько. Обойти эту ситуацию можно следующим образом:

INT 21H

JNC NO_ERROR

JMP ERROR NO ERROR:

ERROR:

При выполнении команды условного перехода микропроцессор непосредственно обращается к регистру флагов и в зависимости от состояния соответствующих бит выполняет эту команду. В частности, команды JC и JNC выполняются в зависимости от того, чему равен флаг четности (С, см. главу 3). Циклы на ассемблере можно орга­низовывать как с помощью команд перехода по условию, там с помощью специали­зированной команды LOOR Данная команда использует регистр СХ как счетчик числа циклов. На Рис.4.2 показана схема организации вложенных циклов. На Рис.4.2 пред­ставлены два вложенных цикла, но потойже системе циклов можно сделать и больше. Не надо только забывать, что LOOP дает короткий переход. Разновидности команды LOOP см. в Приложении 1.

MOV СХ,10       ; счетчик внешнего цикла LOOP1:

PUSH СХ

MOV    СХ,100   ;счетчик внутреннего цикла LOOP2:

PUSH СХ

POP СХ LOOP LOOP2 POP СХ

LOOP LOOP1

Рис. 4.2. Организация вложенных циклов.

Рассмотрим теперь команды, связанные с изменением стека. Прежде всего, это команда обращения к подпрограмме (процедуре). Эта команда может длинной - внут­рисегментный переход и межсегментный. Длинный CALL кладет в стек адрес возвра­та (смещение). Возврат из процедуры реализует команда RET. Она извлекает из стека адрес возврата (два байта) и осуществляет длинный переход по указанному адресу. Если процедура имеет атрибут FAR (даже если процедура находится в том же сегмен­те, что и команда, ее вызывающая), то вызов будет дальним или межсегментным. При этом в стек будет занесен четырехбайтный адрес. Вначале заносится сегментный ад­рес, а затем смещение. При этом команды RET, стоящие в пределах данной процеду­ры, становятся межсегментными, т.е. выталкивают из стека четыре байта. У них и отдельная мнемоника RETF. Отсюда Вам должно быть уже ясно, какую роль играют отметки начала и конца процедуры. Итак, RET может оказаться и внутрисегментным и межсегментным, т.е. превратиться в RETF. RETF же всегда RETF. Для внутрисег­ментного перехода имеется и своя мнемоника RETN. Отмечу также, что если атрибут FAR указать при вызове (CALL FAR SORT), то вызов будет межсегментным, но команды RET, стоящие внутри процедуры, не будут преобразованы к RETF. Следую­щая программа (Рис. 4.3) демонстрирует работу RETF. Результат ее работы аналоги­чен результату работы программы на Рис. 4.1.

CODE SEGMENT

ASSUME CS:CODE

BEG:

JMP   SHORT BEGIN /адрес в ПЗУ,   по которому /находится программа   сброса системы LI       DW OFFFOH       /адрес в  ПЗУ подпрограммы сброса

DW OFOOOH BEGIN:

PUSH Ll+2

PUSH Ll

RETF /переход на  подпрограмму RESET

CODE ENDS

END BEG

Рис. 4.3. Пример использования RETFeMecmo JMP.

III. Команды арифметических операций.

Команды арифметических операций сводятся к выполнению четырех арифмети­ческих действий: сложения, вычитания, умножения, деления. Команды сложения и вычитания разберем на примерах. На Рис. 4.4 показан фрагмент сложения двух опе­рандов OPER1 и OPER2. Результат помещается в SUM. Проблема заключается в том, что операнды имеют длину 4 байта. Обратите внимание на использование команды ADC. Она автоматически учитывает возникновение переноса из последнего бита (еложение с учетом флага переноса). Само собой разумеется, мы предполагаем, что ре­зультат не будет превосходить 4 байта. , :

MOV АХ, WORD PTR OPERl ADD АХ, WORD PTR 0PER2 MOV WORD PTR SUM, AX MOV AX, WORD PTR OPER1+2 ADC AX, WORD PTR OPER2+2 MOV WORD PTR SUM, AX

/поместить первое слово OPER1 /сложить с первым словом OPER2

/поместить в первое слово SUM /поместить второе слово OPER1 /сложить со вторым словом OPER2

/поместить во второе слово SUM

Рис. 4.4. Сложение двухчетырехбайтныхоперандов. Следующий фрагмент (Рис.4.5)демонстрирует аналогичнуюработу команд SUB и SBB.

MOV АХ, WORD PTR OPERl SUB AX,WORD PTR OPER2 MOV WORD PTR SUM, AX MOV AX, WORD PTR OPERl+2 SBB AX, WORD PTR OPER2+2 MOV WORD PTR SUM, AX

/поместить первое слово OPER1 /вычесть первое слово OPER2 /поместить в первое слово SUM /поместить второе слово OPER1 /вычесть второе слово OPER2 /поместить во второе слово SUM

Имеется две команды умножения: чисел без знака и чисел со знаком. Читателю должно быть ясно, что алгоритм умножения должен измениться, если

старший бит считать знаковым. Вот несколько примеров:

MUL DX   /умножить DX на АХ без знака, результат в DX:AX

IMUL BYTE PTR МЕМ1   /умножить содержимое ячейки МЕМ1 на AL со знаком,

/результат поместить в АХ

MUL BL содержимое регистра      на результат в АХ.

Таким образом в зависимости от того, какого типа операнд стоит в команде умноже­ния (байт или слово), умножение будет произведено над байтом (AL) или над словом (АХ). Соответственно результат умножения будет помещен в АХ или DXAX. После исполнения команды МиЕфлаги CFh OF равны 0, если старшая половина произведе­ния (байт или слово) равна нулю. В противном случае оба флага равны 1. После выполнения команды IMUL флаги     и OF равны О, если старшая половина произведения представляет собой лишь расширение знака младшей, В противном случае они равны 1. Командыделения аналогичны командам умножения. Вот несколько примеров.

DIV СХ /разделить DX:AX без знака, результат в АХ, остаток в DX IDIV BYTE FTR МЕМ1    .-разделить AH:AL на содержимое ячейки МЕМ1

результат в AL, остаток в DIV DL /разделить AH:AL на DL без Знака, результат в AL, остаток в АН.

Командыделения осташшотсостояниефлаговнеопределенньїм. I ели часті к >е і ю поме­шается is регистр-приемник, то генерируется прфывание 0 - на экране появляется надпись Divide overflow. При этом дальнейшее вьшолнение программы прерывается. Карифмети-ческимкомандамотносятсяещеШС,ОЕС,№^

Команды расширения знака позволяют выполнять смешанные действия - байта со словом, слова с двойным словом. CBW воспроизводит 7-й бит регистра AL в регистр АН. воспроизводит       бит регистра АХ во всех битах регистра DX.

Особо следует сказать о выполнении арифметических операций над BCD числами. Напомню читателю, что это такое. Упакованное BCD число представляется последова­тельностью полубайт. Каждый полубайт содержит соответствующую цифру. Например, число 87Нв упакованном BCD представлении есть просто 87 (десятичное!). Неупакован­ный BCD формат представляет собой последовательность байт, где каждый байт пред­ставляет одну цифру. Если к каждому такому байтудобавить 48, то мы получим фактичес­ки цепочку символов, отображающих данное число. Такой формат называют еще ASCII форматом. Микропроцессор, естественно, незнает, надкакимчисломонпроизводитдей-ствие. Для него все числа двоичные. Но есть команды, которые корректируют результат, такчтооноказываетсяправильным. Перечислим эти команды. Коррекция сложения:

ААА - для неупакованных чисел, DAA - для упакованных чисел.

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

результат находится в AL. Коррекция вычитания:

AAS - для неупакованных чисел, DAS - для упакованных чисел.

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

ААМ - для неупакованных чисел.

Команда выполняется после команды байтового умножения. Команда деления:

AAD -       неупакованных чисел.

Команда выполняется до (!) операции деления. Корректирует неупакованное де­лимое, находящееся в АХ, в двоичное число в AL, так чтобы результат оказался пра­вильным.

IV. Операции над отдельными битами.

К операциям над битами мы относим как логические команды типа AND и OR, так и различные сдвиговые команды. Логические команды выполняются побитно. Ус­ловно можно считать, что 0 - это ложь, а 1 - истина. Все остальное достаточно триви­ально. Например:

MOVAL, 0101111В MOV DL, 1001001В MOVBL, 0001111В MOVCL, 1111000В AND AL, DL

OR DL,BL XOR BL,CL

После выполнения данных команд в регистре AL будет 0001001 В, в регистре DL -1001111В, в регистре BL -1110111В. Разберитесь в этом. Команда XOR очень удобна для кодировки. Если в Вашей программе есть текстовые строки, то после трансляции, естественно, эти строки останутся в коде программы. может соблазнить

исправление этих строк (это можно сделать даже в простом текстовом редакторе, и

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

выход достаточно прост - закодируйте часть программы, где находятся строки. При запуске профамма сама раскодирует нужные данные. Кодировку и раскодировку можно произвести с помощью одной и той же команды XOR. Легко проверить, что дважды примененная команда XOR не меняет значения операнда. Команду XOR применяют также для обнуления регистров. Причем команда XOR АХ,АХ предпочтительнее MOV АХ,0, т.к. она короче и быстрее выполняется. Команда OR замечательна тем, что при несовпадении битов двух операндов, она равносильна сложению.

Все сдвиговые операции можно подразделить натри класса - знаковые, беззнаковые (арифметические и логические) и циклические. Сдвиговые операции имеют многочис-ленноеприменение,ивдальнейшемяприведунесколькопримеров.Здесьжеяукажуна наиболее часто используемое применение - использование операций сдвига для умно­жения и деления. Часто можно написать процедуру, используя команды сдвига, которая будет выполнять умножение или деление быстрее, чем с использованием стандартных команд МЦЪилиОРУ. Например, умножение на Ібсведется просто ккомандам:

МОУ АХ, 456    /число 456

МОУСЬ, 4        ; сдвиг на четыре бита

БНЬ АХ,СЬ      /сдвигаем,  т.е.  умножаем на 16

Аналогично можно осуществить деление. В том случае, если делитель или мно­житель не является степенью числа 2, умножение или деление можно свести к комби-нациямсдвиговыхоперацийиопераций сложения или вычитания. Предположим, Вы хотите умножить число на 130.Но 130=128+2. Следовательно, фрагмент про­граммы мог бы иметь следующий вид:

MOVAX,NUM MOVCL, 7 SHL AX,CL MOV BX,NUM SHL BX, 1 ADD AX, BX ADD AX, NUM

;число

; сдвигаем на 7 бит

/умножаем на 128

/умножаем на 2 /получили число  * на 130 /получим окончательный результат

Еще одна область применения сдвиговых операций - выделение отдельных групп бит в числе. Рассмотрим следующий пример. Предположим, в байте, содержащемся в регистре АЕ, старшие три бита определяют некоторую величину. Чтобы выделить эту величину удобно использовать сдвиговую операцию. Например, SHRAЕ,5. Если Вы не хотите потерять и другие биты, то можно действовать следующим образом:

Рч011 АЕ, 3 ; 3 старших бита стали младшими

МОУАН,АЬ. /сохранить число

АМОАЬ, 00000111В /выделить биты

8НЯАН,3 /выделяем остальные биты

V. Строковые команды.

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

REPE/REPZ REPNE/REPNZ

Префиксы повторения заставляют микропроцессор повторять строковую коман­ду, пока содержимое регистра СХ не станет равным нулю (ЯЕР) или тока не произой­дет одно из двух событий - СХ=0или флагг= 1 (г=0 для префиксов БШРКЕ/ЫЕР^). Через косую черту перечисляются команды-синонимы. Префиксы КЕРЕЛШР^ РчЕРМЕ/ ЯЕРК^ используются только с командами сравнения и поиска (сканирования), пре­фикс ЯЕР - с остальными строковыми командами.

Несколько общих замечаний. Строковые команды работают с целыми строками -байт или слов. Строка может быть источником или приемником. Предполагается, что строка-источник находится в сегменте, адресуемом регистром DS со смещением в SI, а строка-приемник находится в сегменте, адресуемом регистром ES, со смещением в DI. При выполнении команды содержимое регистров изменяется на 1 (байтовые строки) или на 2 (строки слов). Если флаг ОР=нулю, то содержимое индексных реги­стров увеличивается, если то содержимое индексных регистров умень­шается. Изменить значение флага БЕ можно с помощью команд СШ - сбросить флаг, 8ТБ - установить флаг направления. Каждая из строковых команд имеет по три моди­фикации: с окончанием 'В* байтовая команда, с окончанием '\У- команда работы со строками слов, безокончания. Команда,несодержащаяокончания,приассемблиро-вании преобразуется ккомандес окончанием. О том, к какой команде преобразовы­вать, ассемблер узнает по наличию в команде операндов. Если операнд определен че­рез DB, то команда становится байтовой, если через то команда оперирует со словами. Например,

REP

Если DEST и SOURCE (одновременно) определены через DW, то команда MOVS сведется к MOVSW. Не рекомендуется использовать команды без окончания, идалеев изложении их не будет. Наконец, замечу, что поскольку счетчик находится в регистре СХ, то максимальная длина обрабатываемых строк не должна превышать 64К.

Команды пересылки - MOVSB и MOVSW. В следующем фрагменте происходит пересылка строки байт из SOURCE в DEST. Количество пересылаемых байт равно 200. Во время пересылки значение индексных сегментов увеличивается.

CLD

MOV

LEA SI,DS:SOURCE LEA DI,ES:DEST

REP MOVSB

Обращаю Ваше внимание на команды загрузки адреса в индексные регистры. В случае с 81 можно было явно не указывать сегментный регистр - это подразумевается по умолчанию. В случае же С DI указание сегмента необходимо. Естественно, что если содержимое сегментных регистров DS и ES совпадает, то пересылка осуществляется в пределах одного сегмента. Причем если строки находятся в дополнительном сег­менте (сегменте, на который указывает Е8), то изменять содержимое регистра не по­надобится. Достаточно написать ЕЕА81,Е8:801ЖСЕ. Однако если обе строки нахо­дятся в сегменте данных, то придется менять значение Е8.

Команды сравнения строк - СМР8В и СМР8\¥. Рассмотрим фрагмент:

STD

MOVCX, 100 LEA SI, DS:SOURCE LEA DI,ES:DEST REPNE CMPSW

В представленном примере сравниваютсядве строки - SOURCE и DEST. Сравне­ние осуществляется с конца, при этом значение индексных регистров уменьшается. Сравниваются слова - всего 100 слов. Выход из цикла происходит либо при СХ=0, либо при нахождении совпадающих элементов. При этом, если были найдены совпа­дающие элементы, флаг2= 1. Таким образом, используя команду

JNZ NO_FOUND ;не обнаружено,  если Z=0

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

Команды сканирования строк - SCASWhSCASB. Осуществляют поиск элемента в строке. На строку указывает регистр DI. Рассмотрим конкретный пример.

СЕБ

МОУСХ,200 /просматриваем 200 слов

ЕЕАВ1,5ТК1ЫС     ;Ы указывает на строку МОУАХ,7890Н      /слово для поиска кЕРИЕ ЭСАЗЮ

Фрагмент осуществляет поиск в строке слова 7890Н. Если слово найдено, то сме­щение следующего За ним слова будет возвращено в ТЯ. При этом флаг нуля Ъ будет равен

Команды загрузки и сохранения - ЕОВ8В,ЕОБ8\¥,8Т08В,8Т08\¥. Команда заг­рузки ЕОБ8В (ЬООБМО пересылает байт (слово), адресованный 81 в АЕ (АХ), а затем изменяет регистр 81 согласно флагу направления. Команда сохранения 8Т08В (8ТО8В) пересылает байт из АЬ (АХ) в элемент строки, адресуемый БТ, затем изменяет содер­жимое регистра БІ согласно флагу направления. Рассмотрим фрагмент копирования строки. Пусть указывает на начало строки, БІ - на область, куда она копируется, например, экран. В случае экранной памяти следует помнить, что каждому знакомес­ту соответствует два байта - код символа и его атрибут. Соответственно В8 указывает на сегмент, где находится строка, а - на сегмент, куда она копируется; СХ содержит количество символов в строке:

Данные строки полностью эквивалентны следующим при условии соответствую­щей установки флага направления (DF):

L1:

MOV AL, [SI] MOVES: [DI],AL

Завершая разговор о строковых командах, рассмотрим текст следующей програм­мы. Эта программа копирует часть себя за кодовый сегмент (СОМ-программа) и пере­дает на нее управление. Отработав, фрагмент возвращает управление в основную про­грамму.

CODE SEGMENT

ASSUME CS-.CODE

ORG 100H BEGIN:

JMP BEG

TEXT1  DB   'Я за текущим сегментом', 13,10, '$ ' TEXT2   DB   'Я снова в текущем сегменте',13,10, 1 $' WHE      DW ? ; здесь хранится адрес,

DW ? ;с которого будет загружен фрагмент

L1:

LODSB

STOSB

LOOP Ll

INC DI INC SI

LOOP L1

BEG:

MOV

ADD АХ,1000Н

/максимальная длина сегмента в параграфах

MOV

MOVDI,0 MOV WHE,DI

на куда копируем фрагмент

;сохраним

MOV WHE+2,ES

адрес'.,.. . /смещение копируемого фрагмента

LEA

MOV CX,L2-L1+1    .   ;длина копируемого фрагмента

CLD . . ' .'

REP MOVSB ; копируем фрагмент

CALL DWORD PTR WHE /межсегментный переход на фрагмент

JMP L2 /копируемый фрагмент L1:

LEA DX,TEXTl MOV АН,09Н

INT 21H

RETF ;возвращаемся в основную программу

/конец  копируемого фрагмента L2:

LEA DX,TEXT2 MOV АН,09Н

INT 21H MOV АН,4CH

INT 21H CODE ENDS

END BEGIN

Puc. 4.6. Программа, демонстрирующая работу команды MOVSB.

В начале работы СОМ-программы все сегментные регистры направлены на теку­щий сегмент (для ЕХЕ-программ это неверно, и мы позднее будем об этом говорить). Внимательно разобравшись в программе, проследите, как в процессе ее выполнения меняется содержимое сегментных регистров и в каких командах используется содер-жимоетого или иного сегментного регистра. Напомню, что в командах загрузки MOV или LEAc любым из регистров, кроме BP, неявно предполагается использование сег­ментного регистра DS.

VI. Команды управления.

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

КомандаЬОСК- префикс блокировки шины. Используется в многопроцессорной системен можетсопутствовать любой команде микропроцессора. Приэтом на время работы этой команды закрывается доступ к шине любого другого процессора.

Команда NOP -команда холостого хода. Не производит никаких действий, но счет­чик команд изменяется. С помощью этой команды можно, например, забить другие ненужные команды, не прибегая к повторному ассемблированию.

HLT-команда останова. Переводит микропроцессор в состояние останова. Из этого состояния его может вывести лишь внешнее прерывание, например, времени. После­довательность команд CLI/HLT приводит к полному "зависанию" компьютера.

Команда WAIT используется для синхронизации действия микропроцессора с дру­гими устройствами. Смысл этой команды заключается в остановке микропроцессора на то время, пока какое-то другое устройство не закончит выполнять свою работу и перейдет в состояние готовности. Речь в данном случае может идти, например, о мате­матическом сопроцессоре. Прерывания не блокируются, но в отличие от HLT после завершения прерывания микропроцессор возвращается к этой же команде. Микро­процессор и сопроцессор работают параллельно, однако время выполнения разных команд различно. Может случиться, что микропроцессору потребуются результаты вычисления сопроцессора. В этом случае ему придется ждать, когда сопроцессор за­кончит свою работу. Здесь какраз и нужно воспользоваться командой WAIT.

Команда ESC заставляет микропроцессор передать данные на шину, где этими данными может воспользоваться, например, сопроцессор. Эта команда содержит два операнда. Первым операндом является код команды математического сопроцессора. Вторым - операнд для этой команды. Фактически ESC не является командой микро­процессора, а есть способ записи команды сопроцессора [2,17]. Вместо ESC можно писать команды сопроцессора, используя мнемонические обозначения (см. Приложе­ние 3).

VII. О тестировании микропроцессоров.10

Команды, рассмотренные в данном разделе, будут выполняться на всех микропро­цессорах серии 8088/8086. Это целое семейство, представителями которого являются микропроцессоры: 8088,8086, 80188, 80186,80286, 80386, 80486, Pentium. Добавьте сюда еще микропроцессоры NEC20 и NEC30. Иногда программе требуется знать, с каким процессором ей приходится работать. Конечно, можно попробовать тестиро­вать производительность (мы не будем этим заниматься). Таким образом, Вы легко отличите микропроцессор 8088 от 80286. Однако как различить модели 8086 и 8088?

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

В главе 3 говорилось о буфере команд. Из последовательности команд выбирается несколько (сколько помещается в буфер) и заносится в буфер. По мере выполнения оче­редь пополняется новыми командами. что она всегда полна. Некоторые команды, однако, сбрасывают очередь, так что она заполняется, начиная со следующей команды. Ккомандам, сбрасывающим очередь, относятся ЮТ, IRET, RET, CALLh всевозможные команды перехода. Некоторые марки микропроцессоров можно отличить по размеру буфера. Например, в микропроцессоре 8088 длина буфера 4 байта, а в 8086 - 6. Правда, в микропроцессоре NEC20 длина буфера составляет тоже 4 байта, и здесь потребуется проведение дополнительного тестирования. Ниже (Рис. 4.7) представлена программа, позволяющаяопределитьразмербуферакоманд.ВарьируяколичествокомандШР.Вы

легко определите длину буфера.

Содержимое данного раздела носит в настоящее время в значительной степени историчес-кийхарактер.

CODE SEGMENT

ASSUME CS:CODE

ORG 100H BEGIN:

MOV DI, OFFSET MET

JMP SHORT MET1 /сбрасываем буфер команд

MET1:

MOV BYTE PTR [DI],0C3H   /длина команды З байта NOP MET: NOP

/ текст будет напечатан,   если команда  с меткой МЕТ не попадет ;в буфер команд после выполнения команды JMP SHORT MET1

LEA  DX,TEXT

MOV AH,9

INT 21H RET

TEXT  DB    'конец!',13,10,'$'

CODE ENDS

END BEGIN

Рис. 4.7, Определение длины буфера команд.

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

MOV АХ,FLAG PUSH AX POPF PUSHF POP ВХ CMP AX,BX

Существует некоторое количество "экзотических" команд, выполнение которых может отличаться у разных компьютеров. Примером может служить команда PUSH SP. Вопрос заключается том, когда из содержимого SP вычитается 2 байта до того, как содержимое оказалось в стеке, или после. Оказывается, до 286-го микропроцессо­ра значение SP изменялось раньше, чем попадало в стек. Другим критерием, позволя­ющим судить о том, какой микропроцессор установлен на компьютере, могут служить новые команды. Известно, что команд PUSHA и РОРА нет у 8088/8086 микропроцес­соров. На Рис. 4.8 представлена программа, использующая данный факт для некото­рых выводов о микропроцессоре.

CODE SEGMENT

ASSUME CS:CODE

ORG 100H BEGIN:

MOV AX,SP

PUSHA

CMPAX,SP

JNZ P286

MOV AH, 9

MOV DX, OFFSET MES INT 2 lh :    JHP SHORT KON

P2 86 :

POPA

KON:

RET

MES    DB   'Это 86 или  88  процессор', 13, 10, '$'

CODE ENDS

END BEGIN

Рис. 4.8. Программа, использующая команды PUSHA и POP.A.

Конечно, ни одна из особенностей микропроцессоров, описанных выше, не может являться исчерпывающим критерием для определения его типа. Они должны исполь­зоваться комплексно [15]. Как дополнительный критерий можно использовать скорость выполнения команд микропроцессором, но для этого Вам придется познакомиться с прерыванием по времени. В главе 23 будет дана исчерпывающая программа, опреде­ляющая тип микропроцессора.

VIII. Время выполнения команд.

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