Домой / Спам / Реферат: План: Предисловие. Язык ассемблера и структура команд. Структура exe -файла (семантический разбор). Команды языка Ассемблер (Лекция) Табличные команды на языке ассемблера

Реферат: План: Предисловие. Язык ассемблера и структура команд. Структура exe -файла (семантический разбор). Команды языка Ассемблер (Лекция) Табличные команды на языке ассемблера

Структура команды на языке ассемблера Программирование на уровне машинных команд - это тот минимальный уровень, на котором возможно программирование компьютера. Система машинных команд должна быть достаточной для того, чтобы реализовать требуемые действия, выдавая указания аппаратуре машины. Каждая машинная команда состоит из двух частей: операционной, определяющей «что делать» и операндной, определяющей объекты обработки, то есть то «над чем делать» . Машинная команда микропроцессора, записанная на языке Ассемблера, представляет собой одну строку, имеющую следующий вид: метка команда/директива операнд(ы) ; комментарии Метка, команда/директива и операнд разделяются по крайней мере одним символом пробела или табуляции. Операнды команды разделяются запятыми.

Структура команды на языке ассемблера Команда ассемблера указывает транслятору, какое действие должен выполнить микропроцессор. Директивы ассемблера - параметры, заданные в тексте программы, влияющие на процесс ассемблирования или свойства выходного файла. Операнд определяет начальное значение данных (в сегменте данных) или элементы, над которыми выполняется действие по команде (в сегменте кода). Команда может иметь один или два операнда, или не иметь операндов. Число операндов неявно задается кодом команды. Если команду или директиву необходимо продолжить на следующей строке, то используется символ «обратный слеш»: «» . По умолчанию Ассемблер не различает заглавные и строчные буквы в написании команд и директив. Примеры директивы и команды Count db 1 ; Имя, директива, один операнд mov eax, 0 ; Команда, два операнда

Идентификаторы – последовательности допустимых символов, использующиеся для обозначения имен переменных и названий меток. Идентификатор может состоять из одного или нескольких следующих символов: все буквы латинского алфавита; цифры от 0 до 9; спецсимволы: _, @, $, ? . В качестве первого символа метки может использоваться точка. В качестве идентификаторов нельзя использовать зарезервированные имена ассемблера (директивы, операторы, имена команд). Первым символом идентификатора должна быть буква или спецсимвол. Максимальная длина идентификатора 255 символов, но транслятор воспринимает первые 32, остальные игнорирует. Все метки, которые записываются в строке, не содержащей директиву ассемблера, должны заканчиваться двоеточием «: » . Метка, команда (директива) и операнд не обязательно должны начинаться с какой-либо определенной позиции в строке. Рекомендуется записывать их в колонку для большей yдобочитаемости программы.

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

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

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

Модели памяти Перед объявлением сегментов нужно указать модель памяти при помощи директивы. MODEL модификатор модель_памяти, соглашение_о_вызовах, тип_ОС, параметр_стека Основные модели памяти языка ассемблера: Модель памяти Адресация кода Адресация данных Операционная система Чередование кода и данных TINY NEAR MS-DOS Допустимо SMALL NEAR MS-DOS, Windows Нет MEDIUM FAR NEAR MS-DOS, Windows Нет COMPACT NEAR FAR MS-DOS, Windows Нет LARGE FAR MS-DOS, Windows Нет HUGE FAR MS-DOS, Windows Нет NEAR Windows 2000, Windows XP, Windows Допустимо FLAT NEAR NT,

Модели памяти Модель tiny работает только в 16 -разрядных приложениях MS-DOS. В этой модели все данные и код располагаются в одном физическом сегменте. Размер программного файла в этом случае не превышает 64 Кбайт. Модель small поддерживает один сегмент кода и один сегмент данных. Данные и код при использовании этой модели адресуются как near (ближние). Модель medium поддерживает несколько сегментов программного кода и один сегмент данных, при этом все ссылки в сегментах программного кода по умолчанию считаются дальними (far), а ссылки в сегменте данных - ближними (near). Модель compact поддерживает несколько сегментов данных, в которых используется дальняя адресация данных (far), и один сегмент кода с ближней адресацией (near). Модель large поддерживает несколько сегментов кода и несколько сегментов данных. По умолчанию все ссылки на код и данные считаются дальними (far). Модель huge практически эквивалентна модели памяти large.

Модели памяти Модель flat предполагает несегментированную конфигурацию программы и используется только в 32 -разрядных операционных системах. Эта модель подобна модели tiny в том смысле, что данные и код размещены в одном сегменте, только 32 -разрядном. Для разработки программы для модели flat перед директивой. model flat следует разместить одну из директив: . 386, . 486, . 586 или. 686. Выбор директивы выбора процессора определяет набор команд, доступный при написании программ. Буква p после директивы выбора процессора означает защищенный режим работы. Адресация данных и кода является ближней (near), при этом все адреса и указатели являются 32 -разрядными.

Модели памяти. MODEL модификатор модель_памяти, соглашение_о_вызовах, тип_ОС, параметр_стека Параметр модификатор используется для определения типов сегментов и может принимать значения: use 16 (сегменты выбранной модели используются как 16 -битные) use 32 (сегменты выбранной модели используются как 32 -битные). Параметр соглашение_о_вызовах используется для определения способа передачи параметров при вызове процедуры из других языков, в том числе и языков высокого уровня (C++, Pascal). Параметр может принимать следующие значения: C, BASIC, FORTRAN, PASCAL, SYSCALL, STDCALL.

Модели памяти. MODEL модификатор модель_памяти, соглашение_о_вызовах, тип_ОС, параметр_стека Параметр тип_ОС равен OS_DOS по умолчанию, и на данный момент это единственное поддерживаемое значение этого параметра. Параметр параметр_стека устанавливается равным: NEARSTACK (регистр SS равен DS, области данных и стека размещаются в одном и том же физическом сегменте) FARSTACK (регистр SS не равен DS, области данных и стека размещаются в разных физических сегментах). По умолчанию принимается значение NEARSTACK.

Пример «ничего не делающей» программы. 686 P. MODEL FLAT, STDCALL. DATA. CODE START: RET END START RET - команда микропроцессора. Она обеспечивает правильное окончание работы программы. Остальная часть программы относится к работе транслятора. . 686 P - разрешены команды защищенного режима Pentium 6 (Pentium II). Данная директива выбирает поддерживаемый набор команд ассемблера, указывая модель процессора. . MODEL FLAT, stdcall - плоская модель памяти. Эта модель памяти используется в операционной системе Windows. stdcall - используемое соглашение о вызовах процедур.

Пример «ничего не делающей» программы. 686 P. MODEL FLAT, STDCALL. DATA. CODE START: RET END START . DATA - сегмент программы, содержащий данные. Данная программа не использует стек, поэтому сегмент. STACK отсутствует. . CODE - сегмент программы, содержащей код. START - метка. END START - конец программы и сообщение компилятору, что начинать выполнение программы надо с метки START. Каждая программа должна содержать директиву END, отмечающую конец исходного кода программы. Все строки, которые следуют за директивой END, игнорируются Метка, указанная после директивы END, сообщает транслятору имя главного модуля, с которого начинается выполнение программы. Если программа содержит один модуль, метку после директивы END можно не указывать.

Трансляторы языка ассемблера Транслятор - программа или техническое средство, выполняющее преобразование программы, представленной на одном из языков программирования, в программу на целевом языке, называемую объектным кодом. Помимо поддержки мнемоник машинных команд, каждый транслятор обладает своим собственным набором директив и макросредств, зачастую ни с чем не совместимых. Основные виды трансляторов языка ассемблера: MASM (Microsoft Assembler), TASM (Borland Turbo Assembler), FASM (Flat Assembler) - свободно распространяемый многопроходной ассемблер, написанный Томашем Грыштаром (польск.), NASM (Netwide Assembler) - свободный ассемблер для архитектуры Intel x 86, был создан Саймоном Тэтхемом совместно с Юлианом Холлом и в настоящее время развивается небольшой командой разработчиков на Source. Forge. net.

