Ассемблеры для операционной системы DOS
ЯЗЫКИ ПРОГРАММИРОВАНИЯ НИЗКОГО УРОВНЯ
Конспект лекций
Введение в программирование на языках низкого уровня. Средства программирования на низком уровне
Преимущества знания низкоуровневых языков
В настоящее время создано множество языков программирования, удобных для решения любых задач. Большинство из них являются языками высокого уровня.
Ассемблер же, самый древний язык программирования, – это язык программирования низкого уровня. До него программирование осуществлялось в машинных кодах. Спустя годы ассемблер вернулся в десятку самых популярных языков программирования.
Преимущества, которые дает знание ассемблера:
1. Глубокое понимание работы компьютера и операционной системы
Если программист пишет программу на языке высокого уровня, знание ассемблера помогает понять, как она будет выполняться, как хранятся переменные, как вызываются функции. А это позволяет избежать очень многих ошибок. Есть люди, которые знают программирование только на уровне языка, т. е. знают, что надо написать, чтобы получить результат. А сам внутренний механизм работы для них остается непонятным. Человек, владеющий ассемблером, будет лучше программировать и на других языках.
2. Максимальная гибкость при работе с аппаратными ресурсами
Используя ассемблер, можно делать с аппаратурой компьютера все что угодно. Языки же высокого уровня ограничены компилятором и используемыми библиотеками. Такие современные языки, как Java и C#, вообще не позволяют работать с аппаратными ресурсами и операционной системой напрямую.
3. Оптимизация программ по скорости выполнения
Современные компиляторы неплохо оптимизируют код, поэтому писать на ассемблере все подряд не имеет смысла. Однако если пишется, например, программа для шифрования или архивации больших файлов, то применение ассемблера позволит в несколько раз увеличить скорость ее выполнения. Причем достаточно реализовать на ассемблере небольшой критически важный участок программы, который производит вычисления или сложные преобразования, а интерфейс может быть написан на языке высокого уровня.
4. Оптимизация программ по размеру кода
Программа на ассемблере значительно меньше по размерам аналогичной программы на другом языке программирования. Для современных персональных компьютеров и серверов с терабайтными дисками и гигабайтами памяти это не играет большой роли. Но для микроконтроллеров, где всего несколько килобайт памяти, маленький размер программы очень важен. Чем меньше программа, тем меньше памяти требуется и тем проще и дешевле будет используемая микросхема.
5. Дизассемблирование и отладка
Знание ассемблера позволяет открыть дизассемблером любую программу, заглянуть внутрь и изучить механизм ее работы, даже не имея исходников. Ассемблер также незаменим при отладке программ. Иногда бывают ошибки и в самих компиляторах и, казалось бы, корректно написанный код выполняется вовсе не так, как предполагалось. Чтобы обнаружить такую ошибку надо посмотреть, во что скомпилировался код, а разобраться в этом без ассемблера невозможно.
Понятие низкоуровневого программирования
Низкоуровневое программирование – это программирование, основанное на прямом использовании возможностей и особенностей конкретной вычислительной системы. Для того чтобы писать программы на этом уровне, необходимо знать архитектуру аппаратной части системы:
структуру и функционирование системы в целом;
организацию оперативной памяти;
состав внешних устройств, их адреса и форматы регистров;
организацию и функционирование процессора, состав и форматы его регистров, способы адресации, систему команд;
систему прерываний и т. д.
При этом не следует забывать, что вычислительная система – это совокупность не только аппаратных, но и программных средств, и особенности имеющегося программного обеспечения (операционной системы) оказывают существенное влияние на разработку программ.
В истории развития программирования существовали три разновидности низкоуровневых языков, последовательно сменивших друг друга:
В машинных кодах программа представляется в виде последовательности чисел, являющихся кодами команд процессора, адресами оперативной памяти, номерами регистров процессора и внешних устройств и т. д. Фрагмент последовательности кодов команд микропроцессора с архитектурой Intel для добавления двухбайтового слова с адресом 36 к слову с адресом 32:
Очевидно, что в таком виде создание сколько-нибудь сложной программы является весьма трудной задачей.
Для решения этой задачи были разработаны так называемые мнемокоды, которые и явились основой для современных ассемблеров. Они вместо чисел позволяли использовать мнемонические (символьные) имена, отражающие смысл выполняемой команды. Приведенная выше последовательность команд в мнемонической записи:
В этом фрагменте уже виден смысл команд, из которых складывается сложение двух слов памяти.
Ассемблер отличается от своего предшественника – мнемокода обширным набором директив транслятора, существенно упрощающих процесс кодирования программы, в первую очередь директивами оформления программы в виде логически законченных элементов и макросредствами.
Назначение языков ассемблера
Ассемблер (от англ. assemble — собирать) — компилятор с языка ассемблера в команды машинного языка.
На сегодняшний день ассемблер как язык программирования, предназначенный для создания программ, используется крайне редко. Это связано с тем, что этот процесс является чрезвычайно трудоемким и получающиеся программы являются системнозависимыми, их нельзя свободно переносить между компьютерами, имеющими различные аппаратные архитектуры и операционные системы. Поэтому на сегодняшний день ассемблер изучают в учебных целях, так как только он дает полное представление о реальном устройстве и функционировании аппаратуры и операционной системы.
Сейчас разработка программ на ассемблере применяется в основном в программировании небольших микропроцессорных систем (микроконтроллеров), как правило, встраиваемых в какое-либо оборудование. Очень редко возникает потребность использования ассемблера в разрабатываемых программах в тех случаях, когда необходимо, например, получить наивысшую скорость выполнения определенного участка программы, выполнить операцию, которую невозможно реализовать средствами языков высокого уровня, либо уместить программу в память ограниченного объема (типичное требование для загрузчиков операционной системы).
Под каждую архитектуру процессора и под каждую ОС или семейство ОС существует свой ассемблер. Есть также так называемые кросс-ассемблеры, позволяющие на машинах с одной архитектурой (или в среде одной ОС) ассемблировать программы для другой целевой архитектуры или другой ОС и получать исполняемый код в формате, пригодном к исполнению на целевой архитектуре или в среде целевой ОС.
Язык ассемблера — тип языка программирования низкого уровня. Команды языка ассемблера один в один соответствуют командам процессора и представляют собой удобную символьную форму записи (мнемокод) команд и аргументов. Язык ассемблера обеспечивает связывание частей программы и данныx через метки, выполняемое при ассемблировании (для каждой метки высчитывается адрес, после чего каждое вхождение метки заменяется на этот адрес).
Каждая модель процессора имеет свой набор команд и соответствующий ему язык (или диалект) ассемблера.
Обычно программы или участки кода пишутся на языке ассемблера в случаях, когда разработчику критически важно оптимизировать такие параметры, как быстродействие (например, при создании драйверов) и размер кода (загрузочные секторы, программное обеспечение для микроконтроллеров и процессоров с ограниченными ресурсами, вирусы, навесные защиты).
Связывание ассемблерного кода с другими языками. Большинство современных компиляторов позволяют комбинировать в одной программе код, написанный на разных языках программирования. Это дает возможность быстро писать сложные программы, используя высокоуровневый язык, не теряя быстродействия в критических ко времени задачах, применяя для них части, написанные на языке ассемблера. Комбинирование достигается несколькими приемами:
1. Вставка фрагментов на языке ассемблера в текст программы (специальными директивами языка) или написание процедур на языке ассемблера. Способ хороший для несложных преобразований данных, но полноценного ассемблерного кода с данными и подпрограммами, включая подпрограммы с множеством входов и выходов, не поддерживаемых высокоуровневыми языками, с помощью него сделать нельзя.
2. Модульная компиляция. Большинство современных компиляторов работают в два этапа. На первом этапе каждый файл программы компилируется в объектный модуль. А на втором объектные модули линкуются (связываются) в готовую программу. Прелесть модульной компиляции состоит в том, что каждый объектный модуль будущей программы может быть полноценно написан на своем языке программирования и скомпилирован своим компилятором (ассемблером).
Достоинства языков ассемблера.
1. Максимально оптимальное использование средств процессора, использование меньшего количества команд и обращений в память и, как следствие, большая скорость и меньший размер программы.
2. Использование расширенных наборов инструкций процессора(MMX, SSE, SSE2, SSE3).
3. Доступ к портам ввода-вывода и особым регистрам процессора (вбольшинстве ОС эта возможность доступна только на уровне модулей ядра и драйверов)
4. Возможность использования самомодифицирующегося (в том числеперемещаемого) кода (под многими платформами она недоступна, так как запись в страницы кода запрещена, в том числе и аппаратно, однако в большинстве общедоступных систем из-за их врожденных недостатков имеется возможность исполнения кода, содержащегося в сегменте (секции) данных, куда запись разрешена).
5. Максимальная адаптация для нужной платформы.
Однако следует отметить, что последние технологии безопасности, внедряемые в операционные системы и компиляторы, не позволяют делать самомодифицирующего кода, так как исключают одновременную возможность исполнения программы и запись в одном и том же участке памяти (технология W^X).
Технология W^X используется в OpenBSD , в других BSD-системах, в Linux. В Microsoft Windows (начиная с Windows XP SP2) применяется схожая технология DEP.
Недостатки языков ассемблера.
1. Большие объемы кода, большое число дополнительных мелких задач, меньшее количество доступных для использования библиотек по сравнению с языками высокого уровня.
2. Трудоемкость чтения и поиска ошибок (хотя здесь многое зависит откомментариев и стиля программирования).
3. Часто компилятор языка высокого уровня, благодаря современнымалгоритмам оптимизации, даёт более эффективную программу (по соотношению качество/время разработки).
4. Непереносимость на другие платформы (кроме совместимых).
5. Ассемблер более сложен для совместных проектов.
На языке ассемблера пишут:
1) программы, требующие максимальной скорости выполнения: ядра операционных систем реального времени, основные компоненты компьютерных игр и критичные по времени участки программ;
2) программы, взаимодействующие с внешними устройствами: драйверы, программы, работающие напрямую с портами, звуковыми и видеокартами;
3) программы, использующие полностью возможности процессора: ядра многозадачных операционных систем, серверы;
4) программы, полностью использующие возможности операционной системы: вирусы, антивирусы, защита от несанкционированного доступа, программы обхода защиты от несанкционированного доступа.
Ассемблеры для операционной системы DOS
Наиболее известными ассемблерами для операционной системы DOS являлись пакеты Borland Turbo Assembler (TASM) и Microsoft Macro Assembler (MASM). Также в свое время был популярен простой ассемблер A86. Изначально они поддерживали лишь 16-битные команды (до появления процессора Intel 80386). Более поздние версии TASM и MASM поддерживают и 32-битные команды, а также все команды, введенные в более современных процессорах, и системы команд, специфические для конкретной архитектуры (такие, как MMX, SSE, 3DNow! и т. д.).
Особенностью TASM всегда была быстрота трансляции и обширный набор макросредств. Кроме поддержки стандартного режима, совместимого с ассемблером MASM, данный ассемблер поддерживал также расширенный режим «IDEAL». Несмотря на то что уже много лет Turbo Assembler не поддерживается корпорацией Borland, он до сих пор популярен в кругах программистов.
Дата добавления: 2018-06-27 ; просмотров: 670 ;
MASM, TASM, FASM, NASM под Windows и Linux
В данной статье я хочу рассмотреть вопросы, которые могут возникнуть у человека, приступившего к изучению ассемблера, связанные с установкой различных трансляторов и трансляцией программ под Windows и Linux, а также указать ссылки на ресурсы и книги, посвященные изучению данной темы.
Используется для создания драйверов под Windows.
По ссылке переходим на сайт и скачиваем пакет (masm32v11r.zip). После инсталляции программы на диске создается папка с нашим пакетом C:\masm32. Создадим программу prog11.asm, которая ничего не делает.
Произведём ассемблирование (трансляцию) файла prog11.asm, используя ассемблер с сайта masm32.
Ключ /coff используется здесь для трансляции 32-битных программ.
Линковка производится командой link /subsystem:windows prog11.obj (link /subsystem:console prog11.obj)
MASM — один из немногих инструментов разработки Microsoft, для которых не было отдельных 16- и 32-битных версий.
Также ассемблер версии 6. можно взять на сайте Кипа Ирвина kipirvine.com/asm, автора книги «Язык ассемблера для процессоров Intel».
Кстати, вот ссылка на личный сайт Владислава Пирогова, автора книги “Ассемблер для Windows”.
MASM с сайта Microsoft
Далее скачаем MASM (версия 8.0) с сайта Microsoft по ссылке. Загруженный файл носит название «MASMsetup.exe». При запуске этого файла получаем сообщение -«Microsoft Visual C++ Express Edition 2005 required».
Открываем этот файл архиватором (например 7zip). Внутри видим файл setup.exe, извлекаем его, открываем архиватором. Внутри видим два файла vc_masm.msi,vc_masm1.cab. Извлекаем файл vc_masm1.cab, открываем архиватором. Внутри видим файл FL_ml_exe_____X86.3643236F_FC70_11D3_A536_0090278A1BB8. Переименовываем его в файл fl_ml.exe, далее, произведём ассемблирование файла prog11.asm, используя ассемблер fl_ml.exe.
MASM в Visual Studio
Также MASM можно найти в папке с Visual Studio (у меня VS 10) вот здесь: C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\ml.exe.
Для того, чтобы запустить на 32- или 64-разрядной системе и создавать программы, работающие как под 32-, так и под 64-разрядной Windows, подходит MASM32 (ml.exe, fl_ml.exe). Для того, чтобы работать на 32- и 64-разрядных системах и создавать программы, работающие под 64-разрядной Windows, но неработающие под 32-разрядной нужен ассемблер ml64.exe. Лежит в папке C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\amd64 и вот здесь — C:\Program Files\Microsoft Visual Studio 10.0\VC\bin\x86_amd64.
Программный пакет компании Borland, предназначенный для разработки программ на языке ассемблера для архитектуры x86. В настоящее время Borland прекратила распространение своего ассемблера.
Скачать можно, например, здесь. Инсталлятора нет, просто извлекаем программу. Вот исходник из книги Питера Абеля (рис. 3.2) «Язык Ассемблера для IBM PC и программирования».
Выполним ассемблирование (трансляцию) файла abel32.asm.
Корректность работы программы можно проверить, произведя линковку (tlink.exe) объектного файла и запустив полученный файл в отладчике.
Как было сказано выше, MASM можно использовать для работы с 16-битными программами. Выполним ассемблирование (трансляцию) программы abel32.asm с помощью ассемблера MASM:
Ключ /coff здесь не используется.
Линковка производится файлом link16.exe
В статье Криса Касперски «Сравнение ассемблерных трансляторов» написано, что «FASM — неординарный и весьма самобытный, но увы, игрушечный ассемблер. Пригоден для мелких задач типа „hello, world“, вирусов, демок и прочих произведений хакерского творчества.»
Скачаем FASM с официального сайта. Инсталлятора нет, просто извлекаем программу. Откроем fasm editor — C:\fasm\fasmw.exe. В папке C:\fasm\EXAMPLES\HELLO есть файл HELLO.asm.
Откроем файл HELLO.asm из fasmw.exe. Изменим строку include ‘win32ax.inc’ на строку include ‘c:\fasm\INCLUDE\WIN32AX.INC’. Запускаем из меню Run → Run.
Вот ссылки на ресурсы, посвященные FASM:
Для того, использовать FASM в Linux (у меня Ubuntu), скачаем соответствующий дистрибутив (fasm-1.71.60.tgz), распакуем его, в папке у нас будет бинарный файл fasm, копируем этот файл в /usr/local/bin для того, чтобы можно было запускать его из консоли, как любую другую команду.Выполним ассемблирование программы hello.asm из папки fasm/examples/elfexe/hello.asm.
Корректность работы программы можно проверить в отладчике.
Nasm успешно конкурирует со стандартным в Linux- и многих других UNIX-системах ассемблером Gas.
Nasm в Linux можно установить его с помощью менеджера пакетов или из командной строки: в дистрибутиве Debian (Ubuntu) командой apt-get install nasm, в дистрибутивах Fedora, CentOS, RedHat командой yum install nasm.
Создадим программу, которая 5 раз выводит сообщение “Hello”. Пример взят из книги Андрея Викторовича Столярова “Программирование на языке ассемблера NASM для ОС UNIX”. Учебник, а также библиотека “stud_io.inc” есть на личном сайте автора.
Выполним ассемблирование и линковку и запустим файл hello.asm.
Для 64bit необходимо использовать команду nasm -f elf64 hello.asm
NASM для Windows можно установить, скачав соответствующий дистрибутив с соответствующего сайта.
Ассемблирование:
nasm -f bin имя_файла.asm -o имя_файла.com
Ссылки на ресурсы, посвященные Nasm:
Стандартный ассемблер практически во всех разновидностях UNIX, в том числе Linux и BSD. Свободная версия этого ассемблера называется GAS (GNU assembler). Позволяет транслировать программы с помощью компилятора GCC.
Из учебников удалось найти только книгу на английском «Programming from the ground up». На русском удалось найти только одну главу из книги С. Зубкова «Assembler для DOS, Windows и UNIX».
Возьмем пример программы, которая ничего не делает, с сайта. Создадим программу gas.s
Выполним ассемблирование (трансляцию), линковку и запуск программы:
Если в данной программе изменить _start на main, то можно выполнить ассемблирование (трансляцию) и линковку компилятором gcc.
Выполним ассемблирование (трансляцию), линковку и запуск программы:
Выводы: если вы изучаете программирование под Windows, то вы можете остановить свой выбор на Masm; Tasm больше не поддерживается, но для обучения по старым классическим учебникам подойдёт.
Под Linux Gas подойдет тем, кто использует GCC, а тем, кому не нравится синтаксис Gas, подойдёт Nasm.