WWW.DISS.SELUK.RU

БЕСПЛАТНАЯ ЭЛЕКТРОННАЯ БИБЛИОТЕКА
(Авторефераты, диссертации, методички, учебные программы, монографии)

 

Pages:     | 1 || 3 | 4 |   ...   | 5 |

«(Учебное пособие) Иркутск 2007 УДК 681.3.6 С50 Смоленцев М.Ю. Программирование на языке Ассемблера для микропроцессоров i80x86: Учебное пособие.— Иркутск: ИрИИТ, 2007.— 600с. Ил. Табл. Библиогр.: назв. Рекомендовано ...»

-- [ Страница 2 ] --

Процессору «безразлично» содержимое ячейки памяти, на которую передалось управление, — он всегда пытается трактовать ее как код инструкции префикс). Если ошибочно управление передалось на область данных, то дальнейшее поведение процессора непредсказуемо. Защита не позволяет передать управление на сегмент данных — сработает исключение защиты, которое обрабатывается операционной системой, и ошибочный процесс будет принудительно завершен. Чтобы выдержать принцип хранимости программы, на время ее загрузки в память или программной модификации ту же область объявляют сегментом данных, в который разрешена запись. Система защиты может полностью контролировать распределение памяти, генерируя исключения в случаях различных нарушений. Эффективность защиты (устойчивость компьютера к ошибкам) в значительной мере определяется предусмотрительностью разработчиков операционной системы.

Чем сложнее программа и больше объем обрабатываемых ею данных, тем больше ее потребности в памяти. В первых процессорах семейства память предоставлялась в виде сегментов с размером по 64 Кбайт, а суммарный объем программно адресуемой памяти не превышал значения в Мбайт. Архитектуpa PC ограничивала размер оперативной памяти объемом в 640 Кбайт, начиная с нулевых адресов. Эта область называется стандартной памятью (conventional memory), и для прикладных программ из нее остается доступной область порядка 400-550 Кбайт (остальное «съедает»

операционная система вместе с разными драйверами). Потребности решаемых задач довольно быстро переросли эти ограничения, и в процессоры ввели средства организации виртуальной памяти. Впервые они появились в 80286, но удобный для употребления вид приняли только в 32-разрядных процессорах (80386 и выше). Во-первых, было снято ограничение на 64Кбайтный размер сегмента — теперь любой сегмент может иметь почти произвольный размер до 4 Гбайт. Во-вторых, был введен механизм страничной переадресации памяти (paging). Теперь любая страница (область фиксированного размера) виртуальной логической памяти (адресуемой программой в пределах выделенных ей сегментов) может отображаться на любую область физической памяти (реально установленной оперативной). Отображение поддерживается с помощью специальных таблиц страничной переадресации, в которых кроме связи адресов есть указание на присутствие страницы в физической памяти на данный момент времени. Теперь страница памяти не нужная процессору в данный момент времени, может быть выгружена устройство хранения (диск). На ее место можно загрузить нужную страницу. Заявку на загрузку нужной страницы делает сам процессор, без каких-либо усилий выполняемой программы:

если программе потребовалась ячейка виртуальной памяти из страницы, образа которой сейчас нет в физической памяти. вырабатывается специальное исключение. Обработчик этого исключения (это часть ОС) найдет свободную физическую страницу (выгрузив на диск ту, которая, по его мнению, пока не нужна), «подкачает» на нее с диска требуемую информацию и вернет управление процессу, прерванному исключением. Этот процесс ничего «не заметит» (кроме некоторой задержки выполнения инструкций). Таким образом, в распоряжение всех процессов, исполняемых на компьютере псевдопараллельно, предоставляется виртуальная оперативная память, размер которой ограничен суммой объема физической оперативной памяти и областью дисковой памяти, выделенной для подкачки страниц.Память может быть логически организована в виде одного или множества сегментов переменной длины (в реальном режиме – фиксированный) Дескрипторы сегментов — это специальные указатели, определяющие расположение сегмента в памяти.

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

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

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

1. CR0, CR1, CR2 — 32-разрядные управляющие регистры;

2. LDTR — регистр локальной таблицы дескрипторов;

3. GDTR — регистр глобальной таблицы дескрипторов;

4. IDTR — регистр дескрипторной таблицы прерываний;

5. TR — регистр задачи;

6. DR0-DR7 — отладочные регистры;

7. TR3-TR7 — тестовые регистры.

Регистры CR0-CR3 предназначены для общего управления системой.



Регистры управления доступны только программам с уровнем привилегий 0. Регистр CR0 содержит набор бит, которые управляют режимами работы микропроцессора и отражают его состояние глобально, независимо от конкретных выполняющихся задач. Функции регистра CR1 пока не определены. Он зарезервирован для будущего использования.

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

Регистр дескрипторной таблицы прерываний хранит 32-битовый базовый адрес дескрипторной таблицы прерываний микропроцессора IDT (системной области памяти, в которой размещается таблица прерываний) и 16-битовое значение предела, представляющее собой размер в байтах таблицы IDT.

16-разрядный регистр локальной таблицы дескрипторов содержит селектор, описывающий для данной задачи таблицы дескрипторов. Этот селектор является указателем в таблице GDT, который и описывает сегмент, содержащий локальную дескрипторную таблицу LDT.

16-разрядный регистр задачи хранит селектор сегмента, то есть указатель на дескриптор в таблице GDT, в котором записывается информация о текущей задаче, выполняемой микропроцессором. Этот дескриптор описывает текущий сегмент состояния задачи (TSS — Task Segment Status).

Этот сегмент создается для каждой задачи в системе, имеет жестко регламентированную структуру и содержит контекст (текущее состояние) задачи. Основное назначение сегментов TSS — сохранять текущее состояние в момент переключения на другую задачу.

Регистры GDTR, IDTR 48-разрядные и хранят физические адреса этих таблиц, которые непосредственно выдаются на шину адреса микропроцессора.

32-разрядные регистры DR0-DR3 предназначены для задания линейных адресов четырех точек прерывания. Регистр DR6 — регистр состояния отладки. Биты этого регистра устанавливаются в соответствии с причинами, которые вызывали возникновение последнего исключения с номером 1. Регистр DR7 — регистр управления отладкой. В этом регистре для каждого из четырех регистров контрольных точек отладки DR0-DR3 имеются поля, с помощью которых можно уточнить условия, при которых следует сгенерировать прерывание.

выполнения команд и влияет на состояние самого микропроцессора. 32-битовый регистр EFLAGS содержит информацию, которая используется, скорее побитно, нежели как 32-битное число. Младшие 16 разрядов регистра EFLAGS, для совместимости со старыми программами, полностью аналогичны регистру FLAGS i8086, младших разрядов которого, в свою очередь, аналогичны регистру FLAGS i Регистр EFLAGS представляет собой набор флагов, устанавливаемых или сбрасываемых по результатам выполняемых команд. Флаг — это переменная длиной 1 бит, используемая в командах условного перехода.

Если значение этой переменной равно 1, то считается, что флаг установлен, если 0 – сброшен.

Флаги делятся на:

• 8 флагов состояния (NT, IOPL, SF, ZF, AF, PF, CF) эти флаги могут изменяться после выполнения машинных команд. Флаги состояния регистра EFLAGS отражают особенности результата исполнения арифметических или логических операций. Это дает возможность анализировать состояние вычислительного процесса и реагировать на него с помощью команд условных переходов и вызовов подпрограмм. Для работы с флагом CF существуют специальные команды CLC (очистить флаг CF), STC (установить флаг CF), CMC (инвертировать флаг CF);

• флаг управления (DF) используется цепочечными командами. Значение этого флага определяет направление поэлементной обработки в этих операциях: от начала строки к концу (DF=0), либо, наоборот, от конца строки к ее началу (DF=1). Для работы с флагом DF существуют специальные команды CLD (очистить флаг DF), STD (установить флаг DF).

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

• 5 системных флагов (FT, IF, RF, VM, AC) управляющих вводом/ выводом, маскируемыми прерываниями, отладкой, переключением между задачами и виртуальным режимом 8086. Прикладным программам не рекомендуется модифицировать без необходимости эти флаги, так как в большинстве случаев это приведет к прерыванию работы программы. ;

Для работы с флагом IF существуют специальные команды CLI (очистить флаг IF), STI (установить флаг IF) • неопределенные биты (XX) являются зарезервированными, то есть в настоящий момент они не имеют значения, однако могут быть использованы для специальных целей в последующих версиях микропроцессора либо уже используются в недокументированных целях. Поэтому программа не должна как-либо использовать ни один зарезервированный бит. Хотя, чем черт не шутит! Если у вас есть старенький компьютер и если Вам его не жалко, можно и поэкспериментировать.

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

• CF флаг переноса (Carry Flag) устанавливается при переносе или займе старшего бита в арифметических операциях, в остальных случаях сбрасывается;

• PF флаг паритета (Parity Flag) устанавливается, если 8 младших разрядов результата содержат четное число единиц; в противном случае сбрасывается;

• AF вспомогательный флаг переноса (Auxiliary carry Flag). Только для команд работающих с BCD числами. Устанавливается при переносе или займе старшего бита в результате сложения, в остальных случаях сбрасывается;

• ZF флаг нуля (Zero Flag) устанавливается в случае получения нулевого результата при выполнении очередной команды и сбрасывается при остальных ненулевых значениях;

SF флаг знака (Sign Flag) устанавливается при единичном значении старшего бита результата -признаке отрицательного числа;

TF флаг трассировки (Trace Flag) помогает отлаживать программы.

