- Ассемблер для Linux. Введение (книга)
- Введение
- О чем данная книга
- Разработка на ассемблере в Linux
- Системные вызовы
- Hello, World!
- Посмотрим, что внутри
- Книга «Ассемблер для Linux»
- Ассемблер для Linux
- Глава 1. Ассемблер GAS. Начало
- Глава 2. Основы программирования на языке ассемблера
- Глава 3. Команды процессора архитектуры x86-64
- Глава 4. Взаимодействие с операционной системой. Управление файлами
- Глава 5. Взаимодействие с операционной системой. Управление памятью
- Глава 6. Библиотеки и языки высокого уровня
- Глава 7. Многозадачность
- Приложения
Ассемблер для Linux. Введение (книга)
Приветствую всех на моем канале Old Programmer . Здесь много разных материалов по разным вопросам программирования.
Продолжаю публиковать книгу по ассемблеру GAS , которой занимаюсь в настоящее время. Порядок мной несколько нарушен в силу того, что и книга пишется не всегда в том порядке, в котором она будет опубликована.
Введение
Когда говорят об ассемблере (или языке ассемблера), то часто несколько преувеличивают или преуменьшают те или иные особенности этого языка программирования. В действительности, поскольку ассемблер основывается на командах процессора, то следовало бы говорить о разных языках ассемблера. Добавив сюда еще и разных производителей трансляторов, а также особенности реализации в разных операционных системах, мы получим множество ассемблеров. В нашей книге мы ограничиваем себя вполне конкретным процессором архитектуры x86-64 и вполне конкретным транслятором GAS (GNU Assembler) со своим специфическим синтаксисом. Кроме того, мы рассматриваем программирование на ассемблере для семейства операционных систем Linux. Т.о. когда мы в дальнейшем будем говорить о языке ассемблера, то будем иметь в виду вполне конкретный язык, со своим набором средств программирования, со своим вполне определенным синтаксисом и со своим набором процессорных команд.
И так, какие же крайности можно увидеть в отношении языка ассемблера.
1. Язык ассемблера очень сложен для усвоения.
2. Язык ассемблера сейчас нигде не используется.
Конечно, во введении не стоит углубляться в детали программирования, для этого есть целая книга, поэтому отвечу очень кратко.
Любой язык программирования сложен для усвоения, если собираешься достигнуть на нем достаточно высокого уровня мастерства. Язык ассемблера не сложен, он детален. И если освоить эти детали, то программировать на нем гораздо проще, чем, например, на действительно сложном языке C++. Программирование на языке ассемблера как на любом языке требует умения структурировать программу. Если научиться этому, то писать на нем не составит никакого труда.
Теперь о том, что язык ассемблера нигде не используется. В действительности все не так. Да, область применения ассемблера со времен 80-х годов прошлого века сузилась, сжалась как шагреневая кожа. Но свою нишу ассемблер занимает твердо. Это и разработка драйверов и операционных систем. Это программирование микроконтроллеров. Да, мне возразят, что все таки здесь превалирует C. Но все таки отдельные вставки на ассемблере в ядре операционных систем и в программах для микроконтроллеров неизбежны.
Но есть еще один важный аспект программирования на языке ассемблера. Эта практика дает будущему программисту глубину понимания того, как работает компьютер и операционная система. И вот это последнее может быть самая главная причина того, почему каждый профессиональный программист должен изучать основы ассемблера.
Несколько слов о выборе ассемблера, который сделал автор. Выбор происходил, в действительности в два этапа. В начале был сделан выбор операционной системы, точнее семейство операционных систем Linux. И выбор был сделан по двум причинам: 1. Расширение области использования операционной системы Linux в первую очередь в нашей стране. 2. О программировании на языке ассемблера в Linux всегда писали мало и хотелось восполнить этот недостаток.
Теперь о выборе ассемблера GAS. И здесь выбор обусловлен двумя причинами. 1. GAS является родным ассемблером для семейства операционных систем Linux. 2. Именно этот ассемблер менее всего освещался в литературе по программированию.
И так, когда я кратко объяснил свои побудительные мотивы, я приступаю к самому главному, т.е. к языку ассемблера GAS и программированию на нем.
О чем данная книга
В книгах принято объяснять для чего и для кого они предназначена, а также почему в качестве темы взята именно эта.
1. Почему я занимаюсь ассемблером? Язык ассемблера, программирование на языках низкого уровня всегда меня интересовал. Я написал несколько книг по программированию на языке ассемблера в операционной системе Windows. Мне показалось интересным написать о программировании на ассемблере в операционной системе Linux. Тем более эта операционная система становится все более популярной в нашей стране.
2. Почему в качестве ассемблера взят именно ассемблер GAS или GNU Assembler? На это есть важная причина причины: GAS является родным для всех Unix-подобных операционных систем, т.е. поддерживается в качестве одной из основных утилит, и используется для компилирования и самой операционной системы и при компиляции с использованием gcc (GNU Compiler Collection).
3. Почему в качестве главного процессора в книге рассматриваются процессоры x86-64? В первую очередь потому, что они являются основными для настольных компьютеров, используемых для профессиональной деятельности, в том числе и программистов.
4. Для кого данная книга? Я бы разделил возможных читателей данной книги на три категории: а. Будущие программисты на языке ассемблера. б. Будущие программисты. Любого программиста обогащают знания в области низкоуровневого программирования. в. Все те, кому интересно как происходит выполнение программ на низком уровне и как связана архитектура компьютера с его программным управлением.
Подписываемся на мой канал Old Programmer и пишем свои комментарии.
Разработка на ассемблере в Linux
В папке у нас будет бинарный файл fasm, который мы можем использовать для компиляции. Для удобства вы можете создать симлинк на него:
sudo ln -s /home/username/fasm/fasm /usr/local/bin
ald и shed устанавливаются не сложнее:
$ ./configure
$ make
# make install
В итоге у нас будет 3 полезных инструмента для программирования на ассемблере.
Системные вызовы
Как и большинство других операционных систем, Linux предоставляет т.н. API — набор полезных для программиста функций. В большинстве случаев вызов системной функции производится с помощью прерывания 80h. Следует отметить, что Linux используется fastcall-конвенция передачи параметров. Согласно ей параметры передаются через регистры (в windows, например, используется stdcall, где параметры передаются через стек). Номер вызываемой функции кладется в eax, а параметры в регистры:
1 / ebx
2 / ecx
3 / edx
4 / esi
5 / edi
6 / ebp
Как видите все не так сложно. Узнать номер системной функции, ее описание и параметры можно, хотя бы здесь. Возьмем, к примеру sys_exit . Как можно увидеть на той странице у нее есть один параметр — код возврата и она имеет порядковый номер 1. Таким образом мы можем вызвать ее следующим кодом:
mov eax, 1 ; 1 — номер системной функции
sub ebx, ebx ; Обнуляем регистр (можно было записать mov ebx, 0)
int 80h ; Вызываем прерывание 80h
Hello, World!
Ну что же. Писать мы ничего не будем, т.к. за нас все написано 🙂 В папке fasm/examples/elfexe есть файл hello.asm, в котором находится следующий код:
; fasm demonstration of writing simple ELF executable
format ELF executable 3
entry start
segment readable executable
mov eax,4
mov ebx,1
mov ecx,msg
mov edx,msg_size
int 0x80
mov eax,1
xor ebx,ebx
int 0x80
segment readable writeable
msg db ‘Hello world!’,0xA
msg_size = $-msg
Как видите здесь вызываются 2 системных функции — sys_write (с порядковым номером 4) и sys_exit . sys_write принимает 3 параметра — дескриптор потока вывода (1 — stdout), указатель на строку и размер строки. Сам номер функции, как уже говорилось, мы должны положить в eax. Функцию sys_exit мы уже разобрали. Скомпилировать это чудо можно так: fasm hello.asm (но не обязательно, т.к. там же, где лежит исходник, есть и бинарник).
Посмотрим, что внутри
Думаю, что самое время заглянуть в наш бинарник. Для начала воспользуемся шестнадцатеричным редактором, чтобы посмотреть что у нас получилось. Выполним команду:
Мы видим всю нашу программу, данные, elf-заголовок. Неплохо? Теперь мы посмотрим на нашу программу в отладчике. Наберем в консоли:
Нас должна поприветствовать строка с предложением ввести команду. Список команд вы можете узнать, набрав help или получить помощь по отдельной команде, набрав help command . Дизассемблировать нашу программу можно командой disassemble (или ее алиас — » d «). Вы увидете дизассемблированный листинг вашей программы. Слева — адрес, справа — сама команда, а посередине — опкод команды.
Получить дамп можно командой dump (странно, но ее нет в выводе команды help ).
Теперь попробуем поработать с командой next . Выполните ее и в ответ вам покажут значения регистров, установленные флаги, а так же адрес, опкод и дизассемблированную команду, которая должна выполниться следующей. Попробуйте выполнять команды и следите за изменением флагов и регистров. После вызова первого прерывания у вас на экране должна появиться надпись «Hello world!».
Целью данной статьи было показать основы программирования на ассемблере в linux, а не программирования на ассемблере в общем. Надеюсь, что вы подчерпнули для себя что-то полезное от сюда.
PS. Первая статья на хабре.
Книга «Ассемблер для Linux»
Добрый день на моем канале Old Programmer . Эта статья является одним из разделов канала . В ней будут помещаться ссылки на параграфы моей книги по языку ассемблера. Вообще все статьи по ассемблеру моего канала можно разделить на две части: статьи до того, как я начал писать книгу по ассемблеру и статьи — параграфы книги. Старый раздел по ассемблеру остается и по-прежнему будет пополняться, а здесь только параграфы книги, которые я пишу и правлю прямо сейчас и, которые я буду писать, еще как минимум месяца три.
Книга пишется в LibreOffice. По написанию параграфа я делаю его копию на канале. Но на этом работа не заканчивается и текст параграфов еще какое-то время будет перерабатываться и меняться. Так что не удивляйтесь если встретите еще сыроватый текст. Он потом будет доработан. А можете написать об ошибках и я с удовольствием воспользуюсь вашими замечаниями.
Ассемблер для Linux
«Я люблю сидеть низко — с низкого не так опасно падать .»
Глава 1. Ассемблер GAS. Начало
Глава 2. Основы программирования на языке ассемблера
- Ассемблер для Linux. Архитектура x86-64 для прикладного программиста. Параграф 2.1.
- GNU Assembler для Linux. Операции с ячейками памяти. Параграф 2.2.
- Ассемблер для Linux. Системные вызовы. Параграф 2.3.
- Ассемблер для Linux. Стандартный ввод-вывод. Параграф 2.4
- Числа и строки. Ассемблер. Параграф 2.5.
- Стек. Ассемблер GAS. Linux. Параграф 2.6.
- Функции в ассемблере. Параграф 2.7.
- Функции в ассемблере. Передача параметров через стек. Параграф 2.8.
- Функции в ассемблере. Передача параметров через регистры в 64-битовых системах. Параграф 2.9.
- Функции в ассемблере x86-64. Локальные переменные. Параграф 2.10.
- Функции в ассемблере x86-64. Пример полнофункциональной программа. Параграф 2.11 .
- Функции в ассемблере x86-64. Локальные переменные. Пример рекурсивной функции. Параграф 2.12.
Глава 3. Команды процессора архитектуры x86-64
Данная глава посвящена командам процессора x86-64. Мы не планировали сделать справочник команд. В нашу задачу входило показать все разнообразие множества инструкций процессора и примеры их использования.
Глава 4. Взаимодействие с операционной системой. Управление файлами
Данная глава посвящена различным аспектам взаимодействия программы на языке ассемблера и операционной системы. Естественно интерфейсом такого взаимодействия являются системные вызовы, с принципами вызова которых мы уже знакомы.
Глава 5. Взаимодействие с операционной системой. Управление памятью
В главе рассматриваются технологии и приемы управления памятью на языке ассемблера. Возможности, с помощью использования системных функции, выделение динамической памяти
Глава 6. Библиотеки и языки высокого уровня
В главе будут рассмотрены вопросы многомодульного программирования на ассемблере GAS. Объединение объектных модулей. Создание статических и динамических библиотек. Интегрирование языка ассемблера с языками высокого уровня.
Глава 7. Многозадачность
Глава посвящена многозадачности в операционных системах Linux при использовании при при написании программ ассемблера GAS.