Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Разработка приложений на языке ассемблер в среде MS MASM. Учебно-методическое пособие по дисциплинам «Ассемблер» и «Операционные системы и системное п
.pdf
Министерство транспорта Российской Федерации
Федеральное государственное автономное образовательное
учреждение высшего образования
«Российский университет транспорта»
___________________________________________________________
Кафедра “Цифровые технологии управления транспортными процессами”
В.А. ВАРФОЛОМЕЕВ
РАЗРАБОТКА ПРИЛОЖЕНИЙ НА ЯЗЫКЕ
АССЕМБЛЕР В СРЕДЕ
MS MASM
Учебно-методическое пособие для бакалавров направлений
"Информатика и вычислительная техника"
и "Информационные системы и технологии"
М О С К В А - 2021
1

УДК 681.3.066
В18
Варфоломеев В.А. Разработка приложений на языке ассемблер в среде MS
MASM: Учебно-методическое пособие по дисциплинам "Ассемблер" и
«Операционные системы и системное программирование». — М.: РУТ
(МИИТ), 2021. — 59 с.
В учебно-методическом пособии представлен лабораторный практикум, состоящий из пяти лабораторных работ по изучению средств разработки и написания программ на языке ассемблер для современных персональных компьютеров на базе микропроцессора Intel с использованием
среды программирования Макро Ассемблер (MASM).
Рецензент: к.т.н., доцент каф. «Вычислительные системы, сети и информационная безопасность» РУТ (МИИТ) Шамров Михаил Иванович.
© РУТ (МИИТ), 2021
2

СОДЕРЖАНИЕ
ВВЕДЕНИЕ ....................................................................................................... 5
1 ОСНОВНЫЕ ПОНЯТИЯ ........................................................................... 6
1.1 Машинный язык и язык ассемблер ...................................................... 6
1.2 Синтаксис языка ассемблер .................................................................. 7
1.3 Структура программы на языке ассемблер ......................................... 8
2 СРЕДСТВА РАЗРАБОТКИ ПРИЛОЖЕНИЙ НА ЯЗЫКЕ АССЕМБЛЕР.
ЛАБОРАТОРНАЯ РАБОТА №1 ................................................................... 10
2.1 Пример простейшей программы на языке ассемблер ...................... 10
2.2 Этапы разработки программ на ассемблере ...................................... 12
2.3 Рабочее задание и порядок выполнения работы ............................... 15
2.3.1 Установка программного обеспечения MASM ............................. 15
2.3.2 Создание EXE файла ........................................................................ 15
2.3.3 Использование отладчика ................................................................ 16
2.3.4 Представление данных в ассемблере ............................................. 17
2.4 Использование командных файлов .................................................... 20
2.5 Требования к отчету ............................................................................. 22
2.6 Контрольные вопросы .......................................................................... 22
3 АРИФМЕТИЧЕСКИЕ ВЫЧИСЛЕНИЯ. ЛАБОРАТОРНАЯ РАБОТА
№2. .................................................................................................................... 24
3.1 Флаги ...................................................................................................... 24
3.2 Арифметические команды ................................................................... 24
3.2.1 Команда сложения ADD .................................................................. 25
3.2.2 Команда вычитания SUB ................................................................. 25
3.2.3 Команды умножения MUL, IMUL .................................................. 26
3.2.4 Команды деления DIV, IDIV ........................................................... 27
3.2.5 Команды преобразования типа MOVSX, MOVZX ....................... 27
3.3 Команды сравнения и передачи управления ..................................... 28
3.3.1 Команда безусловного перехода JMP ............................................ 28
3.3.2 Команда сравнения CMP ................................................................. 28
3.3.3 Команды условного перехода ......................................................... 29
3.4 Рабочее задание..................................................................................... 30
3.5 Требования к отчету ............................................................................. 32
3.6 Контрольные вопросы .......................................................................... 32
3.7 Пример программы ............................................................................... 33
4 БИТОВЫЕ ОПЕРАЦИИ. ЛАБОРАТОРНАЯ РАБОТА №3 .................. 34
4.1 Команды логических операций AND, TEST, OR, XOR, NOT ......... 34
4.2 Команды сдвига .................................................................................... 35
4.2.1 Логический сдвиг SHR, SHL ........................................................... 35
4.2.2 Арифметический сдвиг SAR, SAL .................................................. 36
4.2.3 Циклический сдвиг ROR, ROL ....................................................... 37
3