Этот флаг не устанавливается в результате работы микропроцессора, а устанавливается программой с помощью специальной команды. Его также называют флагом трассировки, флагом пошаговой работы или флагом ловушки. Используется преимущественно для осуществления пошагового режима работы. Когда флаг TF установлен, микропроцессор i80x86 автоматически вырабатывает сигнал внутреннего прерывания INT 1h после выполнения каждой команды. Это обеспечивает удобство проверки программ, написанных на машинном коде, поскольку они при этом выполняются команда за командой. Адрес сервисной процедуры организации пошагового режима должен быть определен в абсолютных адресах от 00004h до 00007h. При генерации прерывания INT 1h микропроцессор i80x86 автоматически загружает в стек содержимое регистра флагов (с единичным флагом ловушки), после чего обнуляет флаги ловушки и прерываний. Таким образом, микропроцессор i80x86 не переходит в пошаговый режим, пока выполняется сама процедура обслуживания прерывания, которая реализует различные диагностические операции. Процедура обслуживания прерывания INT 1h может включать в себя отображение на дисплее такой информации, как содержимое регистров и определенной области памяти сразу после выполнения команды. Последняя машинная команда в процедуре обслуживания — команда IRET (возврат из прерывания). Этим восстанавливается прежнее единичное состояние флага TF, и по завершении следующей команды вновь генерируется прерывание INT 1h.

Флаг ловушки TF занимает восьмой разряд в регистре флагов. Для установки флага TF в ноль или единицу можно использовать команду POPF.

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

IF флаг прерываний (Interrupt Flag) управляет внешними прерывания.

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

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

EFLAGS

• NT флаг вложенности задачи (Nested Task). Данный флаг используется в защищенном режиме. NT устанавливается, чтобы показать что выполнение данной задачи вложено в пределах другой задачи. Если он установлен, то сегмент состояния текущей вложенной задачи имеет достоверную обратную связь с сегментом состояния предыдущей задачи.

Данный бит устанавливается или сбрасывается командами передающими управление другим задачам. Значение NT в EFLAGS проверяется командой IRET. Чтобы его установить следует выполнять внутризадачное возвращение или внешнезадачное возвращение. Команды POPF или IRET будут оказывать воздействие на установку данного бита согласно образу EFLAGS на любом уровне привилегий.

• RF флаг возобновления (Resume Flag) используется при пошаговом режиме или совместно с точками прерываний регистров отладки. Он проверяется на границе команды, перед обработкой точки останова. Если RF установлен, то любая ошибка отладки будет игнорирована на следующей команде. RF автоматически сбрасывается при успешном окончании каждой команды (ошибки не сигнализируются), кроме команд IRET, POPF, JMP, CALL, ENTER, которые вызывают включение задачи. Эти команды устанавливают RF в соответствии с определенным образом памяти.

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

• IOPL флаг уровня привилегий ввода /вывода (Input/Output Privilege Level). Используется в защищенном режиме работы микропроцессора для контроля доступа к командам ввода/вывода в зависимости от привилегированности задачи. Уровень привилегий ввода/вывода (IOPL) указывает максимальное значение текущего уровня привилегий (ТУП). Для максимально допустимого значения ТУП, при выполнении команд ввода/вывода без генерирования прерывания по 13 исключению, он также указывает максимальное значение ТУП, позволяющее изменить бит IF, когда новые значения загружаются из стека в регистры FLAGS или EFLAGS. Команды POPF и IRET могут изменять поле IOPL, когда выполняются при ТУП=0. Операции включения задач всегда изменяют поле IOPL, когда новый образ флага загружается из сегмента состояния задачи.

• VM флаг виртуального режима (Virtual 8086 Mode) обеспечивает виртуальный 8086 режим в пределах защищенного. Если он установлен, в то время, когда микропроцессор находится в защищенном режиме, включается в виртуальную 8086 операцию, манипулируя загрузкой сегментов, как это делает 8086, генерируя 13 прерывание привилегированных операционных кодов. Бит VM может быть установлен в защищенном режиме командой IRET, если текущий привилегированный уровень равен 0, и путем включения задач на любом уровне привилегий. Бит VM не подчиняется действию команды POPF. PUSHF всегда посылает в этот разряд, даже, если работает в виртуальном 8086 режиме. Образ EFLAGS, сохраненный в стеке во время обработки прерывания или во время включения задачи, будет содержать единицу в этом бите, если прерывание обрабатывалось как виртуальная 8086 задача.

Не все операции устанавливают флажки. За приблизительное правило можно принять, что:

а) арифметические операции действуют на все флажки, б) логические операции (кроме операции NOT) сбрасывают флажки переноса и переполнения (OF и CF) и действуют на все другие флажки, в) операции приращения и уменьшения на 1 (команды INC и DEC) не действуют на флажок переноса и действуют на все другие флажки (нельзя использовать флажок переноса для контроля переполнения при операции уменьшение на 1), Не изменяют флажки:

а) все операции перемещения (MOV, MOVZX, MOVSX, LEA, LDS, LES, LFS, LGS, LSS, XCHG, BSWAP), б) все операции с портами (IN, OUT, INS, OUTS), в) все команды перехода (JMP, Jcc, JCXZ, JECXZ), г) все команды преобразования (CBW, CWD, CWDE, CDQ), д) все строковые команды (кроме SCAS и CMPS), е) все операции со стеком (кроме POPF).

сегмента команд, на начало которого указывает регистр CS. Поэтому абсолютный адрес этой команды определяется парой регистров CS и IP/EIP. За исключением случаев перехода, последовательно выполняемые команды в памяти следуют друг за другом, содержимое регистра IP/EIP увеличивается после выполнения каждой команды.

В ранних микропроцессорах (до i8086) выборка команд осуществлялась следующим образом: когда микропроцессор был готов к выполнению следующей команды, он посылал содержимое IP по адресной шине во внешнюю память, считывал в соответствующей адресу ячейки памяти байт данных и по шине данных пересылает его в регистр IP. Затем микропроцессор действовал в соответствии с командой и в процессе ее выполнения мог один или несколько раз обращаться к внешней памяти. Одна машинная команда может иметь длину более одного байта. В зависимости от длины команды (для микропроцессоров младше i80386 от 1 до 6 байт, для i80386 и старше от 1 до 15 байт) содержимое увеличивается на 1, 2 или более байт, если это не команда перехода. (При выполнении команды перехода содержимое CS и IP/EIP может измениться на любую величину.) Изменение содержимого в любом из регистров CS и IP/EIP есть ничто иное, как переход. Поэтому содержимое регистра IP/EIP (как и CS) можно менять только командами перехода.

Очередь команд. Для увеличения скорости выполнения программ в микропроцессоре i8086 регистр IP был дополнен 6-байтной очередью команд, организованной по принципу FIFO («первым пришел — первым ушел»). Очередь команд непрерывно заполняется только тогда когда системная шина не требуется для других операций. А в тот момент когда системная шина занята — команды выбираются из очереди команд.

Конвейеризация вычислений. С появлением микропроцессора i80486, для еще большего увеличения скорости выполнения программ очередь команд была дополнена конвейером. Конвейер — специальное устройство, реализующее такой метод обработки команд внутри микропроцессора, при котором исполнение команды разбивается на несколько этапов. i имел пятиступенчатый конвейер. Соответствующие пять этапов включали:

• выборку команды из очереди команд;

• декодирование команды;

генерацию адреса, при котором определяются адреса операндов в памяти;

• выполнение операции с помощью АЛУ;

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

Таким образом, на стадии выполнения каждая машинная команда как бы разбивается на более элементарные операции. Преимущество такого подхода в том, что очередная команда после ее выборки попадет в блок декодирования. Таким образом, блок выборки свободен и может выбрать следующую команду. В результате на конвейере могут находиться в различной стадии выполнения пять команд. Скорость вычисления в результате существенно возрастает. Микропроцессоры, имеющие один конвейер, называются скалярными. Pentium имеет два конвейера, Pentium-II — три, потому эти микропроцессоры называются суперскалярными. Микропроцессоры Pentium-III и Pentium-4 называют гиперконвеерными, длина конвеера Pentium-III — 10, а у Pentium-4 — 20 ступеней.

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

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

Описание любого микропроцессора выглядит иначе, чем описание большинства других микросхем, отчасти из-за присутствия в нем обширного раздела, посвященного «системе команд». Для пользования микропроцессором важно ясно понимать, что «делают» команды: как адресовать память («типы адресации»), как обращаться к регистрам, куда попадают результаты арифметических операций, как устроить условное ветвление (переходы) и т.д. каждая команда микропроцессора i80x86 состоит из одного, двух или более байт, причем первый байт — это код операции (КОП) команды. КОП определяет природу команды; по КОПу микропроцессор i80x86 определяет, нужны ли дополнительные байты, и, если да, микропроцессор получает их в последующих циклах. Поскольку байт КОПа состоит из 8 бит, может существовать 256 разных КОПов. Ограничение в команд было обойдено так как некоторые коды (80h, 0D1h и другие) служат шлюзами к следующим таблицам кодов. В приложении таблица представляет полный список команд микропроцессора i80x86.

В таблице команды даны не в шестнадцатиричном машинном представлении (машинном коде), а в виде мнемокодов языка ассемблера, поскольку микропроцессор i80x86 обычно программируют на этом более удобочитаемом языке, обозначая адреса и числа легко запоминаемыми именами вместо тех чисел, с которыми в действительности оперирует микропроцессор. После того как программа написана на языке ассемблера, стандартная программа, известная также под названием «ассемблер», преобразует мнемокоды и имена в числа. В связи с этим язык ассемблера называют «входным языком» в отличии от числового «объектного языка», который микропроцессор i80x86 использует непосредственно. Таким образом, программа ассемблер переводит на объектный язык программы, составленные на входном языке. В процессе этого перевода одна команда языка ассемблер может быть преобразована в 1, 2 или более байт объектного языка в зависимости от конкретной команды.

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

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

Одним из мотивов было желание предоставить «интеллектуальным»

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

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

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

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

NMI INTA

Микропроцессор i80x86 имеет три линии прерываний RESET, NMI и INTR по которым внешние устройства могут передавать свои запросы на обслуживание со стороны микропроцессора.

