У меня есть некоторые функции сборки, которые я портировал на 64-разрядную ARM, и они отлично работают на Android, но когда я попытался скомпилировать те же файлы в Xcode, я обнаружил, что clang использует другой синтаксис (отличный от официальная документация по ARM).
Я нашел несколько сценариев, которые конвертируют исходный файл из одного формата в другой, но это не идеальное решение (и кажется, что эти скрипты не работают, когда исходные файлы содержат препроцессор).
Можно ли просто использовать газ в Xcode или настроить clang для принятия синтаксиса газа? Если нет, где находится документация ассемблера clang?
ОБНОВЛЕНИЕ - сентябрь 2015
Кажется, что проблема решена XCode 7 (новая версия clang?): теперь я могу импортировать исходные файлы сборки, написанные для Android, и они скомпилированы без каких-либо изменений.
Позвольте использовать мой ответ в качестве общего руководства по написанию кода ARM64 на Android и iOS. для начала мы начнем с энергозависимых и энергонезависимых регистров:
X0-X7 - аргументы и возвращаемое значение (volatile)
X8 = косвенный результат (структура) (или временная рег)
X9-X15 = временный (нестабильный)
X16-X17 - регистры ввода-вступления (PLT, Linker) или temp
X18 - использование платформы (TLS)
X19-X28 - сохраненные регистры (энергонезависимые)
X29 - указатель рамки
X30 - регистр ссылок (LR)
SP - указатель стека и нуль (XZR)
V0-V7, V16-V31 - нестабильные регистры NEON и FP
V8-V15 - сохраненные регистры вызываемого абонента (энергонезависимые, используемые для temp vars компиляторами)
Далее следуют директивы ассемблера для правильного создания "сегментов" для вашего кода:
Android
.cpu generic + fp + simd
.text
для каждой функции, добавьте эти 3 строки
.section.text.MyFunctionName, "ax",% progbits
.align 2
.type MyFunctionName,% function
iOS (ничего не нужно, кроме директивы align)
.align 2
Объявление общедоступных (глобальных) ярлыков
Android
.global MyFunctionName
IOS
.globl _MyFunctionName < - отметить ведущее подчеркивание и другое написание глобальной директивы
Следующее различие заключается в получении указателя на статические данные, определенные в вашем исходном коде. Например, скажем, у вас есть таблица данных, и вы хотите загрузить регистр X0 с указателем на таблицу.
Android
adrp x0, MyDataTable
add x0, x0, #:lo12:MyDataTable
IOS
adrp x0,MyDataTable@PAGE
add x0,x0,MyDataTable@PAGEOFF
Далее синтаксис NEON. iOS позволяет добавлять информацию о размере в командную мнемонику, в то время как Android хочет видеть регистр с суффиксом размера
Android
ld1 {v0.16b}, [x0], # 16
IOS
ld1.16b {v0}, [x0], # 16
Вложенные циклы
В 32-битном ARM-коде было типично нажимать LR на стек, чтобы сохранить его, когда вам нужно вызвать функцию из функции. Поскольку инструкции NEON больше не находятся в сопроцессоре и объединены в основной набор команд Aarch64, нет никакого штрафа за перемещение данных взад и вперед. Теперь практическое сохранение X30 (LR) в неиспользуемом регистре NEON. Например:
fmov d0,x30 // preserve LR
<some code which makes function calls>
fmov x30,d0 // restore LR
Это все на данный момент. Если кто-то найдет конкретные случаи, когда есть больше различий, я добавлю их.
Вам повезло. Команда Libav поддерживает инструмент, который принимает синтаксис газа и выводит ассемблер для ассемблера Apple. Вы можете найти инструмент здесь: https://github.com/libav/gas-preprocessor/blob/master/gas-preprocessor.pl