Ассемблер GAS в операционной системе Linux на платформе x86-64
Покупка
Новинка
Тематика:
Другие операционные системы
Издательство:
ФЛИНТА
Автор:
Пирогов Владислав Юрьевич
Год издания: 2024
Кол-во страниц: 176
Дополнительно
Вид издания:
Монография
Уровень образования:
Профессиональное образование
ISBN: 978-5-9765-5586-0
Артикул: 846532.01.99
В монографии рассматриваются различные аспекты низкоуровневого программирования для 64-битовых операционных систем Linux. На основе многочисленных примеров проводится анализ 64-битового программирования. Значительная часть монографии посвящена программно-архитектурным особенностям систем x86-64, в частности рассмотрению команд микропроцессора. В монографии рассматриваются также особенности интеграции
языка ассемблер с языками высокого уровня. Часть монографии посвящена особенностям ассемблера GAS, его 64-битовой подсистеме.
Монография предназначена программистам, разрабатывающим приложения для Linux. Она также может быть использована как учебное пособие в высших и средних учебных заведениях на инженерных специальностях по таким дисциплинам как низкоуровневое программирование, системное программирование, программирование на языке ассемблера и др.
Тематика:
ББК:
УДК:
ОКСО:
- ВО - Бакалавриат
- 02.03.02: Фундаментальная информатика и информационные технологии
- 09.03.01: Информатика и вычислительная техника
- 09.03.02: Информационные системы и технологии
ГРНТИ:
Скопировать запись
Фрагмент текстового слоя документа размещен для индексирующих роботов
В.Ю. Пирогов АССЕМБЛЕР GAS В ОПЕРАЦИОННОЙ СИСТЕМЕ LINUX НА ПЛАТФОРМЕ X86-64 Монография 2-е издание, стереотипное Шадринск ШГПУ 2024 Москва Издательство «ФЛИНТА» 2024
УДК 004.431.4 ББК 32.973.21 П33 Рецензенты: Баландин А.А. – канд. пед. наук, доцент кафедры программирования и автоматизации бизнес-процессов ФГБОУ ВО «Шадринский государственный педагогический университет» Семахина А.М. – канд. технич. наук, доцента кафедры программного обеспечения автоматизированных систем ФГБОУ ВО «Курганский государственный университет» П33 Пирогов В.Ю. Ассемблер GAS в операционной системе Linux на платформе x86-64 : монография / В.Ю. Пирогов. — 2-е изд., стер. — Москва : ФЛИНТА, 2024. — 176 с. — ISBN 978-5-9765-5586-0 (ФЛИНТА) ; ISBN 978-5-87818-702-2 (ШГПУ). — Текст : электронный. В монографии рассматриваются различные аспекты низкоуровневого программирования для 64-битовых операционных систем Linux. На основе многочисленных примеров проводится анализ 64-битового программирования. Значительная часть монографии посвящена программно-архитектурным особенностям систем x86-64, в частности рассмотрению команд микропроцессора. В монографии рассматриваются также особенности интеграции языка ассемблер с языками высокого уровня. Часть монографии посвящена особенностям ассемблера GAS, его 64-битовой подсистеме. Монография предназначена программистам, разрабатывающим приложения для Linux. Она также может быть использована как учебное пособие в высших и средних учебных заведениях на инженерных специальностях по таким дисциплинам как низкоуровневое программирование, системное программирование, программирование на языке ассемблера и др. УДК 004.431.4 ББК 32.973.21 ISBN 978-5-9765-5586-0 (ФЛИНТА) ISBN 978-5-87818-702-2 (ШГПУ) © Пирогов В.Ю., 2024 © ШГПУ , 2024 2
ОГ ЛАВЛЕНИЕ ВВЕДЕНИЕ .......................................................................................................... 5 ГЛАВА 1. АССЕМБЛЕРЫ И ПЛАТФОРМА X86-64 ................................... 9 1.1. Платформа x86-64 .................................................................................. 9 1.2. Ассемблеры для платформы x86-64 .................................................. 11 1.2.1. Masm ............................................................................................... 12 1.2.2. Tasm ................................................................................................ 13 1.2.3. Nasm ............................................................................................... 13 1.2.4. Yasm ................................................................................................ 14 1.2.5. Fasm ................................................................................................ 15 1.2.6. Gas .................................................................................................. 15 1.3. Аппаратная архитектура ..................................................................... 16 1.3.1 Архитектура процессора x86-64 ................................................... 16 1.3.2. Регистр флагов ............................................................................... 19 ГЛАВА 2. АССЕМБЛЕР В ОПЕРАЦИОННОЙ СИСТЕМЕ LINUX ........ 23 2.1. Основы программирования на языке ассемблера в операционной системе Linux .............................................................................................. 23 2.1.1. Языки высокого уровня и ассемблер .......................................... 23 2.1.2. Ассемблер GAS ............................................................................. 36 2.1.3. Об основах программирования на платформе x86-64 на ассемблере GAS ...................................................................................... 42 2.1.3.1. Адресация ................................................................................ 42 2.1.3.2. Условные и безусловные переходы ...................................... 44 2.1.3.3. Системные вызовы ................................................................. 50 2.2. Стек и функции .................................................................................... 55 2.2.1. Структура стека ............................................................................. 55 2.2.2. Вызов функций .............................................................................. 58 2.2.3. Передача параметров в функцию и локальные переменные .... 63 2.2.4. Многомодульное программирование на ассемблере GAS ....... 71 2.3. Интеграция ассемблера и языков высокого уровня ......................... 77 2.3.1. Использование программы gcc для компилирования ассемблерных модулей ........................................................................... 78 2.3.2. Параметры командной строки ..................................................... 80 2.3.3. Использование ассемблерных модулей на языках высокого уровня ....................................................................................................... 87 2.3.4. Статические библиотеки .............................................................. 90 2.3.5. Использование языков высокого уровня на языке ассемблера 95 2.3.6. Динамические библиотеки ......................................................... 100 3
2.4. Основы системного программирования в операционной системе Linux ........................................................................................................... 102 2.4.1. Файловая система........................................................................ 102 2.4.2. Доступ к содержимому файлов ................................................. 103 2.4.3. Управление файловой системой ................................................ 110 2.4.4. Управление памятью ................................................................... 121 2.4.4.1. Виды памяти ......................................................................... 121 2.4.4.2. Динамическая память и файлы отображаемые в памяти . 131 2.4.5. Управление процессами ............................................................. 139 2.4.5.1. Запуск процессов и создание процессов ............................ 139 2.4.5.2. Взаимодействие процессов.................................................. 152 ЗАКЛЮЧЕНИЕ ............................................................................................... 159 СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ ...................................... 160 Приложение 1. Список системных функций Linux, используемый в работе с кратким описанием в нотации языка C ...................................................... 167 Приложение 2. Система команд процессора X86-64 ................................... 169 4
ВВЕДЕНИЕ Приступая к книге об языке ассемблера, следует прежде всего ответить на следующие вопросы: 1. Что такое язык ассемблера? 2. О какой аппаратной платформе пойдет речь? 3. Какая программная платформа (операционная система) будет использована? 4. Какой ассемблер для выбранных платформ будет рассматриваться? Приступим к ответам на поставленные вопросы. Языком ассемблера будем называть язык программирования, в основе которого лежат команды процессора, обозначаемые удобным для восприятия человека способом. Обозначения обычно представляют собой слова или сокращения на одном из естественных языков, чаще всего английском языке. Основная идея заключается в том, что в таком виде язык становится более понятным и более удобным для восприятия, чем набор двоичных кодов. Например, команда mov, сокращение от английского move, т.е. перемещать. Используется для обозначения команды перемещения данных. Кроме символьного обозначения команда языка ассемблера содержит в себе как правило следующие элементы [12, 13]: − возможность использовать символьные метки, для обозначения адреса команды или адреса области памяти (переменной); − именованные константы, которые в процессе трансляции переводятся в конкретные значения; − макросы, позволяют обозначить определенную последовательность кода именем, что дает возможность заменять подобный код в программе именем макроса с возможностью параметрической настройки его; − директивы ассемблера, позволяющие влиять на процесс трансляции программы. Процесс трансляции программы на языке ассемблера обычно называют ассемблированием. В результате ассемблирования создается двоичный файл, который может исполняться в той или иной среде (операционной системе) или служить частью другого исполняемого файла. Следует особо отметить, что в литературе термин ассемблер используется и как синоним термину «язык ассемблера» и для обозначения программы для трансляции программ, написанных на языке ассемблера. В качестве аппаратной платформы нами взята платформа, обычно 5
обозначаемая как x86–64. Термин x86–64 имеет несколько синонимов, таких, например, как Intel 64, AMD64 и др. Это вносит определенную нечеткость в изложение, хотя, по сути, имеется в виду одно и то же – 64битовое расширение архитектуры x86. Архитектуры x86-64, разрабатываемые корпорациями Intel и AMD [23-28, 33-38], отличаются друг от друга, но это сказывается в основном при разработке компиляторов и операционных систем [62]. На разработку прикладного программного обеспечение это не влияет. Так что мы в дальнейшем не будем акцентировать внимание на эти различия. За основу взята программная платформа, основанная на Unixподобных операционных системах [17, 19-20], учитывая, что популярность этих операционных систем с каждым годом в нашей стране увеличивается. В качестве основного инструмента взят ассемблер GAS (GNU assembler), входящий в пакет GNU Binutils1 и входящий в тот же пакет. Остановимся теперь подробнее на содержательной стороне представленной ниже монографии. Прежде всего следует отметить, что литературы по программированию на языке ассемблера для операционной системы Linux на русском языке практически нет, за исключением авторского учебного пособия [18]. Англоязычная литература представлена в следующих книгах [57-62]. Это в значительной степени определило содержание монографии. В определенной степени она дополняет книгу [18], пропуская некоторые уже изложенные там вопросы, либо излагая их конспективным образом. Структура книги разбита на две главы. Первая глава посвящена двум вопроса: краткому обзору существующих ассемблеров для платформы x8664 и изложению программной архитектуры x86-64. Особый акцент сделан на особенностях архитектуры x86-64 в сравнении с архитектурой x86 (32). Дана также аргументация выбора ассемблера GAS в сравнении с другими ассемблерами. Вторая глава посвящена программированию с использованием ассемблера GAS в операционной системе Linux. Рассмотрены следующие вопросы: 1. Особенности компиляции программ на языках высокого уровня. 2. Особенности структуры программ на языке ассемблера GAS. 3. Адресация в x86-64 и GAS. 4. Условные конструкции. 1 Набор утилит в Unix-подобных системах для работы с двоичными исполняемыми файлами. В частности, в набор входят утилиты as, ld, ar, которые будут использованы в нашей книге. 6
5. Понятие системного вызова. 6. Различные аспекты стековой памяти при программировании на ассемблере x86-64. 7. Технология интеграции языка ассемблера с языками высокого уровня. 8. Многомодульное программирование на языке ассемблера. 9. Динамические и статические библиотеки. 10. Основы программного управления файловой системой. 11. Основы доступа к динамической памяти. 12. Основы многозадачного программирования. В конце монографии представлены два приложения: обзор используемых в книге системных вызовов, полный обзор команд процессора x86-64. 7
Г ЛАВА 1. АССЕМБЛЕРЫ И ПЛАТФОРМА X86-64 1.1. Платформа x86-64 Следует отметить, что элементы 64-ого представления данных зародилось еще в 1960-е годы [31]. Еще в 1961 году IBM выпускает компьютер IBM 7030, в котором можно использовать 64-битовые операнды. Т.е. истории с 64-битовой компьютерной архитектурой уже как минимум 60 лет. В 1994 году корпорация Intel объявила о планах разработки 64-битовой архитектуры IA-642, которая основывалась на процессоре IA-323. Следует отметить, что планируемая архитектура не имела ничего общего с уже широко используемой в персональных компьютерах архитектурой x86, которая производилась Intel. Однако в 1999 году AMD разрабатывает 64-битовое расширение для x86, тем самым опередив корпорацию Intel. Расширение было названо x86-64, а в последствие AMD64. Данная разработка предполагала возможность выполнения программ в 64-разрядном режиме. Корпорация Intel вынуждена была опираться уже на существующие разработки AMD, в частности на определенный уже набор команд, и выпустила свой вариант архитектуры, называемый Intel 64 (также EMT64). Процессоры данной архитектуры могут работать в двух режимах: длинный режим (long mode) и устаревший наследуемый режим (legacy mode). Первый режим является основным с 64-битовыми базовыми регистрами и возможностью адресовать память с помощью 64-битовых адресов. Этот режим позволяет использовать 64-битовые операционные системы. Важно отметить, что в этом режиме имеется поддержка запуска 32-битовых приложений с поддержкой как в самой архитектуре x86-64, так и в 64-х битовых операционных системах. Следует отметить, что в 64битовом режиме можно использовать и 64-битовые и 32-битовые регистры. Кроме того, сам набор основных регистров процессора был увеличен с восьми до шестнадцати. Следует также отметить, что в x86-64 были удалены некоторые устаревшие возможности процессора x86. В частности, была удалена возможность сегментной адресации, сегментные регистры fs и gs остались. Был убран также режим virtual 8086 и механизм переключения задач. Впрочем, все эти рудименты остались в наследуемом режиме. 2 IA-64 является другим обозначением процессора Intel Itanium (также используется название IPF), который несовместим с платформой x86-64. 3 Совместимость между IA-32 и IA-64 весьма условна. В частности, речь идет производительности кода для IA-32, исполняемого в системе на основе IA-64. 8
В наследуемом режиме предполагается возможность выполнять команды процессора x86. Соответственно в нем можно запустить 32битовую операционную систему в полной совместимости с 32-битовыми приложениями. В этом режиме нельзя использовать 64-битовые регистры. Основные операционные системы поддерживают длинный режим x86-64: семейство ОС BSD (FreeBSD, DragonFly BSD, NetBSD, OpenBSD), операционные системы Linux, операционные системы macOS, операционная система Solaris, операционные системы Windows (Windows XP Professional x64, Windows Server 2003 x64, Windows Server 2008, Windows 7, Windows 8, Windows 10 и т.д.). Следует отметить, что между реализациями AMD64 и Intel 64 есть определенные различия, в частности на уровне набора инструкций [23-28, 32-38]. Однако эти различия важны только для разработчиков операционных систем и компиляторов. Компилятор, установленный в операционной системе, производит код, который будет корректно выполняться в данной операционной системе. Говоря о микропроцессоре, следует выделить два важных момента: 1. Размеры числовых данных, над которыми может осуществлять операции процессор. 2. Размер физической и виртуальной памяти, которую может адресовать процессор. Процессоры x86-64 в своем базовом наборе регистров могут выполнять операции над 64-битовыми операндами. Однако для данного процессора разработаны расширения (см. Приложение 2), позволяющие манипулировать и большими операндами, с размерами в 128 битов (SSE24 расширение). Разработано также расширение AVX5 с возможностью оперировать 256 битами. Что касается адресации, в настоящее время процессоры поддерживают 48-битовую адресацию для виртуальной памяти и 40-битовую адресацию для физической памяти. 1.2. Ассемблеры для платформы x86-64 Имеется несколько ассемблеров, которые могут быть использованы для платформы x86-64. Следует отметить, что ассемблеры могут отличаться не только по аппаратной платформе, но и по отношению к операционным системам. Программа, написанная для использования в одной операционной системе на кроссплатформенном ассемблере, часто с большим трудом может быть перенесена в другую операционную систему 4 SSE - Streaming SIMD Extensions (потоковые расширения SIMD), SIMD - Single instruction, multiple data — одна инструкция, много данных. 5 AVX - Advanced Vector Extensions (продвинутые векторные расширения). 9
той же аппаратной платформы. Кроме того, ассемблеры могут отличаться программным синтаксисом, особенно в части макросредств. 10