- •140010, Г. Люберцы, Московской обл., Октябрьский пр-т, 403.
- •Глава 1. Архитектура реального режима
- •1.1. Память и процессор
- •Глава 1
- •Глава 1
- •1.2. Распределение адресного пространства
- •Глава 1
- •1.3. Регистры процессора
- •Глава 1
- •Глава 1
- •9 7H Шестнадцатернчное обозначение числа
- •Глава 1
- •1.4. Сегментная структура программ
- •Глава 1
- •Глава 1
- •Глава 1
- •1.5. Стек
- •Глава 1
- •1.6. Система прерываний
- •Глава 1
- •Глава I
- •1.7. Система ввода-вывода
- •Глава I
- •Глава 1
- •Глава 2. Основы программирования
- •2.1. Подготовка и отладка программы
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •2.2. Представление данных
- •Глава 2
- •Глава 2
- •2.3. Описание данных
- •Глава 2
- •Глава 2
- •2.4. Структуры и записи
- •Глава 2
- •Глава 2
- •2.5. Способы адресации
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 2
- •2.7. Вызовы подпрограмм
- •Глава 2
- •2.8. Макросредства ассемблера
- •Глава 2
- •Глава 2
- •Глава 2
- •Глава 3. Команды и алгоритмы
- •Глава 3
- •Глава 3
- •Глава 3
- •Глава 3
- •Глава 3
- •Глава 3
- •Глава 3
- •Глава 3
- •3.2. Циклы и условные переходы
- •Глава 3
- •Глава 3
- •3.3. Обработка строк
- •Глава 3
- •3.4. Использование подпрограмм
- •Глава 3
- •Глава 3
- •3.5. Двоично-десятичные числа
- •Глава 3
- •Глава 3
- •3.6. Программирование аппаратных средств
- •Глава 3
- •37Ah Порт управлсш!я
- •Глава 3
- •Глава 3
- •Глава 4. Расширенные возможности
- •4.1. Архитектурные особенности
- •Глава 4
- •4.2. Дополнительные режимы адресации
- •Глава 4
- •4.3. Использование средств 32-разрядных процессоров в программировании
- •Глава 4
- •Глава 4
- •Глава 4
- •4.4. Основы защищенного режима
- •Глава 4
- •Глава 4
- •Глава 4
- •Глава 4
- •Idiv Деление целых чисел со знаком
- •Imul Умножение целых чисел со знаком
- •In Ввод из порта
- •Inc Инкремент (увеличение на 1)
- •Int Программное прерывание
- •Into Прерывание по переполнению
- •Iret Возврат из прерывания
- •1 Lods Загрузка операнда из строки : lodsb Загрузка байта из строки lodsw Загрузка слова из строки
- •Операнд
- •Xadd память, регистр
- •Xchg Обмен данными между операндами
- •Xlat Табличная трансляция
- •Xor Логическое исключающее или
- •Содержание
УДК 681.3.068 ББК 32.973
Автор: К-Г.Финогенов Ф59 Основы языка Ассемблера. — М.: Радио и связь, 1999. — 28S с.: ил.
ISBN 5-256-01451-Х.
Книга представляет собой учебное пособие по языку ассемблера персональных компьютеров типа IBM PC. Описаны особенности архитектуры микропроцессоров Intel и всего компьютера в целом, правила составления программ, основные конструкции языка и приемы программирования, принципы программирования подключаемой к компьютеру аппаратуры. Рассмотрены возможности использования в 16-разрядных приложениях реатьного режима средств современных 32-разрядных процессоров. Дано сжатое описание принципов защищенного режима с примером программирования. В приложении дан перечень Команд процессора Pentium с примерами и пояснениями.
Для студентов и преподавателей средних и высших учебных заведений, а тоске для всех желающих познакомиться с основами современных микропро-, цессоров и их программированием.
ББК 32.973 ISBN 681.3.068
О Финогенов К.Г., 1999
Инженерно-техническое издание
Кирилл Григорьевич ФИНОГЕНОВ
ОСНОВЫ ЯЗЫКА АССЕМБЛЕРА
Оформление серии и обложка В.Г.Ситникова. Макет подготовлен ООО ИОЦ «Силуэт»
ИБ № 2876 ЛР № 061888 от 19.12.97
Сдано в набор 19.02.99 г. Подписано в печать 22.03.99 г.
Формат 60x881/i6 Бумага газетная Гарнитура Тайме
Печать офсетная Печ. л. 18,0 Уч.-изд. л. 15,0
Тираж 5000 экзЛзд. Hs 111 Заказ 1371
Отпечатано в Производственно-издательском комбинате ВИНИТИ,
140010, Г. Люберцы, Московской обл., Октябрьский пр-т, 403.
Тел. 554-21-86
Предисловие
Книга рассчитана на пользователей персональных компьютеров типа IBM PC, которые хотели бы поближе познакомиться с архитектурными особенностями семейства микропроцессоров корпорации Intel и научиться понимать и составлять программы на языке ассемблера для этих процессоров.
Если существующие сегодня языки программирования (а их насчитывается не один десяток) условно разбить на две категории, то в одну из которых попадет язык ассемблера, а в другую — все остальные. В то время, как языки высокого уровня ориентируются на решение тех или иных прикладных задач (математических, экономических и др.) и содержат в себе средства алгоритмического описания этих задач, язык ассемблера является отражением архитектуры процессора, т.е. его логического устройства, режимов и алгоритмов функционирования. Операторы языка ассемблера представляют собой фактически команды микропроцессора, только выраженные не в виде машинных кодов, а с помощью более или менее наглядных мнемонических обозначений. Эта особенность языка ассемблера определяет его возможности и сферы использования.
Как известно, программы, написанные на языке ассемблера (если, конечно, они написаны грамотно), отличаются высокой эффективностью, т.е. минимальным объемом и максимальным быстродействием. Это обстоятельство обусловило широкое использование языка ассемблера в тех случаях, когда скорость работы программы или расходуемая ею память имеют решающее значение. Некоторые классы программ (например, программы драйверов устройств, отличающиеся жесткой структурой) требуют для своего составления обязательного использования языка ассемблера. Язык ассемблера также удобен для написания программ управления нестандартной аппаратурой, подключаемой к компьютеру с целью построения автоматизированных систем управления научными измерениями или технологическими процессами, тем более, что от таких программ часто требуется еще и максимальное быстродействие. В то же время для разработки программ математического или логического характера — по моделированию, обработке числовой или символьной информации, обслуживанию баз данных и др. лучше подходят языки высокого уровня.
Язык ассемблера является основным инструментом исследования программ, для которых нет исходных текстов. Расшифровка выполнимых (загружаемых) программ осуществляется с помощью так называемых де-ассемблеров — служебных программ, преобразующих коды выполнимой программы в текст на языке ассемблера. Естественно, работа с этим текстом предполагает достаточно хорошее знание языка, который в нем использован.
Предисловие
Предисловие
При отладке программ, написанных на языках высокого уровня типа С или C++, приходится пользоваться встроенным в систему программирования интерактивным отладчиком, всегда содержащим в себе деассем-блер. В простых случаях удается отладить программу, наблюдая ход выполнения операторов языка высокого уровня; более тонкие ошибки обнаруживаются только на уровне машинных кодов путем анализа содержимого регистров процессора и конкретных ячеек памяти. Такой метод ценен еще и тем, что позволяет войти внутрь вызываемых из прикладной программы системных средств (функций DOS или Windows) и проаншжзировать взаимодействие отлаживаемой программы с внутренними функциями операционной системы.
Кроме потребительских качеств, язык ассемблера имеет еще значительную методическую ценность. Отражая архитектурные особенности используемого в компьютере микропроцессора, а также средства взаимодействия микропроцессора с аппаратурой компьютера и подключенными к компьютеру устройствами, язык ассемблера предоставляет уникальную возможность изучения процессора и компьютера в целом, освоения того, что и как умеет делать аппаратура компьютера и каковы ее возможности и ограничения. Знакомство с внутренними возможностями компьютера чрезвычайно полезно, в частности, для программиста, работающего на языках Паскаль или Си, так как позволяет увидеть за формализмом языка высокого уровня те реальные процессы, которые будут протекать в системе при выполнении прикладной программы и, следовательно, более осознанно подойти к разработке структуры программы и ее конкретных алгоритмов.
В целом можно сказать, что знакомство с языком ассемблера необходимо для любого специалиста, которому приходится писать программы для персонального компьютера, в какой бы прикладной области он не подвизался, и на каком бы языке программирования не работал.
Язык ассемблера, как и любой другой язык программирования, имеет массу встроенных средств, позволяющих в ряде случаев ускорить и облегчить процесс программирования и повысить качество создаваемых программ. Профессиональная работа на языке ассемблера, естественно, предполагает детальное знакомство с этими средствами. Однако для широкого круга прикладных специалистов, если только они не предполагают пользоваться языком ассемблера, как основным языком программирования, нет необходимости в детальном изучении многочисленных тонкостей языка. Для того, чтобы составлять прикладные (как правило, не очень сложные в алгоритмическом плане) программы на языке ассемблера и, что еще более важно, читать и понимать уже составленные программы, достаточно иметь хорошее представление о системе команд и способах адресации и уметь пользоваться основными конструкциями языка. С другой стороны, столь же необходимо иметь ясное представление об архитектуре процессора и компьютера в целом. Всем этим вопросам и посвящена настоящая книга.
В разделе, посвященном архитектуре реального режима, рассматриваются наиболее принципиальные элементы архитектуры процессора и компьютера в целом: понятие сегментной адресации, способы адресации, предоставляемые микропроцессором, система программных и аппаратных прерываний, распределение адресного пространства и система ввода-вывода.
Раздел основ программирования посвящен методике подготовки и отладки программ на языке ассемблера, типам данных и средствам их описания, взаимодействию программ с операционной системой, а также использованию различных способов передачи управления внутри программы.
В следующем разделе описываются типы приложений DOS (программы .ЕХЕ и .СОМ, резидентные программы, обработчики прерываний) и правила их составления, даются многочисленные примеры использования наиболее важных команд, конструкций и алгоритмов языка. Отдельный параграф посвящен принципам программного управления аппаратурой, подключаемой к компьютеру.
Последний раздел книги посвящен расширенным возможностям современных 32-разрядных микропроцессоров типа Pentium и др. Здесь рассматриваются архитектурные особенности этих процессоров, возможности использования 32-разрядных операндов в прикладных программах, основные принципы и команды защищенного режима.
В приложении дается описание всех команд микропроцессоров 8086...Pentium с примерами и пояснениями.
Книга не требует от читателя серьезных знаний в области вычислительной техники или даже навыков программирования. В то же время автор надеется, что приведенный в книге материал позволит читателям получить представление о современных микропроцессорах и их работе в составе персонального компьютера, а также приобрести знания, необходимые для составления и отладки программ на языке ассемблера.
К. Г.Финогенов
Введение
Введение
Микропроцессоры корпорации Intel и персональные компьютеры на их базе прошли не очень длинный во времени, но значительный по существу путь развития, на протяжении которого кардинально изменялись их возможности и даже сами принципы их архитектуры. В то же время, внося в микропроцессор принципиальные изменения, разработчики были вынуждены постоянно иметь в виду необходимость обеспечения совместимости новых моделей со старыми, чтобы не отпугивать потенциального покупателя перспективой полной замены освоенного или разработанного им программного обеспечения. В результате современные микропроцессоры типа Pentium, обеспечивая такие возможности, как 32-битную адресацию почти неограниченных объемов памяти, многозадачный режим с одновременным выполнением нескольких программ, аппаратные средства защиты операционной системы и прикладных программ друг от друга, богатый набор дополнительных эффективных команд и способов адресации, в то же время могут работать (и часто работают) в режиме первых микропроцессоров типа 8086, используя всего лишь 1 мегабайт оперативной памяти, 16-разрядные операнды (т. е. числа в диапазоне до 216-1=65535) и ограниченный состав команд. Поскольку программирование на языке ассемблера напрямую затрагивает аппаратные возможности микропроцессора, прежде всего следует выяснить, в какой степени программист может использовать новые возможности микропроцессоров в своих программах и какие проблемы программной несовместимости могут при этом возникнуть.
Первые персональные компьютеры корпорации IBM, появившиеся в 1981 г. и получившие название IBM PC, использовали в качестве центрального вычислительного узла 16-разрядный микропроцессор с 8-разрядной внешней шиной Intel 8088. В дальнейшем в персональных компьютерах стал использоваться и другой вариант микропроцессора, 8086, который отличался от 8088 тем, что являлся полностью 16-разрядным. С тех пор его имя стало нарицательным, и в программах, использующих только возможности процессоров 8088 или 8086, говорят, что они работают в режиме 86-го процессора.
В 1983 г. корпорацией Intel был предложен микропроцессор 80286, в котором был реализован принципиально новый режим работы, получивший название защищенного. Однако процессор 80286 мог работать и в режиме 86-го процессора, который стали называть реальным.
В дальнейшем на смену процессору 80286 пришли модели 80386, i486 и, наконец, различные варианты процессора Pentium. Все они могут работать и в реальном, и в защищенном режимах. Хотя каждая следующая
Введение \ 7
модель была значительно совершеннее предыдущей (в частности, почти на два порядка возросла скорость работы процессора, начиная с модели 80386 процессор стал 32-разрядным, а в процессорах Pentium реализован даже 64-разрядный обмен данными с системной шиной), однако с точки зрения программиста все эти процессоры весьма схожи. Основным их качеством является наличие двух режимов работы — реального и защищенного. Строго говоря, в современных процессорах реализован еще и третий режим — виртуального 86-го процессора, или V86, однако в плане использования языка ассемблера этот режим не отличается от обычного режима 86-го процессора, и в этой книге мы его касаться не будем.
Реальный и защищенный режимы прежде всего принципиально различаются способом обращения к оперативной памяти компьютера. Метод адресации памяти, используемый в реальном режиме, позволяет адресовать память лишь в пределах 1 Мбайт; в защищенном режиме используется другой механизм (из-за чего, в частности, эти режимы и оказались полностью несовместимыми), позволяющий обращаться к памяти объемом до 4 Гбайт. Другое важное отличие защищенного режима заключается в аппаратной поддержке многозадачности с аппаратной же (т.е. реализованной в самом микропроцессоре) защитой задач друг от друга.
Реальный и защищенный режимы имеют прямое отношение к работе операционной системы, установленной на компьютере.
В настоящее время на персональных компьютерах типа IBM PC используются в основном два класса операционных систем (оба — разработки корпорации Microsoft): однозадачная текстовая система MS-DOS и многозадачная графическая система Windows. Операционная система MS-DOS является системой реального режима; другими словами, она использует только средства процессора 8086, даже если она установлена на компьютере с процессором Pentium. Система Windows — это система защищенного режима; она значительно более полно использует возможности современных процессоров, в частности, многозадачность и расширенное адресное пространство. Разумеется, система Windows не могла бы работать с процессором 8086, так как в нем не был реализован защищенный режим.
Соответственно двум типам операционных систем, и все программное обеспечение персональных компьютеров подразделяется на два класса: программы, предназначенные для работы под управлением MS-DOS (их часто называют приложениями DOS) и программы, предназначенные для системы Windows (приложения Windows). Естественно, приложения DOS могут работать только в реальном режиме, а приложения Windows — только в защищенном.
Таким образом, выражения «программирование в системе MS-DOS», «программирование в реальном режиме» и «программирование 86-го про-цесвора» фактически являются синонимами. При этом следует подчеркнуть, что хотя процессор 8086, как микросхема, уже давно не используется, его архитектура и система команд целиком вошли в современные процессоры. Лишь относительно небольшое число команд современных
8
Введение
процессоров специально предназначены для организации защищенного режима и распознаются процессором, только когда он работает в защищенном режиме. Поэтому изучение языка ассемблера целесообразно начинать с изучения архитектуры процессора 8086 или, точнее, того гипотетического процессора, который как бы объединяет часть архитектурных средств современных процессоров, предназначенных для использования в реальном режиме, и соответствующих архитектуре процессора 8086. Мы будем называть этот гипотетический процессор МП 86. В настоящей книге изучению архитектуры и программирования МП 86 посвящены первые три главы.
Деление программ на приложения DOS и приложения Windows не исчерпывают вопроса о возможньгх типах программ. Дело в том, что ряд дополнительных средств, имеющихся в современных процессорах, вполне можно использовать и в реальном режиме (хотя сама операционная система MS-DOS, разработанная еще в эпоху процессора 8088, ими не пользуется). К этим средствам относится расширенный состав команд процессоров и, главное, их 32-разрядная архитектура.
Современные процессоры (начиная с 80386), в отличие от своего предшественника 8086, являются 32-разрядными. Это дает возможность программисту использовать в программе 32-разядные операнды (т. е. числа в диапазоне до 23:-1=4 294 967 295), что во многих случаях позволяет упростить алгоритм программы и повысить ее быстродействие. Программа, предполагающая работать с 32-разрядными операндами, должна иметь в своем составе одну из директив .386, .486 или .586, которые разрешают транслятору использовать дополнительные средства соответствующего процессора. Включение в программу этой директивы одновременно открывает доступ и к дополнительным командам и способам обращения к памяти, отсутствующим в процессоре 8086, что также расширяет возможности программирования. В настоящей книге эти средства описаны в главе, посвященном расширенным возможностям современных процессоров.
Особая ситуация возникает, если программист хочет использовать не только 32-битовые данные, но и 32-разрядные адреса ячеек памяти. Программы такого рода называются 32-разрядными приложениями (в отличие от 16-разрядных, в которых все адреса 16-разрядные, хотя данные могут иметь размер 32 бит). Для создания 32-разрядного приложения в состав программы необходимо включить (в соответствующем месте) описатель use32. Однако следует иметь в виду, что MS-DOS не позволяет запускать 32-разрядные приложения, которые, таким образом, должны быть приложениями Windows. В то же время приложения Windows обычно составляются не на языке ассемблера, а на одном из языков высокого уровня — Паскаль, С или C++, где тип создаваемой программы (16-разрядная или 32-разрядная) определяется настройками компилятора. Поэтому вопросы разработки 32-разрядных приложений на языке ассемблера не вошли в настоящую книгу.
Как известно, система Windows допускает запуск приложений DOS (программ реального режима), организуя для этого так называемый сеанс
Введение — :
DOS, в котором программы фактически выполняются в режиме 86-го процессора. Кроме этого, в Windows предусмотрена возможность загрузки компьютера в режиме эмуляции DOS, когда компьютер работает под управлением варианта DOS, встроенного в систему Windows. Наконец, компьютер можно сконфигурировать так, чтобы он позволял загружать как Windows, так и «чистую» DOS (например, MS-DOS 6.22), без всякой Windows.' Каким вариантом загрузки компьютера пользоваться при проработке настоящей книги - дело вкуса и привычек читателя. Приводимые в книге примеры в своем большинстве просты, не затрагивают каких-то специальных системных средств и будут работать в любом режиме. Последнее замечание не относится только к примеру программы защищенного режима, приводимому в гл. 4, а также к обработчику прерываний от мыши, рассматриваемому в гл. 3. Эти программы следует запускать на «чистой* DOS.
Архитектура реального режима
11
Бант