Запуск микропроцессора i80x86. Аппаратный сброс выполняется процессором при включении питания или при появлении запроса в линии RESET#. Микропроцессор i80x86 прекращает выполнение инструкций и перестает управлять системной шиной. Процессору устанавливается коэффициент умножения тактовой частоты, режим (WB/WT) работы кэша, роль процессора в многопроцессорных системах, способ подачи сигналов преываний (для процессоров, имеющих APIC) и некоторые другие параметры.

Сброс переводит процессор в реальный режим и устанавливает ряд регистров ят следующие действия:

• Устанавливает флаг IF в нулевое состояние. Это приводит к невозможности выполнения маскируемых прерываний;

• Обнуляет регистры сегментов DS, ES и SS;

• Обнуляет указатель команд;

Засылает число 0FFFFFFF0h в регистр сегмента команд Микропроцессор i80x86 начинает работу с обращения к ячейке с адресом 0FFFFFFF0h. Эта ячейка памяти содержит команду JMP, которая передает управление процедуре инициализации, запускающей компьютер.

Векторы прерываний служат для идентификации процедур, необходимых для обслуживания требования прерывания. Каждому внешнему требованию на прерывание может быть поставлен в соответствие код прерывания в пределах от 0 до 255. В микропроцессоре i80x86 существует векторов прерываний — по одному вектору на каждый тип прерывания.

Таблица векторов прерываний занимает 1024 младших байта памяти — ячейки с физическими адресами от 00000 до 003FFh — и имеет 256 входов в соответствии с количеством векторов.

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

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

Если флаг прерываний IF=0 (прерывание не возможно), то требование маскируемого прерывания игнорируется и микропроцессор продолжает выполнять очередную команду текущей программы. Если IF=1 (прерывание разрешено), микропроцессор подтверждает требование прерывания и передает управление той процедуре, которая должна обслужить поступившее требование. Для выполнения требования маскируемого прерывания микропроцессор автоматически выполняет следующую последовательность действий:

1. генерируется сигнал подтверждения внешнего прерывания INTA. Этот сигнал сообщает внешнему устройству о том что 2. считывается код прерывания N, поступившего на шину данных;

3. включить в стек текущее содержимое FLAGS (EFLAGS), CS и IP (EIP) (именно в таком порядке);

4. сбросить флажки IF и TF, что предотвратит возможность выполнения любого вновь поступающего маскированного прерывания и делает невозможным пошаговый режим;

5. передать содержимое ячеек памяти 4N и 4N+1 в IP(EIP), а содержимое памяти по адресам 4N+2 и 4N+3 в CS.

После выполнения пункта 5 управление передается процедуре обслуживания прерывания, содержащей машинные команды, необходимые для удовлетворения требований маскированного прерывания. Одной из таких команд, содержащихся в процедуре обслуживания, является команда STI (установить прерывание), которая устанавливает флаг IF=1 и тем самым делает возможным выполнение новых требований, поступающих на INTR.

Немаскируемые прерывания. Это внешние требования, поступающие в микропроцессор по линии NMI. Обычно ими являются прерывания сигнализирующими микропроцессору о внешних событиях особой важности (носящих катастрофический характер), таких как отключение питания, сбой памяти и т.п. Немаскируемые прерывания принимаются микропроцессором всегда независимо от состояния флага прерываний IF, поэтому немаскируемые прерывания имеют более высокий приоритет по сравнению с маскируемыми прерываниями. Им присвоен тип 2. Микропроцессор в ответ на требование немаскируемого прерывания выполняет следующие действия:

1. включить в стек текущее содержимое FLAGS (EFLAGS), CS и IP(EIP);

2. сбросить флажки IF и TF;

3. передать содержимое ячеек памяти 00008h и 00009h в IP(EIP), а содержимое памяти по адресам 0000Ah и 0000Bh в CS.

После выполнения пункта 3 управление передается процедуре обслуживания прерывания, содержащей машинные команды, необходимые для удовлетворения требования, поступившего по линии NMI.

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

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

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

Прерывание из-за ошибки деления. Микропроцессор автоматически генерирует прерывания типа 0 немедленно вслед за операциями DIV (целочисленное деление без учета знака) или IDIV (целочисленное деление с учетом знака) при возникновении следующих условий:

• если результат занимает больше 8, 16 или 32 бит при делении соответственно 8-, 16- или 32-разрядных чисел.

Адрес процедуры обслуживания прерывания типа 0 должен определяться ячейками памяти с физичискими адресами с 00000h по 00003h.

Пошаговое прерывание. Когда флаг TF установлен, микропроцессор i80x86 автоматически вырабатывает сигнал внутреннего прерывания INT 1h после выполнения каждой команды. Это обеспечивает удобство проверки программ, написанных на машинном коде, поскольку они при этом выполняются команда за командой. Адрес сервисной процедуры организации пошагового режима должен быть определен в ячейках памяти с физическими адресами от 00004h до 00007h. При генерации прерывания INT 1h микропроцессор i80x86 автоматически загружает в стек содержимое регистра флагов (с единичным флагом ловушки), после чего обнуляет флаги ловушки и прерываний. Таким образом, микропроцессор i80x86 не переходит в пошаговый режим, пока выполняется сама процедура обслуживания прерывания, которая реализует различные диагностические операции. Процедура обслуживания прерывания INT 1h может включать в себя отображение на дисплее такой информации, как содержимое регистров и определенной области памяти сразу после выполнения команды.

Последняя машинная команда в процедуре обслуживания — команда IRET (возврат из прерывания). Этим восстанавливается прежнее единичное состояние флага TF, и по завершении следующей команды вновь генерируется прерывание INT 1h.

Прерывание в точке. Прерывание в заданной точке программы используется для отладки при ее написании и тестировании. Микропроцессор генерирует прерывание типа 3 немедленно по завершении выполнения команды INT 3h. Шестнадцатеричный машинный код этой команды 0CCh используется как команда прерывания в заданной точке программы. Этот код вставляется в любое место программы, где необходимо прервать ее нормальное выполнение, и с помощью процедуры, обслуживающей это прерывание отобразить критическую информацию, такую, как содержимое внутренних регистров микропроцессора и ячеек памяти. Поскольку минимальная смысловая часть команды INT 3h занимает один байт, для использования в различных программных отладчиках для установки точек прерывания (break point) машинный код 0CCh может подменить любую команду, обозначая тем самым точку программы, в которой необходимо осуществить прерывание. Адрес сервисной процедуры организации обработки прерывания в заданной точке программы должен быть определен в ячейках памяти с физическими адресами от 0000Ch до 0000Fh.

Прерывание, если переполнение. Микропроцессор генерирует прерывание типа 4 или INTO если обнаружено, что OF=1. Если команда в программе может в результате своей работы установить флаг переполнения OF (к примеру, арифметические команды), то для обнаружения и обработки такой ситуации можно использовать команду INTO или INT 4h (машинный код 0CEh). Особенности передачи управления и обработки (корректировки) результата зависит от режима работы микропроцессора. Адрес сервисной процедуры организации обработки прерывание по переполнению должен быть определен в ячейках памяти с физическими адресами от 00010h до 00013h.

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

2. Какие типы сегментов вы знаете?

3. Чему равен размер сегмента?

4. Если физический адрес равен 5A23016, когда CS=520016, каким он будет при изменении CS на 780016?

5. Пусть эффективный адрес данного равен 2359 16 и DS=490B16. Чему равен физический адрес данного?

6. Найти состояние флагов AF, SF, ZF, CF, OF и PF после прибавления 62A016 к следующим числам: а) 123416, б) 432116, в) CFA016, г) 9D6016.

7. Найти состояние флагов SF, ZF, CF, OF и PF после вычитания 4AE016 из следующих чисел: а) 123416, б) 5D9016, в) 909016, г) EA Глава 4. Этапы создания программы на языке ассемблера Разработка программы включает несколько этапов:

1. Подготовка (изменение) исходного текста программы.

2. Ассемблирование программы (получение объектного кода) 3. Компоновка программы (получение исполняемого файла программы) 4. Отладка программы.

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

Текст программы записывается в один или несколько текстовых файлов. Имена файлов могут быть любыми, но для файлов, содержащих текст программы, принято расширение *.asm, а для файлов с определением констант и новых типов — расширение *.inc. Эти файлы являются текстовыми, их можно подготовить с помощью стандартных редакторов текста или с использование интегрированных сред разработки программ.

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

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

Обычно для получения файлов объектного кода необходимо выполнить соответствующую программу ассемблера (программы MASM.EXE и ML.EXE фирмы Microsoft и TASM.EXE, TASMX.EXE, TASM32.EXE или BASM.EXE фирмы Borland) указав в командной строке имя файла с текстом программы. Например, если у текстового файла с исходным текстом программы название prog.asm Эта форма вызова является минимально необходимой, кроме имени текстового файла, необходимо указывать опции ассемблирования. Более подробную информацию об опциях программы ассемблирования следует искать в документации к этим программам.

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

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

Процесс объединения объектных модулей в один файл осуществляется специальной программой-компоновщиком или сборщиком (программа LINK.EXE фирмы Microsoft и TLINK.EXE фирмы Borland), которая выполняет связывание объектных модулей и машинного кода стандартных функций, находя их в библиотеках, и формирует на выходе работоспособное приложение — исполнимый код для конкретной платформы.

Исполнимый код — это законченная программа, которую можно запустить на любом компьютере, где установлена операционная система, для которой эта программа создавалась. Имя исполняемого файла задастся именем первого *.OBJ файла:

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