4.3 Типовые задачи использования битовых операций .......................... 37
4.3.1 Проверка значения бита ................................................................... 37
4.3.2 Установка единичного значения бита ............................................ 38
4.3.3 Установка нулевого значения (сброс) бита ................................... 38
4.3.4 Инвертирование значения бита ....................................................... 39
4.3.5 Перемещение битов числа ............................................................... 39
4.4 Рабочее задание..................................................................................... 40
4.5 Требования к отчету ............................................................................. 41
4.6 Контрольные вопросы .......................................................................... 41
5 ОБРАБОТКА МАССИВОВ. ЛАБОРАТОРНАЯ РАБОТА №4 ............ 42
5.1 Описание и инициализация массивов ................................................ 42
5.2 Доступ к элементам одномерного массива ........................................ 42
5.3 Доступ к элементам двумерного массива .......................................... 43
5.4 Организация циклов: команда LOOP ................................................. 44
5.5 Рабочее задание..................................................................................... 45
5.6 Требования к отчету ............................................................................. 46
5.7 Контрольные вопросы .......................................................................... 47
5.8 Пример программы ............................................................................... 47
6 ПРОЦЕДУРЫ. ЛАБОРАТОРНАЯ РАБОТА №5. .................................. 49
6.1 Механизм вызова процедур ................................................................. 49
6.2 Работа со стеком ................................................................................... 49
6.2.1 Запись в стек ...................................................................................... 50
6.2.2 Чтение из стека ................................................................................. 51
6.3 Создание и использование процедур.................................................. 52
6.3.1 Описание процедуры ........................................................................ 52
6.3.2 Вызов процедуры .............................................................................. 52
6.3.3 Возврат из процедуры ...................................................................... 52
6.4 Организация интерфейса с процедурой ............................................. 53
6.5 Рабочее задание..................................................................................... 54
6.6 Требования к отчету ............................................................................. 55
6.7 Контрольные вопросы .......................................................................... 55
6.8 Пример программы ............................................................................... 57
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ...................................... 59
4

ВВЕДЕНИЕ
Данное учебно-методическое пособие посвящено практическому изучению ассемблера - низкоуровневого языка программирования. «Низкоуровневость» означает, что доступный программисту набор команд ассемблера однозначно соответствует набору так называемых «машинных» команд, которые представляются в двоичном коде и могут быть поняты и исполнены процессором. Ассемблер всего лишь позволяет записать машинные команды в более понятном человеку символическом виде.
Чем интересен и полезен современному специалисту ассемблер? В
первую очередь, возможностью написания эффективных программ в полной мере использующих особенности архитектуры современных компьютеров. Эффективность выражается в более экономном использовании ресурсов компьютера (в первую очередь оперативной памяти) и повышении
производительности вычислений. На ассемблере пишут аппаратно-зависимые модули в составе операционной системы, программы управления интеллектуальными устройствами и микроконтроллерами. Для прикладного
программиста существует возможность включать в проект, разрабатываемый, например, на высокоуровневом языке С++, отдельные модули, написанные на ассемблере для существенного повышения быстродействия программ.
Однако есть еще одна важная причина, по которой следует познакомиться с ассемблером. Изучение особенностей построения и реализации ассемблерных программ дает наглядный способ практического знакомства с
базовыми понятиями и глубинными механизмами функционирования современных вычислительных систем на аппаратном уровне и на уровне операционной системы, без понимания которых не может получиться квалифицированный специалист. Именно эта цель и ставится перед студентами,
приступающими к изучению ассемблера.
В данном пособии представлено 5 лабораторных работ по базовым
вопросам разработки программ и использования основных алгоритмических конструкций в ассемблере. В качестве инструментального средства
для разработки используется макроассемблер компании Microsoft (MASM).
Особое внимание уделено использованию отладчика для получения детальной информации о содержимом памяти программы в процессе выполнения.
Следует отметить, что пособие содержит справочные сведения, касающиеся исключительно тем, представленных в лабораторных работах, и не
может быть использовано для изучения всех элементов языка в полном объеме. Обязательно необходимо использовать дополнительные источники,
включая лекционные материалы и рекомендованную литературу.
Автор выражает благодарность студенту Панферову В.Д. (УВА-311,
2019) за помощь при подготовке примеров программ.
5