Src="https://present5.com/presentation/-29367016_63610977/image-15.jpg" alt="Трансляция программы в Microsoft Visual Studio 2005 1) Создать проект, выбрав меню File->New->Project и"> Трансляция программы в Microsoft Visual Studio 2005 1) Создать проект, выбрав меню File->New->Project и указав имя проекта (hello. prj) и тип проекта: Win 32 Project. В дополнительных опциях мастера проекта указать “Empty Project”.

Src="https://present5.com/presentation/-29367016_63610977/image-16.jpg" alt="Трансляция программы в Microsoft Visual Studio 2005 2) В дереве проекта (View->Solution Explorer) добавить"> Трансляция программы в Microsoft Visual Studio 2005 2) В дереве проекта (View->Solution Explorer) добавить файл, в котором будет содержаться текст программы: Source. Files->Add->New. Item.

Трансляция программы в Microsoft Visual Studio 2005 3) Выбрать тип файла Code C++, но указать имя с расширением. asm:

Трансляция программы в Microsoft Visual Studio 2005 5) Установить параметры компилятора. Выбрать по правой кнопке в файле проекта меню Custom Build Rules…

Трансляция программы в Microsoft Visual Studio 2005 и в появившемся окне выбрать Microsoft Macro Assembler.

Трансляция программы в Microsoft Visual Studio 2005 Проверить по правой кнопке в файле hello. asm дерева проекта меню Properties и установить General->Tool: Microsoft Macro Assembler.

Src="https://present5.com/presentation/-29367016_63610977/image-22.jpg" alt="Трансляция программы в Microsoft Visual Studio 2005 6) Откомпилировать файл, выбрав Build->Build hello. prj."> Трансляция программы в Microsoft Visual Studio 2005 6) Откомпилировать файл, выбрав Build->Build hello. prj. 7) Запустить программу, нажав F 5 или выбрав меню Debug->Start Debugging.

Программирование в ОС Windows Программирование в OC Windows основывается на использовании функций API (Application Program Interface, т. е. интерфейс программного приложения). Их количество достигает 2000. Программа для Windows в значительной степени состоит из таких вызовов. Все взаимодействие с внешними устройствами и ресурсами операционной системы происходит, как правило, посредством таких функций. Операционная система Windows использует плоскую модель памяти. Адрес любой ячейки памяти будет определяться содержимым одного 32 -битного регистра. Возможны 3 типа структур программ для Windows: диалоговая (основное окно - диалоговое), консольная, или безоконная структура, классическая структура (оконная, каркасная).

Вызов функций Windows API В файле помощи любая функция API представлена в виде тип имя_функции (ФА 1, ФА 2, ФА 3) Тип – тип возвращаемого значения; ФАх – перечень формальных аргументов в порядке их следования Например, int Message. Box (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); Данная функция выводит на экран окно с сообщением и кнопкой (или кнопками) выхода. Смысл параметров: h. Wnd -дескриптор окна, в котором будет появляться окно-сообщение, lp. Text - текст, который будет появляться в окне, lp. Caption - текст в заголовке окна, u. Type - тип окна, в частности можно определить количество кнопок выхода.

Вызов функций Windows API int Message. Box (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); Практически все параметры API-функций в действительности 32 -битные целые числа: HWND - 32 -битное целое, LPCTSTR - 32 -битный указатель на строку, UINT - 32 -битное целое. К имени функций часто добавляется суффикс "А" для перехода к более новым версиям функций.

Вызов функций Windows API int Message. Box (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); При использовании MASM необходимо в конце имени добавить @N N – количество байт, которое занимают в стеке переданные аргументы. Для функций Win 32 API это число можно определить как количество аргументов n, умноженное на 4 (байта в каждом аргументе): N=4*n. Для вызова функции используется команда CALL ассемблера. При этом все аргументы функции передаются в нее через стек (команда PUSH). Направление передачи аргументов: СЛЕВА НАПРАВО - СНИЗУ ВВЕРХ. Первым будет помещаться в стек аргумент u. Type. Вызов указанной функции будет выглядеть так: CALL Message. Box. A@16

Вызов функций Windows API int Message. Box (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Caption, UINT u. Type); Результат выполнения любой API функции - это, как правило, целое число, которое возвращается в регистре EAX. Директива OFFSET представляет собой «смещение в сегменте» , или, переводя в понятия языков высокого уровня, «указатель» начала строки. Директива EQU подобно #define в языке СИ определяет константу. Директива EXTERN указывает транслятору, что функция или идентификатор является внешним по отношению к данному модулю.

Пример программы «Привет всем!» . 686 P. MODEL FLAT, STDCALL. STACK 4096. DATA MB_OK EQU 0 STR 1 DB "Моя первая программа", 0 STR 2 DB "Привет всем!", 0 HW DD ? EXTERN Message. Box. A@16: NEAR. CODE START: PUSH MB_OK PUSH OFFSET STR 1 PUSH OFFSET STR 2 PUSH HW CALL Message. Box. A@16 RET END START

Директива INVOKE Транслятор языка MASM позволяет также упростить вызов функций с использованием макросредства – директивы INVOKE: INVOKE функция, параметр1, параметр2, … При этом нет необходимости добавлять @16 к вызову функции; параметры записываются точно в том порядке, в котором приведены в описании функции. макросредствами транслятора параметры помещаются в стек. для использования директивы INVOKE необходимо иметь описание прототипа функции с использованием директивы PROTO в виде: Message. Box. A PROTO: DWORD, : DWORD Если в программе используется множество функций Win 32 API, целесообразно воспользоваться директивой include C: masm 32includeuser 32. inc

Тема 2.5 Основы программирования процессора

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

Язык символического кодирования команд называется ассемблером .

Язык ассемблер – это язык, в котором каждое высказывание соответствует ровно одной машинной команде.

Ассемблированием называется преобразование программы с языка ассемблера, т. е. подготовка программы на машинном языке путем замены символических имен операций на машинные коды, а символических адресов – на абсолютные или относительные номера, а также включение библиотечных программ и генерация последовательностей символических команд путем указания конкретных параметров в микрокомандах. Данная программа обычно размещается в ПЗУ или вводится в ОЗУ с некоторого внешнего носителя.

Язык ассемблер имеет несколько особенностей, отличающих его от языков высокого уровня:

1. Это взаимно однозначное соответствие между высказываниями языка ассемблера и машинными командами.

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

Представление об основах программирования на машинно-ориентированных языках полезно для:



Лучшего понимания архитектуры ПК и более грамотного использования компьютеров;

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

Возможности просмотра и корректировки исполняемых программ с расширением.exe и.com, компилированных с любых языков высокого уровня, в случае утраты исходных программ (вызвав указанные программы в отладчик программы DEBUG и декомпилировав их отображение на языке ассемблера);

Составления программ решения наиболее ответственных задач (программа, составленная на машинно-ориентированном языке, обычно эффективнее – короче и быстрее процентов на 30-60 программ, полученных в результате трансляции с языков высокого уровня)

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

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

Алфавит языка ассемблера составляют символы ASCII.

Числа только целые. Различают:

Двоичные числа, заканчиваются буквой В;

Десятичные числа, заканчиваются буквой D;

Шестнадцатеричные числа, заканчиваются буквой Н.

Оперативная память, регистры, представление данных

Для определённой серии МП используется индивидуальный язык составления программ – язык ассемблер.