До тех пор пока Вы не наберетесь достаточного опыта в программировании на языке ассемблера, за исключением учебных, тривиальных программ, в отладке будет нуждаться любая ваша программа. Для этого используются различные отладчики (CW.EXE — CodeView фирмы Microsoft и TD.EXE, TD286.EXE или TD386.EXE — Turbo Debugger фирмы Borland, SOFTICE.EXE фирмы NuMega), позволяющие в процессе выполнения программы контролировать значения регистров или переменных, при необходимости изменять их. Можно просматривать содержимое различных участков памяти. Можно выполнять программы по шагам или расставить точки останова (BREAK POINTS), которые вызовут прекращение работы программы и переход управления к отладчику.

4.5. Использование интегрированных сред Для подготовки текста программы на языке ассемблера очень удобно использование интегрированных программных сред. Такие возможности предоставляются практически всеми разработчиками ассемблеров, например: PWD — Programmer Workbench для компиляторов masm, QC — Quick C для компиляторов QuickAssembler фирмы Microsoft, все компиляторы языка C и C++ фирмы Borland (TC и BC). Интегрированные среды позволяют получить быстрый доступ к справочной информации. Можно сразу же ассемблировать и скомпоновать набранный текст, провести его отладку, а затем вновь вернуться к редактированию.

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

;тело вашей программы ;данные вашей программы Разберем ее подробнее. В первой строке.686P — это директива описания типа микропроцессора (может быть еще и.8086,.8087,.186,.286,.

287,.386,.387,.486,.586,.mmx с добавлением или без добавления букв P (привилегированные команды) и C или N (непривилегированные команды)). Если не указывать тип микропроцессора, то программа будет сгенерирована в кодах i8086.

.8086 Разрешены инструкции базового процессора i8086 (и идентичные им инструкции процессора i8088). Запрещены инструкции более поздних процессоров.

.186.286 Разрешены инструкции соответствующего процессора x.386.486 (x=1,…,6). Запрещены инструкции более поздних процессоров.

.187.287 Разрешены инструкции соответствующего сопроцессора x.387.487 наряду с инструкциями процессора x86. Запрещены инструкции более поздних процессоров и сопроцессоров.

.286c.386c Разрешены НЕПРИЛЕГИРОВАННЫЕ инструкции соответc.586c ствующего процессора x86 и сопроцессора x87. Запрещены.686c инструкции более поздних процессоров и сопроцессоров.

.286p.386p Разрешены ВСЕ инструкции соответствующего процессора.486p.586p x86 включая привелигерованные команды и инструкции соp процессора x87. Запрещены инструкции более поздних процессоров и сопроцессоров.

Строка.model flat говорит, что будет создаваться exe-файл для 32разрядной операционной системы Windows.

Large несколько, несколько, Far far Код может размещаться в Huge несколько, несколько, huge huge Код может размещаться в Flat не ограни- не ограни- flat flat Соответствует варианту В третьей строчке написано.code. По этой команде (директиве) будет определен сегмент кода. Это нужно, потому что у реальных программ код (команды) и данные (переменные) должны быть разделены. Если Вы хотите в каком-либо месте программы вставить данные, то пишите.data, а потом уже сами данные (но их можно и не разделять). Я рекомендую вставлять данные между командами ret и end start. start: — это место, где находится точка входа в программу. На языке ассемблера всегда надо помечать место, где находится начало программы (первая команда). Строка ret нужна, чтобы выйти из программы — если бы ее не было, то программа бы «завесила» компьютер. Последняя строчка end start завершает текст исходной программы.

4.7. Пишем первую программу на языке ассемблера Итак это была теория. А вот это практика. Попробуем написать программу на языке ассемблера самостоятельно. Все что вам нужно это компьютер, причем только PC, программа tasm.exe (можно masm.exe — если вам нравится Microsoft), программа tlink.exe (можно link.exe — то же самое, но для masm’а). Не забудьте также перезагрузится в режим эмуляции MS-DOS, чтобы избежать проблем с зависанием Windows.

Программы на языке ассемблера пишут не ради абстрактного пересчета каких-либо данных или создания виртуальной реальности, а чтобы программно управлять каким-нибудь «железом». Для нашей первой программы на языке ассемблера используем в качестве «железа» сам компьютер. Заставим его для начала перезагрузится, причем в «холодную». Сначала наберем с помощью текстового редактора вот такой файл:

jmp dword ptr reboot reboot dd 0FFFF0000h Сохраните этот файл под любым именем и дайте ему расширение asm. Чтобы запустить эту программу, надо будет этот файл ассемблировать и скомпоновать. Ассемблируют программы с помощью tasm.exe или masm.exe. Допустим, что у вас tasm, тогда наберите в командной строке команду: tasm имя_файла.asm чтобы его ассемблировать. Если все набрано правильно, то в текущем каталоге появится файл с именем исходника, но с расширением obj.

Это объектный код нашей программы — шаг на пути от исходной программы на языке ассемблера к исполнимой программе (exe’шнику или com’у). Получив obj-файл, его надо скомпоновать. Это делается с помощью tlink.exe (link.exe). Вводим команду: tlink /t/x имя_файла.obj.

/t означает, мы хотим получить на выходе файл com, а не exe.

/x не позволяет появляться программному «мусору» в виде mapфайлов. Если все сделано правильно, то появится готовая программа длиной всего 8 байт, запустив которую Вы заставите компьютер перезагрузиться.

Настало время объяснить, как все это работает. Первое — Вы наверняка знаете, как работает ваш микропроцессор, если нет — то это не сложно понять. Вся работа микропроцессора заключается в том, что он берет из памяти подряд числа, смотрит, какой команде они соответствуют и, если какой-то соответствуют, он эту команду выполняет. Если число не соответствует никакой команде — микропроцессор зависнет. То есть в программе на языке ассемблера мы должны в нужном порядке расписать команды микропроцессора, которые мы хотим, чтобы он выполнял. Теперь представьте, что мы включили компьютер, чтобы поиграть или залезть в Internet. Как микропроцессор узнает, откуда взять ему самую первую команду для выполнения? Естественно, никак. Просто разработчики микропроцессора из фирмы Intel решили, что микропроцессор будет считывать первую после включения команду по некоему адресу. А потом решили по этому адресу поместить BIOS (Basic Input/Output System — базовая система ввода-вывода — программа, управляющая элементарными функциями компьютера. Она отвечает за то, как процессор взаимодействует с системной памятью, накопителями, дисплеем и клавиатурой). Таким образом, микропроцессор включается и сразу же попадает в BIOS, выполняет оттуда команды, которые и делают все то, что делает компьютер после включения или перезагрузки. Это наталкивает на мысль, что для «мягкой» перезагрузки надо начать выполнять команды оттуда, откуда их начинает выполнять сам микропроцессор. Но как это сделать? Это тоже просто, ведь разработчики микропроцессора сделали нам команды перехода (глава «Переходы и циклы»). Они заставляют микропроцессор выполнять команду, которая лежит по нужному нам адресу (типа команды goto в Бейсике, Паскале или Си). Благодаря ним можно запускать программы на компьютере и переключаться между приложениями в Windows. Чтобы перезагрузить компьютер понадобилась программа всего из одной команды — переход туда, где лежит первая программа микропроцессора. Именно эту программу Вы только что у себя запустили.

Единственная команда в вашей программе — jmp dword ptr reboot.

Она говорит микропроцессору: прыгни (перейди) по адресу, который находится в переменной reboot. Еще ниже начинается сама переменная reboot.

Директива dd означает, что переменная занимает 4 байта; если нужна переменная величиной один байт, то пишут db, если два — то dw (глава «Представление данных»). В языке ассемблера нет таких типов данных как “целое число”, “символ” и т.д. — все в байтах. Для целого числа надо два байта, для символа – один. В нашей программе требуется 4 байта, чтобы записать адрес перехода для команды jmp. Число 0FFFF0000h это значение адреса куда мы прыгаем. Именно по этому адресу микропроцессор считывает первую команду после включения. Вообще в программах на языке ассемблера большинство чисел пишут в шестнадцатеричном коде, об этом говорит буква h после числа (hexadecimal — шестнадцатеричный) (глава «Представление данных»).

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

1. Что такое программная привязка?

2. Каков максимальный размер COM–файла?

3. Какие сегменты можно определить в программе, которая будет преобразована в COM–файл?

4. Исходные коды находятся в файле с именем EXAMPLE.ASM Напишите команды для создания COM–файла с этим же 5. Что конкретно подразумевает директива END: а) завершение сегмента, б) завершение программы, в) завершение сегмента.

6. Объясните назначение каждого из следующих файлов:

а)file.ASM, б)file.BAK, в)file.INC, г)file.OBJ, д)file.EXE.

7. Укажите различия в назначениях END и RET.

Глава 5. Основные правила написания программ на языке ассемблер Данные правила относятся не только к программированию на языке ассемблер, но и к программированию на других языках. Может быть, их трудно понять, не имея навыка в программировании, но «незнание основ не освобождает от ответственности».

Начните с написания инструкции для пользователя — для чего создается и каковы возможности вашей программы. А теперь немного усложните вашу инструкцию по применению вашей программы, подразумевая под «пользователем» программиста, использующего написанный вами код — зачастую этим программистом-исследователем будете Вы сами.

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

Итак, комментарии для вашей программы уже готовы. Теперь возьмите ваше описание по использованию и добавьте вслед за каждым абзацем блоки кода, реализующие функции, описанные в этом абзаце. Оправдание: «У меня не было времени, чтобы добавить комментарии» на самом деле означает — «Я писал этот код без проекта системы и у меня нет времени воспроизвести его». Если создатель программы не может воспроизвести идеи воплощенные в программный проект, то кто же тогда сможет?

Все писатели — это читатели. Вы учитесь, когда смотрите, что делают другие писатели. Я настоятельно рекомендую, чтобы, как минимум, члены группы программирования читали код друг у друга. Читатель может найти ошибки, которые Вы не увидели, и подать мысль, как улучшить код.

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

