Этот учебник представляет собой краткое введение в программирование на языке ассемблера. Что делает это введение «мягким», так это то, что оно предполагает, что читатель уже знаком с программированием на C или C++. Мы используем эти предполагаемые знания для обратного моста к низкоуровневому ISA (архитектуре набора инструкций).
Мы обращаем внимание на очень острый момент:
Языка ассемблера не стоит бояться!Как уже упоминалось, если вы уже знакомы с C (или языками, произошедшими от C, такими как C++), эта книга начнется с того, что вы уже знаете.
Последующие главы более глубоко погружаются в уголки и тайники ARM V8 ISA и подходят для тех, кто хочет освоить богатый набор команд 64-битных процессоров ARM.
Да, абсолютно.
Программирование на языке ассемблера весьма тесно зависит от базовой аппаратной архитектуры. Операционная среда хоста играет огромную роль в определении того, как создаются программы на языке ассемблера. «Соглашение о вызовах» относится к тому, как вызываются функции и как передаются параметры.
Первоначально в этой книге изучались только соглашения ARM LINUX. Однако со временем мы разработали набор макросов, которые значительно упрощают написание кода для использования как в MacOS, так и в LINUX.
Эта ссылка приведет к их текущей копии, а также к документации. Также включены макросы, которые немного упрощают программирование.
В этой главе представлена дополнительная информация о программировании на языке ассемблера Apple Silicon.
Вы заметите, что мы напрямую используем среду выполнения C, а не выполняем системные вызовы ОС. Так, например, если мы хотим вызвать write() , мы вызываем write из ассемблера.
Эта версия write системного вызова представляет собой функцию-оболочку, встроенную в среду выполнения C (CRT), которая обрабатывает детали нижнего уровня выполнения системного вызова. Посмотрите здесь, что на самом деле происходит внутри этих функций-оболочек.
Преимущество использования оболочек CRT заключается в том, что существуют различия между дистрибутивами и архитектурами, которые маскируются с помощью оболочек CRT. Поэтому, когда вы используете оболочки, а не прямой метод выполнения системных вызовов, ваш код будет более переносимым.
Какими бы похвальными ни были проекты ARM, соглашения ARM об именах их интеллектуальной собственности ужасны. В этой книге AARCH64 и ARM V8 рассматриваются как синонимы 64-битной архитектуры набора инструкций ARM (ISA).
Очень сложно найти документацию на сайте ARM, потому что у них так много версий , так много названий одного и того же и так много документации в целом. Это действительно может сводить с ума.
В тексте мы будем предоставлять соответствующие ссылки по мере необходимости.
Вот ссылка на главную страницу набора инструкций «а».
Получить инструменты для разработки на языке ассемблера довольно просто — возможно, они у вас уже есть. Используя apt из терминала Linux, скажите:
sudo apt update
sudo apt install build-essential gdb
На компьютере Macintosh:
xcode-select --install
в терминал и следуйте указаниям. Обратите внимание, что gdb заменяется на lldb , различий которого достаточно, чтобы заставить вас плакать.
Тогда вам понадобится ваш любимый редактор. Мы сами используем vi для быстрого редактирования и Visual Studio Code для любой тяжелой работы.
Мы используем gcc , «компилятор» C. Также можно использовать g++ . На Mac также можно использовать clang .
Какой в этом смысл... использовать «компилятор» для «компиляции» языка ассемблера?
Что ж, чтобы ответить на этот вопрос, нужно понимать, что слово «компилятор» относится только к одному шагу в последовательности сборки. То, о чем мы говорим как о «компиляторе», на самом деле является зонтиком, который включает в себя:
Препроцессор, который действует на любую команду препроцессора # , например #include . Эти команды не являются частью C или C++. Скорее это команды препроцессору.
Обратите внимание, что gcc вызовет препроцессор C, если ваш файл языка ассемблера заканчивается на .S - заглавную S. Он может или не может быть вызван, если ваш файл заканчивается строчной буквой s или любым другим расширением файла в зависимости от вашей системы.
Фактический компилятор, чья работа заключается в преобразовании языков высокого уровня, таких как C и C++, в язык ассемблера.
Ассемблер, превращающий язык ассемблера в машинный код, не совсем готовый к исполнению.
И, наконец, компоновщик, который объединяет потенциально множество файлов промежуточного машинного кода (называемых объектными файлами), потенциально множество библиотечных файлов (статически связанных .dll в Windows и .a файлов в Linux). Линкер — последний шаг в этой цепочке.
Вот видео, объясняющее этот процесс.
Мы используем gcc и g++ напрямую, потому что, будучи зонтиками, они автоматизируют описанные выше шаги и автоматически связываются с CRT.
Предположим, вы реализовали main() в файле C (main.c) и хотите использовать написанный вами файл на языке ассемблера (asm.S). Это можно сделать несколькими способами.
gcc main.c asm.S
Это все, что вам нужно для минимальной сборки. Полученная программа будет записана в a.out . Все созданные промежуточные файлы будут удалены.
gcc -c main.c
gcc -c asm.S
gcc main.o asm.o
При таком использовании файлы .o остаются на диске. При использовании предыдущего метода файлы .o удаляются, даже если вы их не видите.
Предположим, main() реализована на языке ассемблера, а main.s является автономным, тогда просто:
gcc main.S
Часто вам понадобится включить отладчик gdb или lldb . Сделайте это:
gcc -g main.S
Без параметра командной строки -g ваш отладчик может работать неправильно.
Повторим: если вы хотите, чтобы gcc запускал ваш код через препроцессор C (например, для обработки #include ), назовите файлы исходного кода ассемблера с заглавной буквы S. Итак, в Linux:
gcc main.s
Не будет проходить через препроцессор C, но
gcc main.S
воля.
Чтобы понять, что «компилятор» является зонтиком, использование gcc для «компиляции» программы приводит к вызову следующего в Ubuntu, работающей на ARM:
/usr/bin/cpp
/usr/lib/gcc/aarch64-linux-gnu/11/cc1
/usr/bin/as
/usr/lib/gcc/aarch64-linux-gnu/11/collect2 which is...
/usr/bin/ld
cpp — это препроцессор C. Это универсальный инструмент, который может использоваться и в других языках (например, в C++).
cc1 — это настоящий компилятор.
as и ассемблер.
ld — компоновщик.
Вы можете понять, почему в этой книге мы по умолчанию используем команду зонтик.
Мы начнем с предоставления того, что мы называем «переходом» от C и C++ к языку ассемблера. Мы используем уже имеющиеся у вас знания для освоения новых знаний – как это круто!
| Глава | Уценка | |
|---|---|---|
| 0 | Кикстарт | Связь |
| 1 | Привет, мир | Связь |
| 2 | Если заявления | Связь |
| 3 | Петли | |
| 3а | Пока циклы | Связь |
| 3б | Для циклов | Связь |
| 3с | Реализация Продолжить | Связь |
| 3д | Реализация перерыва | Связь |
| 4 | Интерлюдии | |
| 4а | Регистры | Связь |
| 4б | Загрузка и сохранение | Связь |
| 4с | Подробнее о ldr | Связь |
| 4д | Регистр размеров | Связь |
| 4е | Шестнадцатеричный | Связь |
| 5 | switch | Связь |
| 6 | Функции | |
| 6а | Звонок и возвращение | Связь |
| 6б | Передача параметров | Связь |
| 6с | Пример вызова некоторых распространенных функций времени выполнения C | Связь |
| 7 | FizzBuzz — полная программа | Связь |
| 8 | Структуры | |
| 8а | Выравнивание | Связь |
| 8б | Определение | Связь |
| 8с | С использованием | Связь |
| 8д | Что это" | Связь |
| 9 | const | Связь |
Операции с плавающей запятой используют свои собственные инструкции и собственный набор регистров. Поэтому операции с плавающей запятой рассматриваются в отдельном разделе:
| Глава | Уценка | |
|---|---|---|
| 0 | Обзор главы | Связь |
| 1 | Что такое числа с плавающей запятой? | Связь |
| 2 | Регистры | Связь |
| 3 | Усечение и округление | Связь |
| 4 | Литералы | Связь |
| 5 | fmov | Связь |
| 6 | Поплавки половинной точности | Связь |
| 7 | NEON SIMD еще не написан | Связь |
Какой была бы книга о языке ассемблера без битовой критики?
| Глава | Уценка | |
|---|---|---|
| 1 | Битовые поля | |
| 1а | Без битовых полей | Связь |
| 1б | С битовыми полями | Связь |
| 1с | Обзор вновь описанных инструкций | Связь |
| 2 | Порядок байтов | Связь |
В этом разделе мы представляем разные материалы, включая нашу «всемирно известную лекцию» по отладке. Эту лекцию пригласили в несколько колледжей и университетов. Он предназначен для аудитории, работающей с такими языками, как C, C++ и ассемблер, но некоторые из содержащихся в нем уроков применимы ко всем языкам.
| Глава | Уценка | |
|---|---|---|
| 1 | Яблочный кремний | Связь |
| 2 | Конвергенция Apple и Linux | Связь |
| 3 | Вариадические функции | Связь |
| 4 | Под капотом: системные вызовы | Связь |
| 5 | Определение длины строковых литералов для функций C | Связь |
| 6 | Вызов языка ассемблера из Python | Связь |
| 7 | Атомарные операции | Связь |
| 8 | Таблицы переходов | Связь |
| 9 | аргв | АСМ-КОД |
| 10 | спин-блокировки | Связь |
| - | Лекция по отладке | ППТХ |
Как указано выше, набор макросов можно найти здесь.
Вот некоторые спецификации проектов, которые бросят вызов вашему растущему мастерству. Здесь очень краткие описания, представленные в алфавитном порядке.
Возможно, прежде чем заняться этим, сначала ознакомьтесь с полностью описанной программой FIZZBUZZ.
Тогда попробуйте это как свой первый проект. С некоторыми пустыми строками и комментариями он весит 35 строк.
Проект DIRENT демонстрирует, как можно использовать сложную struct на языке ассемблера.
Проект PI демонстрирует инструкции с плавающей запятой. Программа «бросает дротики в цель», вычисляя приблизительное значение PI, отслеживая, сколько дротиков «попали в цель» по сравнению с общим количеством «брошенных» дротиков.
В проекте SINE особое внимание уделяется математике и функциям с плавающей запятой.
Проект SNOW использует технологии эпохи 1970-х годов для анимации простой системы частиц. Этот проект демонстрирует разумный процесс проектирования, позволяющий разбить сложные проблемы на более простые части.
WALKIES представляет собой симпатичную небольшую анимацию, демонстрирующую цикл с некоторым разыменованием указателя.
Карьера Перри Киволовица в области компьютерных наук охватывает чуть менее пяти десятилетий. Он основал более 5 компаний, в основном связанных с оборудованием, обработкой изображений и визуальными эффектами (для кино и телевидения). Перри получил признание «Эмми» за свою работу над «Сбором», пилотным эпизодом «Вавилона 5». Позже он получил премию «Эмми» в области инженерных наук вместе со своими коллегами из SilhouetteFX, LLC. SilhouetteFX используется практически в каждом значимом кинофильме для ротоскопирования, рисования, отслеживания, реконструкции из 2D в 3D, композитинга и многого другого.
В 1996 году Перри получил премию Американской киноакадемии за научные и технические достижения за изобретение деформации и морфинга, управляемых формой. Эта техника отвечает за многие знаменитые эффекты в «Форресте Гампе», «Титанике» и «Звездных вратах».
Двадцать двадцать три года ознаменовали 19-й год обучения Перри информатике в колледже, десять лет в Университете штата Вашингтон в Мэдисоне и теперь 8+ в Карфагенском колледже.
Язык ассемблера — страсть Перри, работавшего над следующими ISA (в хронологическом порядке):
Унивак 1100
Корпорация цифрового оборудования PDP-11
Корпорация цифрового оборудования VAX-11
Моторола 68000
ARM, начиная с AARCH64
Эта работа посвящается моей жене Саре и сыновьям Яну и Эвану.
Перри создал библиотеку из около 200 программных проектов, подходящих для классов CS 1, CS 2, структур данных, сетей, операционных систем и компьютерной организации. Если издатель учебников по CS (или другого контента, связанного с CS) заинтересован в покупке библиотеки, свяжитесь с нами.
Также ознакомьтесь с «Get Off My L@wn», романом о зомби для программистов.
Вы правильно прочитали... элитный программист Дуг Хэндсман уезжает на пенсию в родной северный Висконсин своей жены Рут Энн. А потом, ну, случается апокалипсис. Облом.
Книга получила оценку 4,3 из 5 и более 70 отзывов. Это увлекательное чтение, которое практически ничего не стоит.