Язык ассемблер занимает промежуточное положение между машинными кодами и языками высокого уровня. Программировать на этом языке проще. Программа на языке ассемблер более рационально использует возможности конкретной машины (точнее МП), чем программа на языке высокого уровня (который более прост для программиста, чем ассемблер). Основные принципы программирования на машинно-ориентированных языках рассмотрим на примере языка ассемблер для МП КР580ВМ80. Для программирования на языке используется общая методика. Конкретные же технические приемы записи программ связаны с особенностями архитектуры и системы команд целевого МП.

Программная модель микропроцессорной системы на основе МП КР580ВМ80

Программная модель МПС в соответствии с рисунком 1

МП Порты Память

S Z AC P C

Рисунок 1

С точки зрения программиста МП КР580ВМ80 имеет следующие программно-доступные регистры.

А – 8-битовый регистр аккумулятор. Является главным регистром МП. Любая операция, выполняемая в АЛУ, предполагает размещение одного из операндов, подлежащих обработке, в аккумуляторе. Результат операции в АЛУ тоже обычно хранится в А.

B, C, D, E, H, L – 8-битовые регистры общего назначения (РОН). Внутренняя память МП. Предназначены для хранения обрабатываемой информации, а также результатов операции. При обработке 16-разрядных слов из регистров образуют пары BC, DE, HL, причем сдвоенный регистр называется первой буквой – B, D, H. В регистровой паре старшим является первый регистр. Особым свойством обладают регистры H, L, используемые как для хранения данных, так и для хранения 16-разрядных адресов ячеек ОЗУ.

FL – регистр флагов (регистр признаков) 8-битовый регистр, в котором сохраняются пять признаков результата выполнения арифметических и логических операций в МП. Формат FL в соответствии с рисунком

Разряд С (CY - carry) - перенос, устанавливается в 1, если был перенос из старшего разряда байта при выполнении арифметических операций.

Разряд Р (parity) – четность, устанавливается в 1, если число единиц в разрядах результата четно.

Разряд АС – дополнительный перенос, предназначен для хранения значения переноса из младшей тетрады результата.

Разряд Z (нуль) – устанавливается в 1, если результат операции равен 0.

Разряд S (знак) – устанавливается в 1, если результат отрицательный, и в 0, если результат положительный.

SP –- указатель стека, 16-разрядный регистр, предназначен для хранения адреса ячейки памяти, куда был записан последний введенный в стек байт.

РС – программный счетчик (счетчик команд), 16-разрядный регистр, предназначен для хранения адреса следующей выполняемой команды. Содержимое счетчика команд автоматически увеличивается на 1 сразу же после выборки очередного байта команды.

В начальной области памяти адреса 0000Н – 07FF располагается управляющая программа и демонстрационные программы. Это область ПЗУ.

0800 – 0АFF - область адресов для записи исследуемых программ. (ОЗУ).

0В00 – 0ВВ0 - область адресов для записи данных. (ОЗУ).

0ВВ0 – начальный адрес стека. (ОЗУ).

Стек – специально организованная область ОЗУ, предназначенная для временного хранения данных или адресов. Число, записанное в стек последним, извлекается из него первым. Указатель стека хранит адрес последней ячейки стека, в которой записана информация. При вызове подпрограммы в стеке автоматически сохраняется адрес возврата в основную программу. Как правило, в начале каждой подпрограммы сохраняются в стеке содержимое всех задействованных при ее выполнении регистров, а в конце подпрограммы восстанавливают их из стека.

Формат данных и структура команд языка ассемблер

Память МП КР580ВМ80 представляет собой массив 8-ьитных слов, называемых байтами, Каждый байт имеет свой 16-разрядный адрес, определяющий его положение в последовательности ячеек памяти. МП может адресовать 65536 байт памяти, которая может содержать как в ПЗУ, так и в ОЗУ.

Формат данных

Данные хранятся в памяти в виде 8-битных слов:

D7 D6 D5 D4 D3 D2 D1 D0

Младшим битом является бит 0, старшим – бит 7.

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

Формат команд

Команды МП КР580ВМ80 имеют одно, двух или трехбайтный формат. Многобайтные команды должны быть размещены в соседних ЯП. Формат команды зависит от особенностей выполняемой операции.

Первый байт команды содержит код операции, записанный в мнемоническом виде.

Он определяет формат команды и те действия, которые должны быть выполнены МП над данными в процессе ее выполнения, и способ адресации, а также может содержать информацию о нахождении данных.

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

Формат однобайтовой команды в соответствии с рисунком 2

Рисунок 4

В командах на языке ассемблера код операции имеет сокращённую форму записи английских слов – мнемоническое обозначение. Мнемоника (от греческого mnemonic – искусство запоминания) позволяет легче запомнить команды по их функциональному назначению.

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


Методы адресации

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

Для МП КР580ВМ80 существуют следующие методы адресации:

Непосредственная;

Регистровая;

Косвенная;

Стековая.

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

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

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

Косвенная (неявная)адресация предполагает, что во внутреннем регистре МП находится не сам операнд, а его адрес в памяти.

Стековая адресация предполагает, что команда не содержит адрес. Адресация к ячейкам памяти по содержимому 16-разрядного регистра SP (указателя стека).

Система команд

Система команд МП – это полный перечень элементарных действий, которые способен производить МП. Управляемый этими командами МП выполняет простые действия, такие как элементарные арифметические и логические операции, пересылку данных, сравнение двух величин и др. Число команд МП КР580ВМ80 - 78 (с учетом модификаций 244).

Различают следующие группы команд:

Передачи данных;

Арифметические;

Логические;

Команды перехода;

Команды ввода-вывода, управления и работы со стеком.


Символы и сокращения, применяемые при описании команд и составлении программ

Символ Сокращение
ADDR 16-битовый адрес
DATA 8-битовые данные
DATA 16 16-битовые данные
PORT 8-битовый адрес УВВ (устройства ввода-вывода)
BYTE 2 Второй байт команды
BYTE 3 Третий байт команды
R, R1, R2 Один из регистров: A, B, C, D, E, H, L
RP Одна из регистровых пар: В - задает пару ВС; D - задает пару DE; H – задает пару HL
RH Первый регистр пары
RL Второй регистр пары
Λ Логическое умножение
V Логическое сложение
Сложение по модулю два
М Ячейка памяти, адрес которой задаёт содержимое регистровой пары HL, т. е. М = (HL)

Команды языка Ассемблер (Лекция)

ПЛАН ЛЕКЦИИ

1. Основные группы операций.

Pentium .

1. Основные группы операций

Микропроцессоры выполняют набор команд,которыереализуютследующиеосновные группыопераций:

Операциипересылки,

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

Логическиеоперации,

Операциисдвига,

Операциисравненияитестирования,

Битовыеоперации,

Операцииуправления программой;

Операцииуправления процессором.

2. Мнемокоды команд процессора Pentium

При описании команд обычно используются их мнемонические обозначения (мнемокоды), которые служат для задания команды при программировании на языке Ассемблера. Для различных версий Ассемблера мнемокоды некоторых команд могут отличаться. Например, для команды вызова подпрограммы используется мнемокод CALL или JSR (“ Jump to SubRoutine ”). Однако мнемокоды большинства команд для основных типов микропроцессоров совпадают или отличаются незначительно, так как они являются сокращениями соответствующих английских слов, определяющих выполняемую операцию. Рассмотрим мнемокоды команд, принятые для процессоров Pentium .

Команды пересылки. Основной командой этой группы является команда MOV , которая обеспечивает пересылку данных между двумя регистрами или между регистром и ячейкой памяти. В некоторых микропроцессорах реализуется пересылка между двумя ячейками памяти, а также групповая пересылка содержимого нескольких регистровиз памяти. Например, микропроцессоры семейства 68 xxx компании Motorola выполняют команду MOVE , обеспечивающую пересылку из одной ячейки памяти в другую, и команду MOVEM , которая производит запись в память или загрузку из памяти содержимого заданного набора регистров (до 16 регистров). Команда XCHG производит взаимный обмен содержимым двух регистров процессора или регистра и ячейки памяти.

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