1 ОСНОВНЫЕ ПОНЯТИЯ
1.1 Машинный язык и язык ассемблер
Как известно, компьютерная программа представляет собой последовательность команд (инструкций), которые "объясняют" компьютеру, что
он должен делать. Программа, запущенная на выполнение, должна быть
размещена в оперативной памяти компьютера в виде совокупности входящих в нее команд, записанных на машинном языке. Машинный язык – это
система представления в двоичном коде всех поддерживаемых процессором команд. Машинный язык - единственный язык, который машина понимает, причем каждая модель процессора имеет свой собственный машинный язык. Процессор извлекает команды машинного языка из оперативной
памяти в определенной последовательности и выполняет их.
Например, машинная команда сложения двух чисел, хранящихся в регистрах процессора AX и BX, будет представлена в оперативной памяти в
виде двухбайтового двоичного числа 000001111000011b. Эти два байта
точно указывают процессору, какую операцию произвести, где размещены
исходные данные и куда поместить результат.
Регистры процессора – это ячейки сверхбыстрой памяти внутри процессора, предназначенные для хранения исходных данных и результатов
вычислений, а также для связи процессора с другими устройствами компьютера. К данным, сохраненным в регистрах, процессор получает доступ
очень быстро - намного быстрее, чем к данным, хранимым в оперативной
памяти. Для всех регистров процессора установлены стандартные символические имена, например, AX, BX, ESI, EDI, DS, CS и др. Различают регистры общего назначения, которые можно использовать в программе произвольно, и специальные регистры, которые предназначены для определенных целей.
Язык ассемблер - это язык программирования, основанный на использовании символьной формы записи команд машинного языка. Каждой машинной команде соответствует определенная команда ассемблера, представленная мнемокодом, в котором указывается код выполняемой операции и операнды. Например, рассмотренная выше команда сложения содержимого регистров AX и BX на языке ассемблер будет записана так:
ADD AX,BX
Код операции ADD происходит от английского «addition» (сложение), а
операнды представлены регистрами процессора AX и BX.
Программа, записанная на языке ассемблер, относительно легко воспринимается человеком, но не может быть непосредственно выполнена
компьютером. Для выполнения ассемблерной программы сначала необходимо осуществить ее перевод на машинный язык. Этот процесс, называется
ассемблированием программы. Операцию перевода с языка ассемблер на
6