5.3. Разлагайте сложные проблемы на задачи меньшего раздела На самом деле это также и правило литературного стиля. Если очень трудно объяснить точку зрения за один раз, то разбейте изложение на меньшие части и по очереди объясняйте каждую. То же самое назначение у глав в книге и параграфов в главе.

Некоторые программисты считают одним из недостатков языка ассемблера большее, по сравнению с языками высокого уровня, количество команд, но по-моему это одно из достоинств языка ассемблер.

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

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

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

Такая оптимизация достигается в три этапа:

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

• Подстройка программы под конкретное оборудование;

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

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

Каждая единица информации хранимая в ячейках памяти компьютера имеет свой адрес. На практике заранее неизвестно, в каких конкретно ячейках памяти во время работы программы будут записаны ее данные, поэтому в языках программирования введено понятие переменной, позволяющее отвлечься от конкретных адресов и обращаться к содержимому памяти с помощью идентификатора или имени. Имена указывают на значение, о реальном адресе и способе хранения которого можно забыть. В процессе работы содержимое соответствующих ячеек можно менять, обращаясь к переменной по имени. Кроме имени и значения, переменная обычно имеет тип, определяющий, какая информация хранится в данной переменной (число, адрес и т.д.). В зависимости от объема памяти, отведенного для хранения значения переменной, оно должно укладываться в допустимый диапазон. Например, значение типа байт имеет диапазон от -127 до 255. Максимальное число 255 равно 2 8 – 1 (8 по количеству битов в байте), минимальное –127 равно 27-1 (1 бит для знака и 7 бит для значения).

Идентификаторы — последовательность из латинских букв, цифр и знаков «?», «.», «@» «_», «$». При записи идентификатора придерживаются следующих правил:

1. Длина идентификатора, может быть длинее 247 символов 2. Идентификатор не должен начинаться с цифры.

3. Точка может быть только первым символом идентификатора.

4. В идентификаторах большие и малые одноименные буквы при использовании ключа /Cp считаются неэквивалентными.

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

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

Целые числа могут быть записаны в десятичной, двоичной, восьмеричной и шестнадцатеричной системах счисления. Десятичные числа записываются как обычно, а вот при записи чисел в других системах счисления в конце числа ставится спецификатор — буква, которая указывает в какой системе счисления записано это число. В конце двоичного числа ставится буква b (binary), в конце восьмеричного — o (octal) или буква q, в конце шестнадцатеричного числа — буква h (hexadecimal), в конце десятичного числа можно поставить букву d (decimal), хотя употребление спецификатора в этом случае и не обязательно.

При записи шестнадцатеричного числа соблюдают следующие правила:

1. если число начинается с «буквенной цифры» (A-F), то в начале числа ставят ноль;

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

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

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

2. в строковых константах большие и малые одноименные буквы не отождествляются;

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

Примеры: ”внутри строки допустим вот такой символ ’ ” ’строки ”могут быть вложены” таким образом’ Слова типа can’t или don’t можно записать вот так:

1)’can’’t’,2)’can’,27h,’t’,3)”can’t” Программа на языке ассемблера это последовательность предложений, каждое из которых записывается в отдельной строке. Переносить предложение на следующую строку можно используя символ «\», записывать два предложения в одной строке нельзя. Если в предложение более 131 символа, то 132-ой и все следующие за ним символы игнорируются.

Правила расстановки пробелов в предложении:

• пробел обязателен между двумя стоящими рядом идентификаторами и/или числами;

• внутри идентификаторов и чисел пробелы не допустимы;

• там где допустим один пробел, можно ставить любое число пробелов.

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

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

1. комментарии;

2. команды;

3. директивы (приказы ассемблеру).

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

Команды управляют работой микропроцессора. Для команд транслятор с языка ассемблера всегда генерирует код машинных команд.

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

Как они должны быть расположены в памяти компьютера. Большинство директив не генерирует код машинных команд.

Комментарии не влияют на смысл программы, при трансляции ассемблер игнорирует строки комментария. Комментарием считается любая строка, начинающаяся со знака «точка с запятой». Перед знаком «точка с запятой» может быть любое количество пробелов. В комментариях можно использовать русские буквы и символы псевдографики. Предложения-комментарии используются для пояснения не одной команды, а целой группы команд, следующих за этим комментарием. Старайтесь комментировать задачу, а не инструкции ассемблера. Пустые строки используют для отделения одной части программы от другой — для наглядности. В языке ассемблера допустим и многострочный комментарий. Многострочный комментарий должен начинаться со строчки COMMENT. В качестве маркера многострочного комментария берется первый за словом COMMENT символ, отличный от пробела; этот символ начинает комментарий. Концом многострочного комментария является конец первой из последующих строк программы, в которой в любой позиции снова встретился этот же маркер. Такой вид комментария обычно используется, когда например, при отладке программы необходимо временно исключить какой-либо фрагмент программы.

Предложения-команды — символьная форма записи машинных команд. Общий синтаксис предложения-команды таков:

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

Метка может быть обработана как константа со значением, равным смещению помеченного кода или данных. Например, если вы определяете данные, используя помеченную директиву "char db 224", для того, чтобы поместить адрес начала этих данных в регистр EBX, вам нужно использовать инструкцию "mov ebx,offset char", а для того, чтобы поместить в регистр DL значение байта, на который ссылается "char", нужно использовать "mov dl,char". Последний и самый гибкий способ задания меток это использование директивы "label". Перед этой директивой должно следовать имя метки, далее, размер оператора, и далее, числовое выражение, определяющее адрес, на который данная метка должна ссылаться. Метка нужна для ссылок на команду из других мест программы, например, для перехода на команду, перед которой стоит метка.

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

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

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

регистр AH, AL, BH, BL, CH, CL, DH, DL будем обозначать r8;

регистр AX, BX, CX, DX, BP, SP, SI, DI, IP, FLAGS будем обозначать r16;

регистр EAX, EBX, ECX, EDX, EBP, ESP, ESI, EDI, EIP, EFLAGS будем обозначать r32;

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

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

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

ptr 16:16 непосредственное значение 20-разрядного адреса памяти, задаваемое прямо в команде;

ptr 16:32 непосредственное значение 48-разрядного адреса памяти, задаваемое прямо в команде;

m16:32 длинный указатель, находящийся по данному адресу в памяти;

сегментный регистр CS, DS, SS, ES, GS, FS будем обозначать sr;

8-разрядное непосредственное значение, задаваемое в команде будем обозначать imm8;

16-разрядное непосредственное значение, задаваемое в команде будем обозначать imm16;

32-разрядное непосредственное значение, задаваемое в команде будем обозначать imm32;

8-разрядный адрес в пространстве ввода/вывода будем обозначать port8.

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

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

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

Основное отличие команды от директивы:

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

директива (псевдооператор, псевдокоманда) управляет работой компилятора и не генерирует машинный код основное различие между языками ассемблер (tasm, masm, fasm и т.д.) это разный синтаксис директив.

Синтаксис директив: [] < название директивы> Имя, указываемое в начале директивы — это имя константы или переменной, описываемой данной директивой. Название директив — это служебное слово.

Директивы определения данных необходимы для описания типов переменных (байт, слово, двойное слово и т.д.) с которыми работает программа.

По директиве DB (define byte, определить байт) определяются данные размером в байт.

Синтаксис директивы:

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

Существует следующие способы задания операндов директивы DB:

1) ? (знак неопределенного значения);

2) константное выражение со значением от –127 до 255.

По этой директиве описывается переменная X. Для нее отводится один байт в памяти, в который ничего не записывается. В этом случае говорят, что переменная не получила никакого значения. Выделив байт под переменную, ассемблер запоминает ее адрес. Когда ассемблер снова встретит в тексте программы имя этой переменной, то он заменит имя на данный адрес.

Адрес ячейки, выделенной переменной с именем X, принято называть значением имени X. По описанию переменной ассемблер запоминает, сколько байт занимает переменная в памяти. Этот размер называется типом переменной. Значение (адрес) и тип (размер) имени переменной однозначно определяют ячейку памяти, обозначаемую этим именем.

6.2.3.1.1.2. Операнд — константное выражение со значением Для описания переменной размером в байт с начальным значением в виде числа величиной от –127 до 255. Максимальное число 255 равно 2 8 – (8 по количеству битов в байте) По каждой из этих директив ассемблер отводит один байт под переменную и записывает в этот байт число. К началу выполнения программы переменная A будет иметь значение 254, переменная B – значение –2, переменная C – значение 17h, а переменная D -10011110b. В качестве значения переменной может быть указан символ. В качестве символа можно указать как его код (в кодировке ASCII) либо указать сам символ в кавычках.

6.2.3.1.1.3. Директива с несколькими операндами Для описания переменной-массива с некоторыми начальными значениями, применяется директива DB с несколькими операндами.

В массивах имя дается только его первому элементу, а остальные остаются безымянными. Если в массиве много элементов, то такой способ описания массива слишком громоздок. Поэтому допускается также и упрощенная форма записи: M DB 2,-2,?,’*’ По директиве DB с несколькими операндами ассемблер выделяет в памяти соседние байты памяти, по одному на каждый операнд, и записывает в эти байты значения операндов (для операнда ? ничего не записывается) Если в директиве несколько соседних операндов символы, то их можно объединить в одну строку. Два следующих примера эквивалентны:

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

6.2.3.1.1.5. Операнд – конструкция повторения DUP Довольно часто в директиве приходится указывать одинаковые операнды. Например, при описании байтового массива R из 8 элементов, где каждый элемент проинициализирован 0 можно записать так:

А можно записать короче:

В этой директиве в качестве операнда использована конструкция повторения, в которой сначала указывается коэффициент повторения, затем служебное слово DUP (duplicate «копировать»), а за ним в круглых скобках — повторяемая величина.

В общем случае эта конструкция имеет следующий вид:

где k - константное выражение с положительным значением, n1, pi -любой допустимый операнд директивы DB (в частности, это может быть снова конструкция повторения):