Команды арифметических операций. Основными в этой группе являются команды сложения, вычитания, умножения и деления,которыеимеютрядвариантов. Команды сложения ADD и вычитания SUB выполняют соответствующие операции с c одержимым двух регистров, регистра и ячейки памяти или с использованием непосредственного операнда. Команды AD C , SB B производят сложение и вычитание с учетом значения признака C , устанавливаемого при формировании переноса в процессе выполнения предыдущей операции. С помощью этих команд реализуется последовательное сложение операндов, число разрядов которых превышает разрядность процессора. Команда NEG изменяет знак операнда, переводя его в дополнительный код.

Операции умножения и деления могут выполняться над числами со знаком (команды I MUL, I DIV ) или беззнака(команды MUL, DIV ).Одинизоперандоввсегдаразмещаетсяврегистре, второй может находиться в регистре, ячейке памяти или быть непосредственным операндом. Результат операции располагается в регистре. При умножении (команды MUL , IMUL ) получается результат удвоенной разрядности, для размещения которого используется два регистра. При делении (команды DIV , IDIV ) в качестве делимого используется операнд удвоенной разрядности, размещаемый в двух регистрах, а в качестве результата в два регистра записывается частное и остаток.

Команды логических операций . Практически все микропроцессоры производят логические операцииИ , ИЛИ, Исключающее ИЛИ, которые выполняются над одноименными разрядами операндов с помощью команд AND, OR, X OR . Операции выполняются над содержимым двух регистров, регистра и ячейки памяти или с использованием непосредственного операнда. Команда NOT инвертирует значение каждого разряда операнда.

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

Команды сравнения и тестирования . Сравнение операндов обычно производится с помощью команды CMP , которая производит вычитание операндов с установкой значений признаков N, Z, V, C в регистре состояния в соответствии с полученным результатом. При этом результат вычитания не сохраняется, и значения операндов не изменяются. Последующий анализ полученных значений признаков позволяет определить относительное значение (>, <, =) операндов со знаком или без знака. Использование различных способов адресации позволяет производит сравнение содержимого двух регистров, регистра и ячейки памяти, непосредственно заданного операнда с содержимым регистра или ячейки памяти.

Некоторые микропроцессоры выполняют команду тестирования TST , которая является однооперандным вариантом команды сравнения. При выполнении этой командыустанавливаются признаки N, Z в соответствии со знаком и значением (равно или не равно нулю) адресуемого операнда.

Команды битовых операций . Эти команды производят установку значения признака C в регистре состояний в соответствии со значением тестируемого бита bn в адресуемом операнде. В некоторых микропроцессорах по результату тестирования бита производится установка признака Z . Номер тестируемого бита n задаетсялибо содержимым указанного в команде регистра, либо непосредственным операндом.

Команды данной группы реализуют разные варианты изменениятестируемогобита.КомандаBT сохраняет значение этого бита неизменным .КомандаB T S послетестирования устанавливает значениеbn =1, а команда B T C - значение bn =0.Команда B T C инвертирует значение бита bn после его тестирования.

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

- команды безусловной передачи управления;

- команды условных переходов;

- команды организации программных циклов;

- команды прерывания;

- команды изменения признаков.

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

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

Команды управления признаками обеспечивают запись - чтение содержимого регистра состояния, в котором хранятся признаки, а также изменение значений отдельных признаков. Например, в процессорах Pentium реализуются команды LAHF и SAHF , которые выполняют загрузку младшего байта, где содержатся признаки, из регистра состояния EFLAG в младший байт регистра EAX и заполнение младшего байта EFLAGS из регистра E A X .. Команды CLC, STC осуществляют установку значений признака переноса CF=0, CF=1, а команда CMC вызывает инвертирование значения этого признака. Так как признаки определяют ход выполнения программы при условных переходах, то команды изменения признаков обычно используются для управления программой.

Командыуправления процессором . К этой группе относятся команды останова, отсутствия операции и ряд команд, определяющих режим работы процессора или его отдельных блоков. Команда HLT прекращает выполнение программы и переводит процессор в состояние останова, выход из которого происходит при поступлении сигналов прерывания или перезапуска (Reset ). Команда NOP (“пустая” команда), которая не вызывает выполнения каких-либо операций, служит для реализации программных задержек или заполнения пропусков, образовавшихся в программе.

Специальные команды CLI, STI запрещают и разрешают обслуживание запросов прерывания. В процессорах Pentium для этого используется бит управления (флаг) IF в регистре EFLAGS .

Многие современные микропроцессоры выполняют команду идентификации, которая позволяет пользователю или другим устройствам получить информацию о типе процессора, используемого в данной системе. В процессорах Pentuim для этого служит команда CPUID , при выполнении которой необходимые данные о процессоре поступают в регистры EAX , EBX , ECX , EDX и могут затем считываться пользователем или операционной системой.

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

Некоторые процессоры производят арифметические операции с двоично-десятичными числами или выполняют специальные команды коррекции результата при обработке таких чисел. В состав многих высокопроизводительных процессоров входит FPU - блок обработки чисел c “плавающей точкой”.

В ряде современных процессоров реализована групповая обработка нескольких целых чисел или чисел c “плавающей точкой” с помощью одной команды по принципу SIMD (“ Single Instruction – Multiple Data ”) - «Одна команда – Множество данных». Одновременное выполнение операций над несколькими операндами существенно повышает производительность процессора при работе с видео- и аудиоданными. Такие операции широко используются для обработки изображений, звуковых сигналов и в других приложениях. Для выполнения этих операций в состав процессоров введены специальные блоки, реализующие соответствующие наборы команд, которые в различных типах процессоров (Pentium , Athlon ) получили название MMX (“ Milti - Media Extension ”) – Мультимедийное Расширение, SSE (“ Streaming SIMD Extension ”) – Потоковое SIMD – расширение, “3 D Extension – Трехмерное Расширение.

Характерной особенностью процессоров компании Intel , начиная с модели 80286, является приоритетный контроль при обращении к памяти, который обеспечивается при работе процессора в режиме защищенных виртуальных адресов – “ Protected Mode ” (защищенный режим). Для реализации этого режима используется специальные группы команд, которые служат для организации защиты памяти в соответствии с принятым алгоритмом приоритетного обращения.

Тема 1.4 Ассемблерная мнемоника. Структура и форматы команд. Виды адресации. Система команд микропроцессора

План:

1 Язык ассемблера. Основные понятия

2 Символы языка ассемблера

3 Типы операторов ассемблера

4 Директивы ассемблера

5 Система команд процессора

1 Я зык ассемблера. Основные понятия

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

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

Предложения ассемблера бывают четырех типов:

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

2) макрокоманды - оформляемые определенным образом предложения текста программы, замещаемые во время трансляции другими предложениями;

3) директивы, являющиеся указанием транслятору ассемблера на выполнение некоторых действий. У директив нет аналогов в машинном представлении;

4) строки комментариев , содержащие любые символы, в том числе и буквы русского алфавита. Комментарии игнорируются транслятором.

­ Структура программы на ассемблере. Синтаксис ассемблера.

Предложения, составляющие программу, могут представлять собой синтаксическую конструкцию, соответствующую команде, макрокоманде, директиве или комментарию. Для того чтобы транслятор ассемблера мог распознать их, они должны формироваться по определенным синтаксическим правилам. Для этого лучше всего использовать формальное описание синтаксиса языка наподобие правил грамматики. Наиболее распространенные способы подобного описания языка программирования - синтаксические диаграммы и расширенные формы Бэкуса-Наура. Для практического использования более удобны синтаксические диаграммы. К примеру, синтаксис предложений ассемблера можно описать с помощью синтаксических диаграмм, показанных на следующих рисунках 10, 11, 12.

