Перетяжка, Премия ТПрогер, 13.11
Перетяжка, Премия ТПрогер, 13.11
Перетяжка, Премия ТПрогер, 13.11

Как освоить ассемблер для разработчиков Swift: первые шаги

Понимание ассемблера открывает разработчикам Swift новые горизонты: от глубокого анализа производительности до отладки сложных сбоев. Эта статья рассказывает, как начать работу с ассемблером на macOS: от настройки Xcode до написания программы «Hello, Assembly!». Узнайте, как регистры и системные вызовы работают «под капотом» вашего кода.

177 открытий3К показов
Как освоить ассемблер для разработчиков Swift: первые шаги

Статья переведена с оригинала польского iOS-разработчика Артура Грачаты, который делится практическими советами по низкоуровневому программированию для улучшения навыков Swift-разработчиков.

Зачем разработчику Swift изучать ассемблер

Ассемблер — это не просто низкоуровневое программирование, а способ понять, как код на Swift или Objective-C преобразуется в инструкции процессора. Он помогает разобраться в движении данных, оптимизировать производительность и отлаживать сложные ошибки. Изучение ассемблера не требует писать целые приложения на нем, но дает уверенность и глубокое понимание работы системы. К тому же, умение работать на уровне процессора добавляет разработчику уникальности и открывает новые карьерные перспективы.

Регистры: основа работы процессора

Регистры — это быстрые ячейки памяти процессора, своего рода «рабочий стол» для данных. На архитектуре Apple Silicon (ARM64) они выполняют следующие роли:

  • x0–x7: передача аргументов и возвращаемых значений.
  • x8: регистр косвенных результатов (используется редко).
  • x9–x15: временные регистры для промежуточных вычислений.
  • x16–x17: для системных вызовов (например, указание номера вызова).
  • x18: регистр платформы, сохраняемый между вызовами.
  • x19–x28: регистры, которые нужно сохранять при вызове функций.
  • sp (x31): указатель стека, хранящий локальные данные.
  • pc: счетчик программы, указывающий на следующую инструкцию.

При выполнении системного вызова (например, для вывода текста в консоль) аргументы загружаются в регистры x0, x1 и далее, номер вызова — в x16, а команда svc 0 передает управление ядру системы.

Настройка Xcode для работы с ассемблером

Чтобы начать писать код на ассемблере, нужно настроить проект в Xcode:

  1. Откройте Xcode и создайте новый проект: File → New → Project….
  2. Выберите Command Line Tool в разделе macOS, затем нажмите Next.
  3. Назовите проект, например, HelloAsm, выберите язык C (его позже заменим) и нажмите Create.
  4. В Project Navigator удалите файл main.c.
  5. Добавьте новый пустой файл: File → New → File… → Other → Empty, назовите его main.s и нажмите Create.
  6. В настройках проекта откройте Build Phases и убедитесь, что main.s добавлен в Compile Sources.

Теперь Xcode будет компилировать файл main.s как точку входа для программы на ассемблере.

Первая программа: «Hello, Assembly!»

Рассмотрим минимальную программу, которая выводит «Hello, Assembly!» в терминал. Вот ее структура с пояснениями:

			.section    __TEXT,__text
.global     _main

_main:
    // write(fd: Int, buf: UnsafePointer<UInt8>, count: Int)
    mov         x0, #0x1                  // stdout file descriptor
    adrp        x1, msg@PAGE              // page address of msg
    add         x1, x1, msg@PAGEOFF       // offset to msg
    mov         x2, #0x11                 // length of our string
    mov         x16, #0x4                 // syscall number for write
    svc         0

    // exit(status: Int)
    mov         x0, #0x0                  // status = 0
    mov         x16, #0x1                 // syscall number for exit
    svc         #0x0

    .section    __TEXT,__cstring
msg:
    .asciz      "Hello, Assembly!\n"

		
  • .section __TEXT,__text & .global _main: указывает, что это исполняемый код, а _main — точка входа.
  • mov x0, 1: задает 1 (stdout) как первый аргумент системного вызова.
  • adrp/add: загружает адрес строки msg в регистр x1 (с учетом разбиения на страницы).
  • mov x2, #0x11: задает длину сообщения (включая символ новой строки и нулевой терминатор).
  • mov x16, #0x4: указывает номер системного вызова для записи в macOS.
  • svc 0: выполняет системный вызов, передавая управление ядру.
  • Повторение для вызова выхода.
Примечание: в коде используются шестнадцатеричные числа. Знание преобразования между десятичными, двоичными и шестнадцатеричными числами пригодится.

Сборка и запуск

Соберите и запустите проект в Xcode. При успешной компиляции в терминале появится:

Hello, Assembly!

Если вывод не появился, проверьте:

  • Файл main.s добавлен в Compile Sources.
  • Нет лишних C-файлов, которые могут переопределить main.
  • Архитектура проекта соответствует вашему оборудованию (Intel или Apple Silicon).

Что дальше

Написав первую программу на ассемблере, вы сделали шаг к пониманию работы процессора. Продолжайте изучать регистры — это упростит отладку и поможет лучше понимать, где находятся данные в вашем коде.

Следите за новыми постами
Следите за новыми постами по любимым темам
177 открытий3К показов