машинный язык выполняет специальная программа, называемая ассембле-
ром.
Язык ассемблер является машинно-зависимым, так как программы,
написанные на этом языке, непосредственно относятся к тому типу процессора, на котором они должны выполняться. Язык ассемблер для персонального компьютера, использующего микропроцессоры фирмы Intel (или
AMD), принципиально отличен от языка ассемблер для других компьютеров. Более того, существуют некоторые различия между языками ассемблер
для персональных компьютеров, использующих различные модели микропроцессоров Intel (например, i386, Pentium IV или Core i7). Наиболее важное отличие заключается в максимальном размере используемых регистров: 16 разрядов (2 байта) для первых моделей процессора; 32 разряда (4
байта) для моделей, начиная с i386; 64 разряда (8 байт) для современных
моделей. Именно разрядность регистров определяет понятие «разрядность
компьютера».
1.2 Синтаксис языка ассемблер
Команда языка ассемблер состоит из четырех частей и имеет вид:
Метка КОП Операнды Комментарий
Вот пример типичной команды:
PART1: ADD AX,BX ;Добавить к длине буфера
Единственная обязательная часть команды языка ассемблер - код операции (КОП), определяющий, какую операцию должен будет выполнить
процессор. В нашем примере ADD указывает на операцию сложения.
Поле операндов содержит дополнительную информацию о команде,
например, какие значения участвуют в операции. Каждому коду операции
должно соответствовать определенное число операндов определенного
типа. Для команды ADD требуется два операнда; операция перемены знака
(NEG) обходится лишь одним, а для некоторых команд, например, команды
преобразования типа числа CBW, операнды не указываются вовсе. В качестве операндов могут использоваться регистры процессора, переменные,
адреса памяти, задаваемые непосредственно числовые и символьные значения.
Поля метки и комментария – необязательные поля в команде. Метка
позволяет обозначить какое-либо конкретное место в тексте программы для
последующих ссылок на него. Фактически метка является символическим
указателем на расположение команды в оперативной памяти, принимая
значение адреса соответствующей ячейки. Использование меток - одна из
причин предпочтительности языка ассемблер перед машинным языком.
Превращением же символических имен в реальные адреса ведает ассемблер.
7

Поле комментария начинается с символа ";" и служит для записи
произвольного текста, поясняющего смысл выполняемого в команде дей-
ствия. Существует возможность отвести под комментарий целую строку,
поставив в ее начале символ ";". Это позволяет программисту включить в
текст программы блок собственной информации, к примеру, описание используемого алгоритма и т.п..
Помимо команд язык ассемблер включает специальные инструкции директивы. Директивы не являются частью выполняемой программы, а
предназначены для программы-ассемблера, который должен выполнять их
во время ассемблирования. Директивы не преобразуются в машинные команды.
Формат директив схож с форматом представления команд, но может
иметь некоторые особенности, которые здесь не рассматриваются.
1.3 Структура программы на языке ассемблер
Программа, написанная на языке ассемблер, представляется в виде совокупности блоков, называемых сегментами. Обычно программа включает
три сегмента: сегмент данных, сегмент кода и сегмент стека. При размещении программы в оперативной памяти каждому сегменту будет предоставлена отдельная область памяти.
Сегмент данных программы служит для описания и инициализации
переменных и обеспечивает возможность резервирования необходимого
количества ячеек памяти для их размещения в памяти. Начало сегмента
данных обычно помечают директивой .data.
Сегмент кода программы содержит записанные программистом команды. Начало сегмента кода обычно помечают директивой .code.
Сегмент стека служит для резервирования памяти для временного
хранения данных программы при вызове подпрограмм, обработке прерываний и т.п. Начало сегмента стека обычно помечают директивой .stack.
Способ размещения сегментов программы в оперативной памяти
определяется выбранной моделью памяти, задаваемой с помощью директивы .model. Микропроцессор Intel реализует две основные модели: сег-
ментированную и плоскую.
В сегментированной модели памяти, используемой для 16-разрядных
процессоров, для каждого сегмента программы (данные, код, стек) можно
было выделить отдельный сегмент оперативной памяти размером не более
64 Кб. Для формирования адреса каждого сегмента использовались сегментные регистры: DS – для сегмента данных, CS – кода, SS – стека. Адрес
любой ячейки памяти в сегменте записывался в виде P:D, где величина P
задает позицию начала сегмента, а величина D задает смещение ячейки
внутри выбранного сегмента. Поскольку установлено, что начало любого
8