Рисунок 10 - Формат предложения ассемблера


­ Рисунок 11 - Формат директив

­ Рисунок 12 - Формат команд и макрокоманд

На этих рисунках:

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

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

­ код операции (КОП) и директива - это мнемонические обозначения соответствующей машинной команды, макрокоманды или директивы транслятора;

­ операнды - части команды, макрокоманды или директивы ассемблера, обозначающие объекты, над которыми производятся действия. Операнды ассемблера описываются выражениями с числовыми и текстовыми константами, метками и идентификаторами переменных с использованием знаков операций и некоторых зарезервированных слов.

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

­ 2 Символы языка ассемблера

Допустимыми символами при написании текста программ являются:

1) все латинские буквы: A-Z , a-z . При этом заглавные и строчные буквы считаются эквивалентными;

2) цифры от 0 до 9 ;

3) знаки ? , @ , $ , _ , & ;

4) разделители , . () < > { } + / * % ! " " ? = # ^ .

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

Лексемами являются:

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

2) цепочки символов - последовательности символов, заключенные в одинарные или двойные кавычки;

3) целые числав одной из следующих систем счисления: двоичной, десятичной, шестнадцатеричной. Отождествление чисел при записи их в программах на ассемблере производится по определенным правилам:

4) десятичные числа не требуют для своего отождествления указания каких-либо дополнительных символов, например 25 или 139. Для отождествления в исходном тексте программы двоичных чисел необходимо после записи нулей и единиц, входящих в их состав, поставить латинское “b ”, например 10010101b .

5) шестнадцатеричные числа имеют больше условностей при своей записи:

Во-первых, они состоят из цифр 0...9 , строчных и прописных букв латинского алфавита a , b , c , d , e , f или A , B , C , D , E , F .

Во-вторых, у транслятора могут возникнуть трудности с распознаванием шестнадцатеричных чисел из-за того, что они могут состоять как из одних цифр 0...9 (например, 190845), так и начинаться с буквы латинского алфавита (например, ef15 ). Для того чтобы "объяснить" транслятору, что данная лексема не является десятичным числом или идентификатором, программист должен специальным образом выделять шестнадцатеричное число. Для этого на конце последовательности шестнадцатеричных цифр, составляющих шестнадцатерич-ное число, записывают латинскую букву “h ”. Это обязательное условие. Если шестнадцатеричное число начинается с буквы, то перед ним записывается ведущий ноль: 0 ef15h.

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

Возможно, провести следующую классификацию операндов:

­ постоянные или непосредственные операнды;

­ адресные операнды;

­ перемещаемые операнды;

­ счетчик адреса;

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

­ базовый и индексный операнды;

­ структурные операнды;

­ записи.

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

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

­ 3 Типы операторов ассемблера

Перечислим возможные типы операторов ассемблера и синтаксические правила формирования выражений ассемблера:

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

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

­ операторы сравнения;

­ логические операторы;

­ индексный оператор;

­ оператор переопределения типа;

­ оператор переопределения сегмента;

­ оператор именования типа структуры;

­ оператор получения сегментной составляющей адреса выражения;

­ оператор получения смещения выражения.

1 Директивы ассемблера

­ Директивы ассемблера бывают:

1) Директивы сегментации. В ходе предыдущего обсуждения мы выяснили все основные правила записи команд и операндов в программе на ассемблере. Открытым остался вопрос о том, как правильно оформить последовательность команд, чтобы транслятор мог их обработать, а микропроцессор - выполнить.

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

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

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

­ с одним сегментом данных;

­ с тремя дополнительными сегментами данных.

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


­ Рисунок 13 - Синтаксическое описание сегмента на ассемблере

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

2) Директивы управления листингом. Директивы управления листингом делятся на следующие группы:

­ общие директивы управления листингом;

­ директивы вывода в листинг включаемых файлов;

­ директивы вывода блоков условного ассемблирования;

­ директивы вывода в листинг макрокоманд;

­ директивы вывода в листинг информации о перекрестных ссылках;

­ директивы изменения формата листинга.

2 Система команд процессора

Система команд процессора представлена на рисунке 14.

Рассмотрим основные группы команд.

­ Рисунок 14 - Классификация команд ассемблера

Команды бывают:

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

­ сохранение в памяти содержимого внутренних регистров процессора;

­ копирование содержимого из одной области памяти в другую;

­ запись в устройства ввода/вывода и чтение из устройств ввода/вывода.

В некоторых процессорах все эти функции выполняются одной единственной командой MOV (для байтовых пересылок - MOVB ) но с различными методами адресации операндов.

В других процессорах помимо команды MOV имеется еще несколько команд для выполнения перечисленных функций. Также к командам пересылки данных относятся команды обмена информацией (их обозначение строится на основе слова Exchange ). Может быть предусмотрен обмен информацией между внутренними регистрами, между двумя половинами одного регистра (SWAP ) или между регистром и ячейкой памяти.

2 Арифметические команды. Арифметические команды рассматривают коды операндов как числовые двоичные или двоично-десятичные коды. Эти команды могут быть разделены на пять основных групп:

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

­ команды операций с плавающей запятой (сложение, вычитание, умножение, деление);

­ команды очистки;

­ команды инкремента и декремента;

­ команда сравнения.

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

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

5 Команды инкремента (увеличения на единицу) и декремента

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

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

7 Логические команды. Логические команды выполняют над операндами логические (побитовые) операции, то есть они рассматривают коды операндов не как единое число, а как набор отдельных битов. Этим они отличаются от арифметических команд. Логические команды выполняют следующие основные операции:

­ логическое И, логическое ИЛИ, сложение по модулю 2 (Исключающее ИЛИ);

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

­ проверка битов и операндов;

­ установка и очистка битов (флагов) регистра состояния процессора (PSW ).

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

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

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

Команды переходов без возврата делятся на две группы:

­ команды безусловных переходов;

­ команды условных переходов.

В обозначениях этих команд используются слова Branch (ветвление) и Jump (прыжок).

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

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

­ переход, если равно нулю;

­ переход, если не равно нулю;

­ переход, если есть переполнение;

­ переход, если нет переполнения;

­ переход, если больше нуля;

­ переход, если меньше или равно нулю.

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

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

Особое место среди команд перехода с возвратом занимают команды прерываний. Эти команды в качестве входного операнда требуют номер прерывания (адрес вектора).

Вывод:

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

Допустимыми символами при написании текста программ являются все латинские буквы: A-Z , a-z . При этом заглавные и строчные буквы считаются эквивалентными; цифры от 0 до 9 ; знаки ? , @ , $ , _ , & ; разделители , . () < > { } + / * % ! " " ? = # ^ .

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

Система команд разделена на 8 основных групп.

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

1 Что представляет собой язык ассемблера?

2 Какие символы можно применять для записи команд на ассемблере?

3 Что представляют собой метки и их назначение?

4 Пояснить структуру команд ассемблера.

5 Перечислить 4 типа предложений ассемблера.

НАЦИОНАЛЬНЫЙ УНИВЕРСИТЕТ УЗБЕКИСТАНА ИМЕНИ МИРЗО УЛУГБЕКА

ФАКУЛЬТЕТ КОМПЬЮТЕРНЫХ ТЕХНОЛОГИИ

На тему: Семантический разбор EXE-файла.

Выполнил:

Ташкент 2003.

Предисловие.

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

Структура EXE –файла (семантический разбор).

Структура COM-файла.

Принцип действия и распространения вируса.

Дисассемблер.

Программы.

Предисловие

