Мир ARM немного грязный.
Для программистов C все просто: все архитектуры ARM предлагают стандартную 32-битную модель с плоской адресацией. До тех пор, пока вы остаетесь с исходным кодом C, единственное различие, которое вы можете увидеть, - это утверждение и эффективность. Большинство процессоров ARM (даже старых моделей) могут быть как большими, так и малоподобными; выбор затем осуществляется с помощью логической платы и операционной системы. Хороший код C endian neutral: он компилируется и работает корректно, независимо от его конечности (нейтральный нейтраль конечности хорош для надежности и ремонтопригодности, но также и для производительности: не нейтральный код - это код, который обращается к тем же данным через указатели различной размеры, и это приводит к хаосу со строгими правилами псевдонимов, которые компилятор использует для оптимизации кода).
ситуация совершенно иная, если вы считаете двоичную совместимость (т.е. повторное использование кода, который был скомпилирован один раз):
- Есть несколько наборов инструкций:
- оригинальная инструкция ARM установленный с 26-битным программным счетчиком (очень старый, вряд ли встречается в настоящее время)
- набор инструкций ARM с 32-разрядным счетчиком программ (часто c alled "АРМ-код")
- набор команд Thumb (16-битные упрощенные опкоды)
- набор команд Thumb-2 (большой палец с расширениями)
Данный процессор может реализовывать несколько инструкции наборы.Новейшим процессором, который знает только ARM-код, является StrongARM, представитель ARMv4, который уже довольно старый (15 лет). ARM7TDMI (архитектура ARMv4T) знает как ARM, так и Thumb, как и почти все последующие ARM-системы, кроме Cortex-M. Код ARM и Thumb можно смешивать вместе в одном и том же приложении, при условии, что соответствующий клей будет вставлен в случае изменений конвенций; это называется взаимодействием большого пальца и может обрабатываться автоматически компилятором C.
Cortex-M0 знает только инструкции Thumb. Он знает несколько расширений, потому что в «обычных» ARM-процессорах операционная система должна использовать ARM-код (для обработки прерываний); таким образом, Cortex-M0 знает несколько вещей Thumb-for-OS. Это не имеет значения для кода приложения.
Другой Cortex-M знает только Thumb-2. Thumb-2 в основном назад совместим с Thumb, по крайней мере на уровне сборки.
- Некоторые архитектуры добавить дополнительные инструкции.
Таким образом, если какой-то код скомпилирован с переключателем компилятора говорить, что это для ARMv6, то компилятор может использовать один из нескольких инструкций с ARMv6 имеет, но не в ARMv5. Это обычная ситуация, встречающаяся практически на всех платформах: например, если вы скомпилируете код C на ПК с GCC, используя флаг -march=core2
, тогда результирующий двоичный файл может не работать на более старом процессоре Pentium.
- Есть несколько конвенций вызова.
Соглашение о вызове - это набор правил, которые определяют, как функции обмениваются параметрами и возвращаемыми значениями. Процессор знает только свои регистры и не имеет понятия о стеке. В соглашении вызовов указано, в каких параметрах регистров идет и как они закодированы (например, если есть параметр char
, он входит в младшие 8 бит регистра, но вызывающий должен очистить/подписать расширенные 24 бита , или нет ?). Он описывает структуру стека и выравнивание. Он нормализует условия выравнивания и заполнение полей структуры.
Существует два основных соглашения для ARM, называемых ATPCS (старый) и AAPCS (новый). Они отличаются друг от друга по значению значений с плавающей запятой. Для целочисленных параметров они в основном идентичны (но AAPCS требует более строгого выравнивания стека). Конечно, соглашения варьируются в зависимости от набора инструкций и наличия взаимодействия Thumb.
В некоторых случаях возможно иметь двоичный код, который соответствует как ATPCS, так и AAPCS, но это не является надежным и нет предупреждения о несоответствии. Итак, нижняя строка: вы не можете иметь истинную двоичную совместимость между системами, использующими различные соглашения о вызовах.
- Есть дополнительные сопроцессоры.
Архитектура ARM может быть дополнена дополнительными элементами, которые добавляют свои собственные инструкции к набору основных команд. FPU является таким дополнительным сопроцессором (и его очень редко встречают на практике). Другим сопроцессором является NEON, набор команд SIMD, обнаруженный на некоторых новых процессорах ARM.
Код, который использует сопроцессор, не будет работать на процессоре, который не поддерживает этот сопроцессор, если только операционная система не перехватывает соответствующие коды операций и не эмулирует сопроцессор в программном обеспечении (это более или менее то, что происходит с аргументами с плавающей запятой, когда используя соглашение о вызове ATPCS, и это slow).
Подводя итог, если у вас есть код С, то перекомпилируйте его. Не пытайтесь повторно использовать код, скомпилированный для другой архитектуры или системы.
Это на самом деле не ответить на вопрос, как спросил (который был «с точки зрения C программистом «). –
Спасибо за этот ответ. Похоже, что бинарная совместимость довольно хороша, если вы держитесь подальше от операций FP и большого пальца. –