сегмента должно приходится на ячейку с абсолютным адресом S, кратным
16 (10h), величина P определяется, как S/16. Например, если абсолютный
адрес начала сегмента равен 144=90h, то позиция начала сегмента P будет
равна 9. Адрес первой ячейки данного сегмента будет записан так: 9:0 (смещение D равно 0), следующей за ней – 9:1 и т.д.
Именно для хранения сегментной составляющей адреса P служат сегментные регистры микропроцессора Intel. Позиция начала сегмента данных
в памяти задается с помощью сегментного регистра DS, так что адрес пер-
вой переменной, объявленной в сегменте данных, будет записан как DS:0.
Ячейки сегмента кода адресуются с помощью пары регистров CS:IP. Сегментный регистр CS задает позицию начала сегмента кода в памяти. 16разрядный регистр IP служит для указания относительного адреса (смещения) очередной выполняемой машинной команды в сегменте кода. Содер-
жимое регистра IP изменяется в ходе выполнения программы автоматически путем добавления к текущему значению величины, равной длине (в
байтах) выполненной команды.
Плоская модель памяти (flat) используется для 32 (64)-разрядных
процессоров и заключается в создании упрощенных по структуре программ, в которых данные, код и стек размещаются в одном сегменте памяти, но в разных его участках. Для 32-разрядных процессоров максимальный размер сегмента памяти равен 4 Гб, для 64-разрядных – 16 Еб. Для адресации команд используется 32-разрядный регистр EIP или 64-разряд-
ный RIP, в котором всегда хранится адрес следующей выполняемой команды. На рисунке 1.1 показано, как будут размещены в памяти исполни-
мые программы при использовании сегментированной и плоской моделей
памяти.
Сегментированная модель памяти
DS:0
CS:0
SS:0
Сегмент данных
Сегмент кода
Сегмент стека
Плоская модель памяти
0
Данные, код,
стек
Рисунок 1.1 - Размещение программы в памяти
9

2 СРЕДСТВА РАЗРАБОТКИ ПРИЛОЖЕНИЙ НА ЯЗЫКЕ
АССЕМБЛЕР. ЛАБОРАТОРНАЯ РАБОТА №1
Содержание работы:
- знакомство с общими принципами создания программ на языке ас-
семблер;
- практическое освоение средств системы программирования Макро
Ассемблер (MASM);
- практическое изучение работы с отладчиком OllyDebug.
2.1 Пример простейшей программы на языке ассемблер
Рассмотрим, как выглядит простейшая оконная программа на языке
ассемблер, которая предназначена для вывода на экран фразы: «Здравствуйте, это я, ХХХХХ!», где ХХХХХ - Ваши имя и фамилия.
Текст программы представлен на рисунке 2.1.
;Лабораторная работа №1 (1)
;Выполнил ст. гр. УВА-313 Панферов В.Д. (2)
;Программа 1 (HELLO.ASM) Вариант №1 (3)
.486 (4)
.model flat, stdcall ;Тип используемой модели памяти (5)
option casemap: none (6)
.stack 100h ;Определяется сегмент стека размером 256 байт (7)
;Подключение необходимых системных модулей и библиотек (8)
include c:\masm32\include\windows.inc (9)
include c:\masm32\include\user32.inc (10)
include c:\masm32\include\kernel32.inc (11)
includelib c:\masm32\lib\user32.lib (12)
includelib c:\masm32\lib\kernel32.lib (13)
.data ;Начало сегмента данных (14)
tit db 'Привет, мир',0 ;Переменная - заголовок окна (15)
hello db'Здравствуйте, я Панферов!',0;Резервируется память (16)
;для переменной Hello
.code ;Начало сегмента кода (17)
main: ;Метка, обозначающая точку входа в программу (18
push 0 ;Дескриптор окна (19)
push offset tit ;Заголовок окна (20)
push offset hello ;Текст для вывода (21)
push 0 ;Стиль окна (0 – окно с кнопкой ОК) (22)
call MessageBox ;Вызов функции вывода на экран (23)
push 0 ;Код завершения (24)
call ExitProcess ;Завершаем работу программы (25)
end main (26)
Рисунок 2.1 – Исходный код программы hello.asm
10
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