Профессия программиста удивительна и уникальна. В наше время науку и жизнь невозможно представить без новейших технологии. Все что связано с деятельностью человека не обходится без вычислительной техники. А это способствует ее высокому развитию и совершенству. Пусть развитие персональных компьютеров началось не так давно, но в течение этого времени были сделаны колоссальные шаги по программным продуктам и еще долгое время эти продукты будут широко использоваться. Область связанных с компьютерами знании претерпела взрыв, как и соответствующая технология. Если не брать в рассмотрение коммерческую сторону, то можно сказать, что чужих людей в этой области профессиональной деятельности нет. Многие занимаются разработкой программ не ради выгоды или заработка, а по собственной воле, по увлечению. Конечно это не должно сказаться на качестве программы, и в этом деле так сказать «бизнесе» есть конкуренция и спрос на качество исполнения, на стабильной работе и отвечающий всем требованиям современности. Здесь так же стоит отметить появление микропроцессоров в 60-х годах, которые пришли на замену большого количества набора ламп. Есть некоторые разновидности микропроцессоров которые сильно отличаются друг от друга. Эти микропроцессоры отличны друг от друга разрядностью и встроенными системными командами. Самые распространенные такие как: Intel, IBM, Celeron, AMD и т.д. Все эти процессоры имеют отношение к развитой архитектуре процессоров фирмы Intel. Распространение микрокомпьютеров послужило причиной пересмотра отношения к языку ассемблера по двум основным причинам. Во-первых, программы, написанные на языке ассемблера, требуют значительно меньше памяти и времени выполнения. Во-вторых, знание языка ассемблера и результирующего машинного кода дает понимание архитектуры машины, что вряд ли обеспечивается при работе на языке высокого уровня. Хотя большинство специалистов в области программного обеспечения ведут разработки на языках высокого уровня, таких как Паскаль, С или Delphi, что проще при написании программ, наиболее мощное и эффективное программное обеспечение полностью или частично написано на языке ассемблера. Языки высокого уровня были разработаны для того, чтобы избежать специальной технической особенности конкретных компьютеров. А язык ассемблера, в свою очередь, разработан для конкретной специфики процессора. Следовательно, для того, чтобы написать программу на языке ассемблера для конкретного компьютера, следует знать его архитектуру. В настоящие дни видом основного программного продукта является EXE-файл. Учитывая положительные стороны этого, автор программы может быть уверен в ее неприкосновенности. Но зачастую порой это далеко не так. Существует так же и дисассемблер. С помощью дисассемблера можно узнать прерывания и коды программы. Человеку, хорошо разбирающегося в ассемблере не сложно будет переделать всю программу на свой вкус. Возможно отсюда появляется самая неразрешимая проблема – вирус. Зачем же люди пишут вирус? Некоторые задают этот вопрос с удивлением, некоторые с злостью, но тем не менее продолжают существовать люди которые интересуются этой задачей не с точки зрения нанесения какого-то вреда, а как интереса к системному программированию. Пишут Вирусы по разным причинам. Одним нравится системные вызовы, другим совершенствовать свои знания в ассемблера. Обо всем этом я постараюсь изложить в своей курсовой работе. Так же в нем сказано не только про структуру EXE-файла но и про язык ассемблера.

^ Язык Ассемблера.

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

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

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

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

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

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

Типичный современный компьютер (на базе i486 или Pentium) состоит из следующих компонентов (рис. 1).

Рис. 1. Компьютер и периферийные устройства

Рис. 2. Структурная схема персонального компьютера

Из рисунка (рис 1) видно, что компьютер составлен из нескольких физических устройств, каждое из которых подключено к одному блоку, называемому системным. Если рассуждать логически, то ясно, что он играет роль некоторого координирующего устройства. Давайте заглянем внутрь системного блока (не нужно пытаться проникнуть внутрь монитора - там нет ничего интересного, к тому же это опасно): открываем корпус и видим какие-то платы, блоки, соединительные провода. Чтобы понять их функциональное назначение, посмотрим на структурную схему типичного компьютера (рис. 2). Она не претендует на безусловную точность и имеет целью лишь показать назначение, взаимосвязь и типовой состав элементов современного персонального компьютера.

Обсудим схему на рис. 2 в несколько нетрадиционном стиле.
Человеку свойственно, встречаясь с чем-то новым, искать какие-то ассоциации, которые могут помочь ему познать неизвестное. Какие ассоциации вызывает компьютер? У меня, к примеру, компьютер часто ассоциируется с самим человеком. Почему?

Человек создавая компьютер где то в глубине себя думал что создает что то похожее на себя самого. У компьютера есть органы восприятия информации из внешнего мира - это клавиатура, мышь, накопители на магнитных дисках. На рис. 2 эти органы расположены справа от системных шин. У компьютера есть органы “переваривающие” полученную информацию - это центральный процессор и оперативная память. И, наконец, у компьютера есть органы речи, выдающие результаты переработки. Это также некоторые из устройств справа.

Современным компьютерам, конечно, далеко до человека. Их можно сравнить с существами, взаимодействующими с внешним миром на уровне большого, но ограниченного набора безусловных рефлексов.
Этот набор рефлексов образует систему машинных команд. На каком бы высоком уровне вы не общались с компьютером, в конечном итоге все сводится к скучной и однообразной последовательности машинных команд.
Каждая машинная команда является своего рода раздражителем для возбуждения того или иного безусловного рефлекса. Реакция на этот раздражитель всегда однозначная и “зашита” в блоке микрокоманд в виде микропрограммы. Эта микропрограмма и реализует действия по реализации машинной команды, но уже на уровне сигналов, подаваемых на те или иные логические схемы компьютера, тем самым управляя различными подсистемами компьютера. В этом состоит так называемый принцип микропрограммного управления.

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

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

Из всего вышесказанного можно сделать вывод, что, так как язык ассемблера для компьютера “родной”, то и самая эффективная программа может быть написана только на нем (при условии, что ее пишет квалифицированный программист). Здесь есть одно маленькое “но”: это очень трудоемкий, требующий большого внимания и практического опыта процесс. Поэтому реально на ассемблере пишут в основном программы, которые должны обеспечить эффективную работу с аппаратной частью. Иногда на ассемблере пишутся критичные по времени выполнения или расходованию памяти участки программы. Впоследствии они оформляются в виде подпрограмм и совмещаются с кодом на языке высокого уровня.

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

Данные регистры можно разделить на две большие группы:

^ 16 пользовательских регистров;

16 системных регистров.

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

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

Восемь 32-битных регистров, которые могут использоваться программистами для хранения данных и адресов (их еще называют регистрами общего назначения (РОН)):

шесть регистров сегментов: cs, ds, ss, es, fs, gs;

регистры состояния и управления:

Регистр флагов eflags/flags;

Регистр указателя команды eip/ip.

Рис. 3. Пользовательские регистры микропроцессоров i486 и Pentium

Почему многие из этих регистров приведены с наклонной разделительной чертой? Нет, это не разные регистры - это части одного большого 32-разрядного регистра. Их можно использовать в программе как отдельные объекты. Так сделано для обеспечения работоспособности программ, написанных для младших 16-разрядных моделей микропроцессоров фирмы Intel, начиная с i8086. Микропроцессоры i486 и Pentium имеют в основном 32-разрядные регистры. Их количество, за исключением сегментных регистров, такое же, как и у i8086, но размерность больше, что и отражено в их обозначениях - они имеют
приставку e (Extended).

^ Регистры общего назначения
Все регистры этой группы позволяют обращаться к своим “младшим” частям (см. рис. 3). Рассматривая этот рисунок, заметьте, что использовать для самостоятельной адресации можно только младшие 16 и 8-битные части этих регистров. Старшие 16 бит этих регистров как самостоятельные объекты недоступны. Это сделано, как мы отметили выше, для совместимости с младшими 16-разрядными моделями микропроцессоров фирмы Intel.

Перечислим регистры, относящиеся к группе регистров общего назначения. Так как эти регистры физически находятся в микропроцессоре внутри арифметико-логического устройства (АЛУ), то их еще называют регистрами АЛУ:

eax/ax/ah/al (Accumulator register) - аккумулятор.
Применяется для хранения промежуточных данных. В некоторых командах использование этого регистра обязательно;

ebx/bx/bh/bl (Base register) - базовый регистр.
Применяется для хранения базового адреса некоторого объекта в памяти;

ecx/cx/ch/cl (Count register) - регистр-счетчик.
Применяется в командах, производящих некоторые повторяющиеся действия. Его использование зачастую неявно и скрыто в алгоритме работы соответствующей команды.
К примеру, команда организации цикла loop кроме передачи управления команде, находящейся по некоторому адресу, анализирует и уменьшает на единицу значение регистра ecx/cx;

edx/dx/dh/dl (Data register) - регистр данных.
Так же, как и регистр eax/ax/ah/al, он хранит промежуточные данные. В некоторых командах его использование обязательно; для некоторых команд это происходит неявно.

Следующие два регистра используются для поддержки так называемых цепочечных операций, то есть операций, производящих последовательную обработку цепочек элементов, каждый из которых может иметь длину 32, 16 или 8 бит:

esi/si (Source Index register) - индекс источника.
Этот регистр в цепочечных операциях содержит текущий адрес элемента в цепочке-источнике;

edi/di (Destination Index register) - индекс приемника (получателя).
Этот регистр в цепочечных операциях содержит текущий адрес в цепочке-приемнике.

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

esp/sp (Stack Pointer register) - регистр указателя стека.
Содержит указатель вершины стека в текущем сегменте стека.

ebp/bp (Base Pointer register) - регистр указателя базы кадра стека.
Предназначен для организации произвольного доступа к данным внутри стека.

Стеком называют область программы для временного хранения произвольных данных. Разумеется, данные можно сохранять и в сегменте данных, однако в этом случае для каждого сохраняемого на время данного надо заводить отдельную именованную ячейку памяти, что увеличивает размер программы и количество используемых имен. Удобство стека заключается в том, что его область используется многократно, причем сохранение в стеке данных и выборка их оттуда выполняется с помощью эффективных команд push и pop без указания каких-либо имен.
Стек традиционно используется, например, для сохранения содержимого регистров, используемых программой, перед вызовом подпрограммы, которая, в свою очередь, будет использовать регистры процессора "в своих личных целях". Исходное содержимое регистров изатекается из стека после возврата из подпрограммы. Другой распространенный прием - передача подпрограмме требуемых ею параметров через стек. Подпрограмма, зная, в каком порядке помещены в стек параметры, может забрать их оттуда и использовать при своем выполнении. Отличительной особенностью стека является своеобразный порядок выборки содержащихся в нем данных: в любой момент времени в стеке доступен только верхний элемент, т.е. элемент, загруженный в стек последним. Выгрузка из стека верхнего элемента делает доступным следующий элемент. Элементы стека располагаются в области памяти, отведенной под стек, начиная со дна стека (т.е. с его максимального адреса) по последовательно уменьшающимся адресам. Адрес верхнего, доступного элемента хранится в регистре-указателе стека SP. Как и любая другая область памяти программы, стек должен входить в какой-то сегмент или образовывать отдельный сегмент. В любом случае сегментный адрес этого сегмента помещается в сегментный регистр стека SS. Таким образом, пара регистров SS:SP описывают адрес доступной ячейки стека: в SS хранится сегментный адрес стека, а в SP - смещение последнего сохраненного в стеке данного (рис. 4, а). Обратитим внимание на то, что в исходном состоянии указатель стека SP указывает на ячейку, лежащую под дном стека и не входящую в него.

Рис 4. Организация стека: а - исходное состояние, б - после загрузки одного элемента (в данном примере - содержимого регистра АХ), в - после загрузки второго элемента (содержимого регистра DS), г - после выгрузки одного элемента, д - после выгрузки двух элементов и возврата в исходное состояние.

Загрузка в стек осуществляется специальной командой работы со стеком push (протолкнуть). Эта команда сначала уменьшает на 2 содержимое указателя стека, а затем помещает операнд по адресу в SP. Если, например, мы хотим временно сохранить в стеке содержимое регистра АХ, следует выполнить команду

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

переведет стек в состояние, показанное на рис. 1.10, в. В стеке будут теперь храниться два элемента, причем доступным будет только верхний, на который указывает указатель стека SP. Если спустя какое-то время нам понадобилось восстановить исходное содержимое сохраненных в стеке регистров, мы должны выполнить команды выгрузки из стека pop (вытолкнуть):

pop DS
pop AX

Какого размера должен быть стек? Это зависит от того, насколько интенсивно он используется в программе. Если, например, планируется хранить в стеке массив объемом 10 000 байт, то стек должен быть не меньше этого размера. При этом надо иметь в виду, что в ряде случаев стек автоматически используется системой, в частности, при выполнении команды прерывания int 21h. По этой команде сначала процессор помещает в стек адрес возврата, а затем DOS отправляет туда же содержимое регистров и другую информацию, относящуюся к прерванной программе. Поэтому, даже если программа совсем не использует стек, он все же должен присутствовать в программе и иметь размер не менее нескольких десятков слов. В нашем первом примере мы отвели под стек 128 слов, что безусловно достаточно.

^ Структура программы на ассемблере

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

Предложения ассемблера бывают четырех типов:

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

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

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

строки комментариев, содержащие любые символы, в том числе и буквы русского алфавита. Комментарии игнорируются транслятором.

^ Синтаксис ассемблера

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

Рис. 5. Формат предложения ассемблера

Рис. 6. Формат директив

Рис. 7. Формат команд и макрокоманд

На этих рисунках:

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

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

код операции (КОП) и директива - это мнемонические обозначения соответствующей машинной команды, макрокоманды или директивы транслятора;

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

^ Как использовать синтаксические диаграммы? Очень просто: для этого нужно всего лишь найти и затем пройти путь от входа диаграммы (слева) к ее выходу (направо). Если такой путь существует, то предложение или конструкция синтаксически правильны. Если такого пути нет, значит эту конструкцию компилятор не примет. При работе с синтаксическими диаграммами обратим внимание на направление обхода, указываемое стрелками, так как среди путей могут быть и такие, по которым можно идти справа налево. По сути, синтаксические диаграммы отражают логику работы транслятора при разборе входных предложений программы.

Допустимыми символами при написании текста программ являются:

Все латинские буквы: A-Z, a-z. При этом заглавные и строчные буквы считаются эквивалентными;

Цифры от 0 до 9;

Знаки?, @, $, _, &;

Разделители, . () < > { } + / * % ! " " ? \ = # ^.

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

Лексемами являются:

идентификаторы - последовательности допустимых символов, использующиеся для обозначения таких объектов программы, как коды операций, имена переменных и названия меток. Правило записи идентификаторов заключается в следующем: идентификатор может состоять из одного или нескольких символов. В качестве символов можно использовать буквы латинского алфавита, цифры и некоторые специальные знаки - _, ?, $, @. Идентификатор не может начинаться символом цифры. Длина идентификатора может быть до 255 символов, хотя транслятор воспринимает лишь первые 32, а остальные игнорирует. Регулировать длину возможных идентификаторов можно с использованием опции командной строки mv. Кроме этого существует возможность указать транслятору на то, чтобы он различал прописные и строчные буквы либо игнорировал их различие (что и делается по умолчанию).

^ Команды ассемблера.

Команды ассемблера раскрывают возможность передавать компьютеру свои требования, механизм передачи управления в программе (циклы и переходы) для логических сравнений и программной организации. Однако, программируемые задачи редко бывают так просты. Большинство программ содержат ряд циклов, в которых несколько команд повторяются до достижения определенного требования, и различные проверки, определяющие, какие из нескольких действий следует выполнять. Некоторые команды могут передавать управление, изменяя нормальную последовательность шагов непосредственной модификацией значения смещения в командном указателе. Как говорилось ранее, существуют различные команды для различных процессоров, мы же будем рассматривать ряд некоторых команд для процессоров 80186, 80286 и 80386.

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

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