Например, директивы слева эквивалентны директивам справа:

X DB 2 DUP (’ab’, ?, 1) X DB ’ab’,?,1,’ab’,?, Y DB -7,3DUP(0,2DUP(?)) Y DB -7,0,?,?,0,?,?,0,?,?

Вложенность конструкций DUP используют для описания многомерных массивов. Директива A DB 200 DUP (300 DUP (?)) отводит в памяти место под байтовую матрицу A размера 200x300, в которой элементы расположены в памяти следующим образом: первые байтов это элементы первой строки матрицы, следующие 300 байтов элементы второй строки и т.д. (А слабо Вам написать 60 тысяч раз директиву ‘DB ?’) Директивой DW (define word, определить слово) описываются переменные размером в слово. Она аналогична директиве DB, поэтому вкратце рассмотрим допустимые виды ее операндов.

По этой директиве описывается переменная X. Для нее отводится одно слово в памяти, в которое ничего не записывается, т.е. эта переменная не получает начального значения.

6.2.3.1.2.2. Константное выражение со значением от –32768 до Для описания переменной размером в слово с начальным значением в виде числа величиной от -32768 до 65535. Максимальное число равно 216 – 1 (16 по количеству битов составляющих слово):

По каждой из этих директив ассемблер отводит одно слово под переменную и записывает в это слово указанное число, которое становятся начальным значением этой переменной. Как и в случае директивы DB, неотрицательные числа записываются в память как числа без знака, а отрицательные числа в дополнительном коде. Поэтому числа, которые могут быть заданы как операнды директивы DW, должны принадлежать отрезку [–215, 216 – 1].

В памяти компьютера числа размером в слово хранятся в «перевернутом» виде, поэтому по нашим двум директивам память заполнится следующим образом:

Частный случай директивы DW строка из одного или двух символов, например:

Если указана строка из двух символов, тогда ассемблер берет коды указанных символов (код ASCII для ‘0’ равен 30h, для ‘1’ — 31h) и образует из них число-слово (3031h), которое и считается начальным значением описываемой переменной S1. Но, как и любое число размером в слово, данное значение будет записано в память в «перевернутом» виде. Если же в правой части директивы DW указан один символ, тогда к нему слева ассемблер приписывает символ с кодом 0 и далее работает с этим символом как с двухсимвольной строкой. Поэтому по нашим двум директивам память будет заполнена следующим образом:

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

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

В этом случае ассемблер запишет в слово, выделенное под переменную D, адрес переменной C, который становится начальным значением переменной D.

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

Директивой DD (define double word, определить двойное слово) описываются переменные, под которые отводятся двойные слова. В остальном эта директива похожа на две предыдущие.

По этой директиве описывается переменная X. Для нее отводится двойное слово в памяти, в которое ничего не записывается, т.е. эта переменная не получает начального значения.

6.2.3.1.3.2. Константное выражение со значением от –231 до 232- Для описания переменной размером в двойное слово с начальным значением в виде числа величиной от приблизительно – 2 миллиардов (если быть точным 2.147.483.647) до приблизительно 4 миллиардов (4.294.967.294). Максимальное число 4.294.967.294 равно 232 – 1 (32 по количеству битов составляющих двойное слово):

Такой операнд задает абсолютный адрес.

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

6.2.3.1.4. Дополнительные директивы определения данных • директивы DF и DP резервируют в памяти 6 последовательно расположенных байтов;

• директива DQ резервирует в памяти 8 байтов;

• директива DT резервирует в памяти 10 байтов.

Вещественные числа могут использоваться только с директивами DD, DQ и DT. Для записи вещественного числа используется любая комбинация десятичных чисел. Цифры, которые стоят перед десятичной точкой представляют целую часть, стоящие послеточки — дробную часть числа. Цифры стоящие после экспоненциального символа e, представляют степень.

Если степень задана, то знак ее показателя определяется стоящими перед ней знаками + или -.

получаем число 42C1C000h. В кодированном вещественном 32-битовом числе: 1 бит отведен под поле знака, под поле порядка отводится 8 бит, мантисса занимает 23 бита. Расписываем 42C1C000h побитно:

01000010.11000001.11000000.00000000 = первый бит — знак “+”;

(1)1000001.11000000.00000000 — нормализованная мантисса без первой 6.2.3.2. Директивы эквивалентности и присваивания Допустим Вы пишете на языке ассемблера компьютерную игрушку.

Через какое-то время Вам понадобилось изменить правила игры и повысить или понизить порог очков (100), после превышения которого партия считается оконченной. Число 100 упоминается несколько раз в разных местах Вашего файла, и постоянно менять все операторы довольно хлопотно.

Замену нельзя выполнить автоматической командой текстового редактора «найти и заменить», так как число 100 может встречаться в разных местах программы и обозначать не только предел набранных очков. Поэтому лучше всего описать число 100 как константу и в дальнейшем обращаться к ней по имени. В языке ассемблера используют константы, которые подобно переменным имеют имена. Единственное их отличие от переменных заключается в том, что им нельзя присвоить новое значение во время выполнения программы. Имя константы может быть более выразительным и в ряде случаев более коротким, чем ее значение. При многократном использовании такой константы в программе экономится время набора текста программы. Изменение значения именованной константы связано с изменением только одного оператора, тогда как в случае использовании числовых значений этой константы такое исправление пришлось бы делать многократно.

Константы в языке ассемблера описывают с помощью директивы EQU (equal, «равно»).

Синтаксис директивы: EQU Обязательно должны быть указаны имя и операнд, причем только один.

Директивой EQU автор программы заявляет, что указанному операнду он дает указанное имя, и требует, чтобы все вхождения данного имени в текст программы ассемблер заменял на этот операнд. Например, если есть директива STAR EQU ‘*’ то ассемблер будет рассматривать предложение N DB STAR как предложение N DB ‘*’ другими словами STAR и ‘*’ это одно и то же. Директива EQU носит чисто информационный характер и по нему ассемблер ничего не записывает в конечную программу. Поэтому директиву EQU можно ставить в любое место программы Если в правой части директивы указано имя регистра, переменной, константы и тому подобное, тогда имя слева объявляется синонимом данного имени и все последующие вхождения в текст программы этого имени-синонима ассемблер будет заменять на имя, указанное справа.

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

6.2.3.2.1.2. Операнд — константное выражение Если в правой части директивы EQU стоит константное выражение, тогда указанное слева имя принято называть именем константы. Значением этой константы объявляется значение выражения. N это константа со значением 100, K — со значением 199, P — со значением 41h (это код буквы ‘A’ в системе ASCII). Все последующие вхождения в текст программы имени константы ассемблер будет заменять на значение этой константы. Например, директива X DB N DUP(?) Случаи, когда полезно применение констант, такие же, как в языках высокого уровня. Например, в качестве констант рекомендуется описывать размеры массивов, поскольку в таком случае легко настроить программу на работу с массивом любого другого размера — для этого достаточно внести изменение лишь в директиву EQU, описывающую константу. Если в константном выражении используются имена других констант, то они (эти константы) должны быть описаны раньше данной директивы EQU, иначе ассемблер, просматривающий текст программы сверху вниз, не сможет вычислить значение этого выражения.

WP EQU WORD PTR

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

ANS DB S,’!’ ANS DB ’Вы ошиблись!’ INC WP [BX] INC WORD PTR [BX] Такой вариант директивы EQU обычно используется для того, чтобы ввести более короткие обозначения для часто встречающихся длинных текстов. Текст, указанный в правой части директивы EQU, должен быть сбалансирован по скобкам и кавычкам и не должен содержать вне скобок и кавычек символа «;». Поскольку текст не вычисляется, то в нем можно использовать как имена, описанные до этой директивы EQU, так и имена, описанные после нее.

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

Пример: K= Подобного рода константы используют ради «экономии имен»: если в разных частях программы используются разные константы и области использования этих констант не пересекаются, тогда, чтобы не придумывать новые имена, этим константам можно дать одно и тоже имя.

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

• Арифметические операторы: одноместные (унарные) «+» и «-» (знак числа), двуместные (бинарные) «+» и «-» (операторы сложения и вычитания), оператор умножения «*», целочисленного деления «/», получения остатка от деления «MOD».

;вычисляется число элементов массива и заносится в CX MOV CX,TAB_SIZE/SIZE_EL ;оператор «/»

Операторы сдвига SHL, SHR выполняют сдвиг выражения на указанное количество разрядов.

Пример: MASK_B EQU 10111011B • Операторы сравнения EQ, NE, LT, LE, GT, GE (возвращают значение «истина» или «ложь») предназначены для формирования логических выражений.

Пример:

MOV AL,TAB_SIZE GE 50 ;сравнение размера таблицы с ;и загрузка в AL в случае меньшего значения • Логические операторы NOT AND OR, XOR выполняют над выражениями побитовые операции.

Пример:

FLAGS EQU 10010011B MOV AL,FLAGS XOR 01B ;AL=10010010 b; пересылка в AL ;поля FLAGS с инвертированным правым битом • Индексный оператор [ ]. Транслятор воспринимает квадратные скобки как указание сложить значение перед скобками с выражением, находящимся внутри скобок.

Пример:

MOV AX,MAS[SI] ;пересылка слова по адресу MAS+[SI] в • Оператор переопределения типа PTR применяется для временного переопределения или уточнения типа метки или переменной, определяемой выражением. Тип может принимать одно из следующих значений:

BYTE, WORD, DWORD, QWORD, TBYTE, NEAR, FAR.

• Оператор переопределения сегмента «:» (двоеточие) заставляет вычислять физический адрес относительно конкретно задаваемой сегментной составляющей: «имя сегментного регистра», «имя сегмента» из соответствующей директивы SEGMENT или «имя группы».

• Оператор именования типа структуры «.» (точка).