1 - после выполнения команды флаг устанавливается (равен 1);

0 - после выполнения команды флаг сбрасывается (равен 0);

r - значение флага зависит от результата работы команды;

После выполнения команды флаг не определен;

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

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

r8, r16, r32 - операнд в одном из регистров размером байт, слово или двойное слово;

m8, m16, m32, m48 - операнд в памяти размером байт, слово, двойное слово или 48 бит;

i8, i16, i32 - непосредственный операнд размером байт, слово или двойное слово;

a8, a16, a32 - относительный адрес (смещение) в сегменте кода.

Команды (в алфавитном порядке):

*Данные команды описаны подробно.

ADD
(ADDition)

Сложение

^ Схема команды:

add приемник, источник

Назначение: сложение двух операндов источник и приемник размерностью байт, слово или двойное слово.

Алгоритм работы:

сложить операнды источник и приемник;

записать результат сложения в приемник;

установить флаги.

Состояние флагов после выполнения команды:

Применение:
Команда add используется для сложения двух целочисленных операндов. Результат сложения помещается по адресу первого операнда. Если результат сложения выходит за границы операнда приемник (возникает переполнение), то учесть эту ситуацию следует путем анализа флага cf и последующего возможного применения команды adc. Например, сложим значения в регистре ax и области памяти ch. При сложении следует учесть возможность переполнения.

Регистр плюс регистр или память:

|000000dw|modregr/rm|

Регистр AX (AL) плюс непосредственное значение:

|0000010w|--data--|data, если w=1|

Регистр или память плюс непосредственное значение:

|100000sw|mod000r/m|--data--|data, если BW=01|

CALL
(CALL)

Вызов процедуры или задачи

^ Схема команды:

Назначение:

передача управления близкой или дальней процедуре с запоминанием в стеке адреса точки возврата;

переключение задач.

Алгоритм работы:
определяется типом операнда:

Метка ближняя - в стек заносится содержимое указателя команд eip/ip и в этот же регистр загружается новое значение адреса, соответствующее метке;

Метка дальняя - в стек заносится содержимое указателя команд eip/ip и cs. Затем в эти же регистры загружаются новые значения адресов, соответствующие дальней метке;

R16, 32 или m16, 32 - определяют регистр или ячейку памяти, содержащие смещения в текущем сегменте команд, куда передается управление. При передаче управления в стек заносится содержимое указателя команд eip/ip;

Указатель на память - определяет ячейку памяти, содержащую 4 или 6-байтный указатель на вызываемую процедуру. Структура такого указателя 2+2 или 2+4 байта. Интерпретация такого указателя зависит от режима работы микропроцессора:

^ Состояние флагов после выполнения команды (кроме переключения задачи):

выполнение команды не влияет на флаги

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

О б ъ е к т н ы й к о д (четыре формата):

Прямая адресация в сегменте:

|11101000|disp-low|diep-high|

Косвенная адресация в сегменте:

|11111111|mod010r/m|

Косвенная адресация между сегментами:

|11111111|mod011r/m|

Прямая адресация между сегментами:

|10011010|offset-low|offset-high|seg-low|seg-high|

CMP
(CoMPare operands)

Сравнение операндов

^ Схема команды:

cmp операнд1,операнд2

Назначение: сравнение двух операндов.

Алгоритм работы:

выполнить вычитание (операнд1-операнд2);

в зависимости от результата установить флаги, операнд1 и операнд2 не изменять (то есть результат не запоминать).

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

О б ъ е к т н ы й к о д (три формата):

Регистр или память с регистром:

|001110dw|modregr/m|

Непосредственное значение с регистром AX (AL):

|0011110w|--data--|data, если w=1|

Непосредственное значение с регистром или памятью:

|100000sw|mod111r/m|--data--|data, если sw=0|

DEC
(DECrement operand by 1)

Уменьшение операнда на единицу

^ Схема команды:

dec операнд

Назначение: уменьшение значения операнда в памяти или регистре на 1.

Алгоритм работы:
команда вычитает 1 из операнда. Состояние флагов после выполнения команды:

Применение:
Команда dec используется для уменьшения значения байта, слова, двойного слова в памяти или регистре на единицу. При этом заметьте то, что команда не воздействует на флаг cf.

Регистр: |01001reg|

^ Регистр или память: |1111111w|mod001r/m|

DIV
(DIVide unsigned)

Деление беззнаковое

Схема команды:

div делитель

Назначение: выполнение операции деления двух двоичных беззнаковых значений.

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

если делитель размером в байт, то делимое должно быть расположено в регистре ax. После операции частное помещается в al, а остаток - в ah;

если делитель размером в слово, то делимое должно быть расположено в паре регистров dx:ax, причем младшая часть делимого находится в ax. После операции частное помещается в ax, а остаток - в dx;

если делитель размером в двойное слово, то делимое должно быть расположено в паре регистров edx:eax, причем младшая часть делимого находится в eax. После операции частное помещается в eax, а остаток - в edx.

^ Состояние флагов после выполнения команды:

Применение:
Команда выполняет целочисленное деление операндов с выдачей результата деления в виде частного и остатка от деления. При выполнении операции деления возможно возникновение исключительной ситуации: 0 - ошибка деления. Эта ситуация возникает в одном из двух случаев: делитель равен 0 или частное слишком велико для его размещения в регистре eax/ax/al.

О б ъ е к т н ы й к о д:

|1111011w|mod110r/m|

INT
(INTerrupt)

Вызов подпрограммы обслуживания прерывания

^ Схема команды:

int номер_прерывания

Назначение: вызов подпрограммы обслуживания прерывания с номером прерывания, заданным операндом команды.

^ Алгоритм работы:

записать в стек регистр флагов eflags/flags и адрес возврата. При записи адреса возврата вначале записывается содержимое сегментного регистра cs, затем содержимое указателя команд eip/ip;

сбросить в ноль флаги if и tf;

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

^ Состояние флагов после выполнения команды:

Применение:
Как видно из синтаксиса, существуют две формы этой команды:

int 3 - имеет свой индивидуальный код операции 0cch и занимает один байт. Это обстоятельство делает ее очень удобной для использования в различных программных отладчиках для установки точек прерывания путем подмены первого байта любой команды. Микропроцессор, встречая в последовательности команд команду с кодом операции 0cch, вызывает программу обработки прерывания с номером вектора 3, которая служит для связи с программным отладчиком.

Вторая форма команды занимает два байта, имеет код операции 0cdh и позволяет инициировать вызов подпрограммы обработки прерывания с номером вектора в диапазоне 0–255. Особенности передачи управления, как было отмечено, зависят от режима работы микропроцессора.

О б ъ е к т н ы й к о д (два формата):

Регистр: |01000reg|

^ Регистр или память: |1111111w|mod000r/m|

JCC
JCXZ/JECXZ
(Jump if condition)

(Jump if CX=Zero/ Jump if ECX=Zero)

Переход, если выполнено условие

Переход, если CX/ECX равен нулю

^ Схема команды:

jcc метка
jcxz метка
jecxz метка

Назначение: переход внутри текущего сегмента команд в зависимости от некоторого условия.

^ Алгоритм работы команд (кроме jcxz/jecxz):
Проверка состояния флагов в зависимости от кода операции (оно отражает проверяемое условие):

если проверяемое условие истинно, то перейти к ячейке, обозначенной операндом;

если проверяемое условие ложно, то передать управление следующей команде.

Алгоритм работы команды jcxz/jecxz:
Проверка условия равенства нулю содержимого регистра ecx/cx:

если проверяемое услов