• Оператор получения сегментной составляющей адреса выражения SEG возвращает физический адрес сегмента для выражения, в качестве которого могут выступать метка, переменная, имя сегмента, имя группы или некоторое символическое имя.

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

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

В таблице 9 указаны операторы ассемблера в порядке убывания Значениями константных выражений всегда являются 32-битовые целые числа (исключениями являются директивы DQ, DF, DP, DT, которыми можно явно указывать 32-битовые и более числа).

К простейшим константным выражениям относятся:

• числа от –2 до 2 -1;

• символ (значением такого выражения является код символа);

строка из двух символов (значением является слово-число составленное из кодов этих символов);

имя константы (значением такого выражения является значением константы).

К константным выражениям применимы следующие арифметические операторы (k, k1 и k2 означают любые константные выражения):

• одноместные плюс и минус +k, -k;

• операторы сложения и вычитания k1+k2, k1-k2;

• оператор умножения k1*k2, целочисленного деления k1/k2, получения остатка от деления k1 MOD k2.

Пример: K EQU Операндами арифметических операторов должны быть константные выражения. Язык ассемблер разрешает вычитать один адрес из другого, в результате Вы получите число, а не адрес.

Вычитание адресов используется обычно для определения расстояния (числа байтов) между этими адресами. Результатом действия арифметических операторов на константные выражения будет 32-битное число.

Например: 2*80000000h=100000000h 0 а не 100000000h Значениями адресных выражений являются 16-битовые адреса.

К простейшим адресным выражениям относятся:

• метка (имя команды) и имя переменной, описанное в директиве DB, DW или DD (значениями таких выражений являются адреса меток и имен);

• счетчик размещения; он записывается как $ и обозначает адрес того предложения, в котором он встретился. В разных предложениях $ обозначает разные адреса. Например, если адрес переменной A равен 100h, то имеем:

Чаще всего счетчик размещения используется для вычисления размера памяти занимаемой каким-то массивом, Пример: X DW 40 DUP(?) Здесь $ обозначает адрес первого байта за массивом X, из этого адреса и вычитается начальный адрес массива.

1. Какие из следующих имен неправильны: а)PC_AT, б)$50, в)@$_Z, г)34B7, д)AX.

2. Какова длина в байтах для элементов данных, определенных директивами: а) DW, б) DD, в) DT, г) DB, д) DQ.

3. Определите символьную строку по имени TITLE1 содержащую константу RGB Electronics.

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

5. Определите следующие числовые значения в элементах данных от FLDA до FLDE: а) четырехбайтового элемента, содержащего шестнадцатеричный эквивалент десятичного числа 115, б) однобайтового элемента, содержащего шестнадцатеричный эквивалент десятичного числа 25, в) двухбайтового элемента, содержащего неопределенное значение, г) однобайтового элемента, содержащего двоичный эквивалент десятичного числа 25, д) директивы DW, содержащей последовательные значения 16, 19, 20, 27, 30.

6. В чем разница между DB ‘26’ и DB 26.

7. Определите ассемблерный шестнадцатеричный объектный код для: а) DB –26, б) DW 2645h, в) DD 25733Ah, г) DQ 25733Ah.

8. Представьте следующие символьные цепочки в коде ASCII (пользуясь шестнадцатеричными кодами): а) SAM JONES; б) – 75.61; в) Hello, how are you?

Среди команд микропроцессора i80x86 достаточно много команд пересылки, здесь мы рассмотрим следующие MOV, XCHG и BSWAP. Кроме того, рассмотрим оператор PTR.

Команда пересылки байта, слова или двойного слова. Пересылаемая величина берется из команды, регистра или ячейки памяти, а записывается в регистр или ячейку памяти. Таких команд много, но в языке ассемблера все они записываются одинаково: MOV,< операнд2> Алгоритм работы: копирование второго операнда в первый операнд.

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

• направление пересылки в команде MOV всегда справа налево, то есть из второго операнда в первый;

• значение второго операнда не изменяется;

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

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

желательно использовать в качестве одного из операндов регистр AL/AX/EAX, так как в этом случае транслятор генерирует более короткую форму команды MOV.

Примеры:

MOV AL,5;непосредственная запись байта в регистр MOV BL,AL;пересылка байта из регистра в регистр MOV Omega,CX ;пересылка слова из регистра в ячейку MOV EAX,0FFFFFFFFh ;непосредственная запись MOV BX,DS ;пересылка байта из сегментного регистра Команда MOV применяется для обмена данными между системными регистрами. Это одна из немногих возможностей доступа к содержимому этих регистров. Данную команду можно использовать только на нулевом уровне привилегий либо в реальном режиме работы микропроцессора.

;переключение микропроцессора в защищенный режим OR EAX,1 ;помещает в нулевой бит EAX Если необходимо переслать в регистр адрес какой-то переменной, тогда Вам придется использовать в команде MOV оператор OFFSET (оператор получения смещения выражения). OFFSET позволяет получить значение смещения выражения в байтах относительно начала того сегмента, в котором выражение определено. А если эта переменная еще и находится в другом сегменте тогда в паре с оператором OFFSET Вам придется использовать оператор SEG (оператор получения сегментной составляющей адреса выражения). Оператор SEG возвращает физический адрес сегмента для выражения, в качестве которого могут выступать метка, переменная, имя сегмента, имя группы или некоторое символическое имя.

Например, если в сегменте данных содержится POLE, то следующие команды пересылают в пару ES:DX полный адрес этой переменной:

MOV AX,SEG POLE

MOV DX,OFFSET POLE

MOV EAX,44332211h LEA EAX,[44332211h] immediate to register (alternate encoding) 1011 w reg: immediate data register to segment register 1000 1110:11sreg3 reg memory to segment register 1000 1110:mod sreg3 r/m segment register to register 1000 1100:11 sreg3 reg segment register to memory 1000 1100:mod sreg3 r/m (Загрузка эффективного адреса = “Load Effective Address”) Синтаксис команды: LEA, LEA,[+*+] где 1,2,4 или Семантика команды: получить в регистр операнд1 эффективный адрес (смещение) операнда2.

Алгоритм работы: алгоритм работы команды зависит от действующего режима адресации (use 16 или use 32):

• если use 16, то в регистр операнд1 загружается 16-битное значение смещения операнда2;

• если use 32, то в регистр опреранд1 загружается 32-битное значение смещения операнда2.

Применение:

При прямой адресации данная команда является альтернативой команде MOV с оператором OFFSET. Но позволяет реализовать косвенно-базово-индексную адресацию операндов».

;загрузить в регистр BX адрес пятого элемента массива MAS DB 10 DUP (0) MOV DI, LEA BX,MAS[DI] ;или LEA BX,MAS[4] или LEA BX,MAS+ Хотя никто не может Вам помешать написать эквивалентную команду MOV BX,OFFSET MAS[DI], и даже наоборот, при попытке использовать команды типа LEA BX,MAS[4] или LEA BX,MAS+4 при трансляции программы произойдет замена команды LEA на команду MOV с оператором OFFSET, как на более быструю и более короткую команду, поэтому, хотя команда LEA и относится к группе команд по загрузке адресов, мы рассматриваем ее вместе с командами пересылки.

mov ebx, offset adr BBF9004000 mov ebx,0004000F9h lea ebx, adr 8D1DF9004000 lea ebx,[004000F9h] 0108h — адрес переменной adr Использование команды lea Для умножения на 2 lea eax,[eax+eax] или lea eax,[eax*2] LEA В программах на языке ассемблера приходится довольно часто переставлять местами какие-то две величины, и хотя такую перестановку можно организовать с помощью двух команд MOV с сохранением значения в промежуточной ячейке памяти, в процессор введена специальная команда для этого.

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

Алгоритм работы: обмен содержимым операнда1 и операнда2.

Применение:

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



Pages:     | 1 || 3 | 4 |   ...   | 5 |


Похожие работы:

«Вестник МГТУ, том 13, №4/2, 2010 г. стр.857-860 УДК 378 : 629.5.072.8 О некоторых проблемах подготовки инженеров-судоводителей Б.А. Вульфович Судоводительский факультет МА МГТУ, кафедра судовождения Аннотация. Статья посвящена некоторым актуальным проблемам образовательного процесса в МГТУ. В их числе: отсутствие объективных методов контроля и самоконтроля качества занятий преподавателей; плохая посещаемость занятий, недостаток производственной практики, отсутствие системы обмена опытом и...»

«ЦЕНТР ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ САМАРСКОЙ ОБЛАСТИ Основные требования к оформлению методической продукции МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ Самара 2013 Основные требования к оформлению методической продукции [Текст] : Методические рекомендации – Самара : ЦПО, 2013. – 25 с. Со ставитель: Пасечникова Т.В., методист ЦПО Самарской области Редакто р: Елькина С.В., заместитель директора ЦПО Самарской области Рецензент: Ефимова С.А., к.п.н., директор ЦПО Самарской области Методические рекомендации...»

«МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РФ ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ БЮДЖЕТНОЕ УЧРЕЖДЕНИЕ ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ ВОРОНЕЖСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ МЕТОДИЧЕСКИЕ РЕКОМЕНДАЦИИ К ПРОВЕДЕНИЮ УЧЕБНОЙ ФАРМАЦЕВТИЧЕСКОЙ ПРОПЕДЕВТИЧЕСКОЙ ПРАКТИКИ Составители: Е.Е. Чупандина, С.А. Каракозова, И.В. Ручкин А.А. Черникова Издательско-полиграфический центр Воронежского государственного университета 2012 Утверждено решением Научно-методическим советом фармацевтического факультета от 24.01.2012...»

«1 Федеральное агентство по образованию ГОУВОП Удмуртский государственный университет Институт экономики и управления Кафедра региональной и муниципальной экономики МЕТОДИЧЕСКИЕ УКАЗАНИЯ по выполнению курсовой работы по дисциплине Управление инфраструктурой организации для студентов специальности 080502 “Экономика и управление на предприятии(городское хозяйство) всех форм обучения Ижевск 2005 2 Методические указания разработаны доцентом кафедры региональной и муниципальной экономики А.В....»

«В серии: Библиотека ALT Linux Георгий Курячий Кирилл Маслинский Операционная система Linux Курс лекций. Учебное пособие Москва, 2010 УДК ББК Операционная система Linux: Курс лекций. Учебное пособие / Г. В.Курячий, К. А. Маслинский М. : ALT Linux; Издательство ДМК Пресс, 2010. 348 с. : ил. ; 2-е изд., исправленное. (Библиотека ALT Linux). ISBN В курсе даются основные понятия операционной системы Linux и важнейшие навыки работы в ней. Изложение сопровождается большим количеством практических...»

«Федеральное агентство по образованию Государственное образовательное учреждение высшего профессионального образования ГОРНО-АЛТАЙСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ Кафедра геоэкологии и природопользования ЭКОЛОГИЧЕСКАЯ ЭТИКА Учебно-методический комплекс Для студентов, обучающихся по специальности 020802 Природопользование Горно-Алтайск РИО Горно-Алтайского госуниверситета 2007 Печатается по решению методического совета Горно-Алтайского госуниверситета ББК – 20.1 Э 40 Экологическая этика:...»

«МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ ФЕДЕРАЛЬНОЕ АГЕНТСТВО ПО ОБРАЗОВАНИЮ Государственное образовательное учреждение высшего профессионального образования ГОРНО-АЛТАЙСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ Географический факультет Кафедра физической географии СОГЛАСОВАНО УТВЕРЖДАЮ Декан ГФ Проректор по УР А.В. Бондаренко _Е.Е. Шваков _2009 г. 2009 г. УЧЕБНО-МЕТОДИЧЕСКИЙ КОМПЛЕКС ПО ДИСЦИПЛИНЕ Палеогеография Для студентов, обучающихся по специальностям 020401 География (очное...»

«Формирование культуры БЖ населения Общими мероприятиями по совершенствованию формирования КБЖ являются: подготовка и внесение изменений в федеральные законы О гражданской обороне, О защите населения и территорий от чрезвычайных ситуаций природного и техногенного характера О пожарной безопасности, другие нормативные правовые акты — в части, касающейся необходимости реализации в качестве важнейшего способа защиты — формирование культуры безопасности жизнедеятельности: развитие подзаконных...»

«Т. Л. Смирнова Размещение производительных сил в России Учебное пособие Северск 2011 МИНИСТЕРСТВО ОБРАЗОВАНИЯ И НАУКИ РОССИЙСКОЙ ФЕДЕРАЦИИ Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования Национальный исследовательский ядерный университет М И Ф И Северский технологический институт - филиал НИЯУ МИФИ (СТИ Н И Я У М И Ф И ) T.JI. Смирнова РАЗМЕЩЕНИЕ ПРОИЗВОДИТЕЛЬНЫХ СИЛ В РОССИИ Допущено У МО по образованию в области производственного...»

«Тема ГБ 24–11/1 АКТУАЛИЗАЦИЯ МЕТОДИКИ ПРЕПОДАВАНИЯ ХИМИКО-АНАЛИТИЧЕСКИХ ДИСЦИПЛИН В ТЕХНОЛОГИЧЕСКОМ ВУЗЕ Промежуточный отчёт за 2012 год: Разработка системы контроля усвоения учебного материала и диагностики сформированных знаний с использованием информационных технологий РЕФЕРАТ Отчет 61с., 7 рис., 14 табл., 22 источников. АНАЛИТИЧЕСКАЯ ХИМИЯ, ФИЗИКО-ХИМИЧЕСКИЕ МЕТОДЫ АНАЛИЗА, ПРЕПОДАВАНИЕ, КОМПЬЮТЕРНОЕ ТЕСТИРОВАНИЕ Объектом исследования является – разработка системы контроля усвоения учебного...»

«1.Цели и задачи дисциплины ее место в учебном процессе. Целью дисциплины является изучение теоретических основ технологии лесозаготовительного производства и получение практических навыков в области управления на предприятиях лесного комплекса. Основными задачами дисциплины являются: теоретическая подготовка в области управления на предприятиях лесопромышленного производства; изучение технологии машин и механизмов, применяемых на лесосечных и лесоскладских работах; изучение вопросов связанных с...»

«СПИСОК научных и научно-методических трудов Хроленко Александра Тимофеевича 1. Хроленко, А.Т. К вопросу о паратаксисе в русском языке (статья) // Известия ВГПИ. Воронеж, 1966. – Т. 53. – С. 202-209. 2. Хроленко, А.Т. К вопросу об использовании паратактических конструкций в русской народной лирической песне (статья) // Известия ВГПИ. Воронеж, 1968. – Т. 81. – С. 42-54. 3. Хроленко, А.Т. Один из типов паратактических конструкций в русской народной лирической песне (статья) // Известия ВГПИ....»

«Министерство образования и науки Российской Федерации Южно-Уральский государственный университет Юридический факультет Кафедра трудового и социального права Х93.я7 С138 МЕЖДУНАРОДНОЕ ПРАВОВОЕ СОТРУДНИЧЕСТВО В СФЕРЕ ТРУДА Методические указания Челябинск Издательский центр ЮУрГУ 2011 2 ББК Х627.я7 + Х935.я7 С138 Одобрено учебно-методической комиссией юридического факультета Южно-Уральского государственного университета Рецензент: Майоров В.И., доктор юридических наук, профессор, заведующий...»

«Содержание Строительство и архитектура Строительное производство Строительные машины и механизмы Экономика и управление в строительстве Архитектура и ландшафтное строительство Общепрофессиональные дисциплины Деревообрабатывающая промышленность Нефтяная и газовая промышленность. Горное дело Химические технологии Иллюстрированные пособия Справочное издание Тематический каталог 2014 год Строительство и архитектура. Деревообрабатывающая промышленность. Нефтяная и газовая промышленность. Горное...»

«Методические материалы по порядку образования позывных сигналов для опознавания радиоэлектронных средств гражданского назначения Содержание Стр. I. Общие положения 1 II. Образование позывных сигналов РЭС радиовещательной службы 8 III. Образование позывных сигналов радиостанциям любительской и любительской спутниковой служб 8 IV. Образование позывных сигналов РЭС фиксированной службы и сухопутной подвижной службы 12 V. Особенности образования позывных сигналов РЭС фиксированной службы и...»

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

«Аннотация к рабочей программе УМК Л. В. Занкова 1 класс Система Л. В. Занкова Литературное чтение Рабочая программа по литературному чтению для 1 класса разработана на основе авторской программы В.Ю. Свиридовой, Литературное чтение, утверждённой Министерством образования и науки РФ (Сборник Программы начального общего образования. Система Л. В. Занкова. Самара: Издательский дом Федоров, 2011г.) в соответствии с требованиями федерального государственного образовательного стандарта начального...»

«SWorld – 19-30 March 2013 http://www.sworld.com.ua/index.php/ru/conference/the-content-of-conferences/archives-of-individual-conferences/march-2013 MODERN DIRECTIONS OF THEORETICAL AND APPLIED RESEARCHES ‘2013 Никонова Т.Е. Т Е Х Н ОЛ ОГ И Я ДЕ БА Т Ы Н А У РОК А Х А Н Г Л И Й С К ОГ О Я ЗЫ К А Таганрогский педагогический институт им. А.П. Чехова, Таганрог, Инициативная 48,347900 Nikonova T.E. T E C H NOL OG Y DE B A T E S A T T H E E NG L I SH L A NG UA G E L E SSONS Taganrog State Pedagogical...»

«МИНОБРНАУКИ РОССИИ Федеральное государственное бюджетное образовательное учреждение высшего профессионального образования РОССИЙСКИЙ ГОСУДАРСТВЕННЫЙ ГУМАНИТАРНЫЙ УНИВЕРСИТЕТ (РГГУ) ИНСТИТУТ ФИЛОЛОГИИ И ИСТОРИИ ИСТОРИКО-ФИЛОЛОГИЧЕСКИЙ ФАКУЛЬТЕТ Кафедра славистики и центральноевропейских исследований История и культура страны основного языка (Хорватия) Рабочая программа курса для бакалавриата по направлению 032700 – Филология Москва 2013 ИСТОРИЯ И КУЛЬТУРА СТРАНЫ ОСНОВНОГО ЯЗЫКА (ХОРВАТИЯ)...»

«Автономная некоммерческая организация РОССИЙСКАЯ АКАДЕМИЯ ПРЕДПРИНИМАТЕЛЬСТВА (АНО РАП) РК СМК 01 Система качества образовательного учреждения ОДОБРЕНО УТВЕРЖДАЮ Ученым советом Ректор _ Протокол №_ В.С. Балабанов _2011 г. __2011 г. МЕТОДИЧЕСКИЕ УКАЗАНИЯ ДЛЯ НАПИСАНИЯ КУРСОВЫХ РАБОТ СК-МРКР - 28-02-11 Дата введения 2011 ­ 02 ­ 28  СОГЛАСОВАНО Проректор по учебной работе _ О.А. Воробьева 2011 г.   Москва, КУРСОВАЯ РАБОТА КАК ВИД УЧЕБНОЙ И НАУЧНОЙ СТУДЕНЧЕСКОЙ РАБОТЫ Курсовые работы относятся к...»






 
2014 www.av.disus.ru - «Бесплатная электронная библиотека - Авторефераты, Диссертации, Монографии, Программы»

Материалы этого сайта размещены для ознакомления, все права принадлежат их авторам.
Если Вы не согласны с тем, что Ваш материал размещён на этом сайте, пожалуйста, напишите нам, мы в течении 1-2 рабочих дней удалим его.