LXF158:ARM и Android:Программирование
|
|
|
» Ваши программные наработки не пропадут даром
ARM и Android: Программирование
Часть 4: Андрей Боровский берется за программирование на ассемблере ARM и пренебрегает правами root.
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
В этой, завершающей части мы прикоснемся к увлекательному миру программирования на ассемблере ARM, а также рассмотрим программу Android, которая позволит запускать программы Linux на устройствах Android, не имеющих режима root.
Начиная эту серию статей, я писал, что одной из причин для разработки программ Linux под Android может стать стремление познакомиться с особенностями процессоров ARM в сравнительно комфортных условиях. Именно этим мы теперь и займемся.
NEON!= OFF
Концепция, положенная в основу процессоров ARM, изначально выглядела очень красиво. В то время как процессоры Intel обрастали различными костылями, призванными обеспечить совместимость с предыдущими моделями и конкурентами (AMD), процессоры ARM сохраняли компактную и элегантную структуру. И хотя Intel превосходил ARM в производительности, ARM с его низкими затратами энергии и пассивным охлаждением нашел свою нишу в мире встраиваемых устройств. Второе рождение ARM пережил в нынешнюю эпоху смартфонов и других интеллектуальных мобильных устройств, которые требуют сочетания вычислительной мощи ПК и низкого энергопотребления.
Но за все приходится платить. Современные мобильные устройства насыщены графикой, видео и звуком, а для обработки всего этого в режиме реального времени требуются специальные наборы команд. И процессоры ARM, расставшись с изначальной простотой, обзавелись такими наборами. Причем, как это часто бывает в подобных случаях, введенные сначала наборы дополнительных команд оказались недостаточно удобными и функциональными, а отказаться от них было уже нельзя, так как они использовались во многих приложениях. В результате архитектура ARM, как и Intel, обладает теперь несколькими наборами команд для работы с числами с плавающей точкой и массивами данных, которые частично дублируют функции друг друга.
Если вы откроете файл /system/proc/cpuinfo (на нерутованном девайсе содержимое этого файла можно получить, например, с помощью программы Droid System Suite), то увидите перечень расширений (fastmult, vfp и дугие), поддерживаемых вашим процессором. Эти расширения похожи на расширения Intel (mmx, sse и т. д.), но, разумеется, не тождественны им. Рассматривать систему команд процессора ARM подробно мы не станем. Помимо самой документации, доступной на сайте arm.com, хорошим пособием является книга ARM System Developer’s Guide, Andrew Sloss et al. Morgan Kaufmann Publishers.
В качестве примера возможностей ARM мы рассмотрим сравнительно новое расширение, которое компания ARM рекламирует под названием NEON.
Команды NEON появились в архитектуре ARMv7 – правда, не во всех ее реализациях. Процессоры ARM Cortex A8 поддерживают NEON в обязательном порядке, тогда как в процессорах ARM Cortex A9 эта поддержка необязательна. Чипсет Nvidia Tegra 2, который до сих пор используется в некоторых планшетах Android, не поддерживает NEON, а Nvidia Tegra 3 – поддерживает. NEON представляет собой набор команд SIMD, то есть инструкций, которые способны работать с несколькими единицами данных одновременно. В отличие от реализаций SIMD в некоторых других архитектурах, для использования команд NEON процессор ARM не требуется переводить в особый режим. Инструкции NEON можно свободно смешивать с другими инструкциями ARM.
В распоряжении команд NEON 32 64-битных регистра, которые можно рассматривать также как 16 128-битных регистров. С точки зрения возможностей инструкции NEON не слишком отличаются от наборов инструкций SIMD в процессорах Intel. Это и неудивительно – ведь создавались они для решения одних и тех же задач.
Рассмотрим простой, самый простой пример. Пусть у нас есть канал стереозвука. Введем немного терминологии. Оцифрованный звук состоит из серии отсчетов [samples]. Поскольку стереозвук содержит два канала, минимальная единица звука – кадр [frame] состоит из двух отсчетов. В обычном стереопотоке отсчеты правого и левого каналов чередуются; таким образом, поток можно рассматривать как последовательность кадров. При обработке звука (например, фильтрации) бывает необходимо разделить отсчеты разных каналов, обработать их, а потом восстановить чередование.
В системе команд NEON существуют команды загрузки чередующихся данных с автоматическим обращением чередования [deinterleaving] и сохранения данных с восстановлением чередования. Мнемонические обозначения этих команд имеют вид vld* и vst*, где * – число 1, 2, 3 или 4, соответствующее порядку чередования данных. Это же число обозначает количество регистров NEON, которые должны использоваться в процессе обращения чередования. Например, при работе со стереозвуком, где мы имеем два чередующихся канала, соответствующие команды должны выглядеть как vld2 и vst2. Если бы нам нужно было обратить чередование отсчетов интенсивности цвета в потоке формата RGBA, мы бы использовали команды vld4 и vst4, при этом четыре задействованных регистра NEON содержали бы данные R, G, B и A соответственно.
На этом магия команд NEON не исчерпывается. Чередующиеся отсчеты могут иметь разную разрядность: 8, 16, 24 и 32 бита, и команды NEON позволяют учесть этот факт. Например, если нам нужно обратить чередование стереопотока аудиоданных разрядностью 16 бит, команда загрузки данных будет выглядеть так: vld2.16. После имени команды следует список регистров NEON для загрузки данных. Число этих регистров должно соответствовать выбранной команде. Например, для стереозвука эта команда может выглядеть так:
vld2.16 {d0, d1}, [r0]
Здесь d0 и d1 – регистры NEON, в которые будут загружены данные, а вместо r0 можно использовать любой обычный регистр ARM, который содержит адрес блока данных для загрузки.
Итак, в результате выполнения операции vld2 в регистры d0 и d1 загружаются отсчеты считанных кадров, соответствующие правому и левому каналам. Сколько же всего кадров было считано? Ответ на этот вопрос позволяет определить, насколько эффективно использование NEON. Регистры d* являются 64-битными. Это значит, что в каждый регистр записано по 4 16-битных отсчета, то есть всего – 4 кадра. В принципе, в инструкции vld* допускается использование 128-битных регистровы q*; в этом случае количество данных, загруженных одной инструкцией, удваивается.
Напишем функцию swap_channels, которая меняет местами каналы стерео.
swap_channels:
vld2.16 {d0, d1}, [r0]
vst2.16 {d1, d0}, [r0]
mov pc, lr
Эта функция, как вы догадались, написана на чистом ассемблере, и ее необходимо поместить в файл с расширением s. Согласно стандарту EABI, регистр r0 используется для передачи первого аргумента при вызове функции, так что из кода, написанного на C, ее следует вызывать так:
swap_channels(data);
где data – указатель на блок аудиоданных. Переставленные местами каналы записываются в ту же область памяти, где находились исходные.
Для сборки проекта с поддержкой NEON вам также понадобится внести изменения в файлы Application.mk и Android.mk. В первом файле переменной APP_ABI необходимо присвоить значение armeabi-v7a. Можно присвоить и сразу два значения: armeabi и armeabi-v7a. В этом случае ваш код будет скомпилирован в двух вариантах – с поддержкой NEON и без оной. Разумеется, это возможно только в том случае, если исходные тексты не содержат ассемблерных вставок, использующих инструкции NEON. Далее следует ввести переменную
LOCAL_ARM_MODE := NEON
И это еще не все. Допустим, что функция swap_channels сохранена в файле swapchannels.s. В таком случае в файле Android.mk в переменной LOCAL_SRC_FILES имя этого файла должно быть указано как swapchannels.s.neon (только в Android.mk, но не на диске!). Так же следует поступать и с другими модулями, в которых требуется поддержка NEON. Хотя необходимость добавлять окончания neon может показаться странной, на самом деле это весьма удобный способ отделить модули, в которых требуется поддержка NEON, от модулей, в которых она не нужна.
Root не нужен
В прошлых статях я писал о том, что для запуска программ Linux под управлением Android потребуется рутованное устройство или программный эмулятор. Но жизнь не стоит на месте, и я рад сообщить вам, что есть замечательная программа, которая позволит вам работать с устройством Android почти так же, как с любой машиной под управлением Linux, в том числе запускать программы для Linux, и все это – не требуя прав суперпользователя! Кроме того, данная программа относится к категории программ, способных разрабатывать приложения для Android на самом устройстве Android (и появление таких программ я тоже предсказывал!).
Речь идет о программе под названием Terminal IDE. На первый взгляд это название выглядит как «Уж и Еж», но не все так просто. Пакет Terminal IDE содержит весь необходимый инструментарий для сборки, отладки и запуска программ Java. Причем конечные файлы собираются не в формате APK, который требует установки, а в обычном для Java формате (правда, байт-код рассчитан на фирменную виртуальную машину Android). Впрочем, как мы с вами договорились, разработка программ Java в рамках этой серии нас не интересует, а интересует нас то, что все инструменты для работы с Java в Terminal IDE являются стандартными консольными программами (javac, java и т. д.), а, стало быть, пакету не обойтись без эмулятора терминала, который он и реализует (и делает это лучше, чем другие виденные мной программы). Кстати, если уж речь зашла об именах: программа, написанная разработчиком, назвавшимся Spartacus Rex (имеется в виду вождь восставших рабов, а не футбольная команда), заслуживает внимания в силу одного этого факта.
Помимо эмулятора терминала, мы получаем в свое распоряжение оболочку bash, набор утилит busybox, набор программ для работы с GIT и программу Midnight Commander. Кроме того, пакет обладает замечательной программистской клавиатурой (она заслуживает отдельного описания), возможностью подключаться к другим системам с помощью программ telnet и ssh, а также возможностью подключаться к устройству Android с помощью тех же telnet и ssh. В последнем случае придется использовать так называемый обратный туннель SSH – режим, в котором клиент SSH, запущенный на компьютере, может предоставлять доступ другим системам через SSH. По-моему, все вышеперечисленное уже звучит достаточно заманчиво для того, чтобы поспешить с установкой Terminal IDE в свою систему. Но главное сокровище Terminal IDE для нас – это собственная файловая система пакета, которая дает нам полный контроль над файлами, в том числе позволяет присваивать им статус исполняемых. При этом разделяемые библиотеки Android остаются видимыми для программ, работающих в этой файловой системе.
Между прочим, в руководстве пользователя Terminal IDE, которое автор программы советует прочесть не менее двух раз, прежде чем задавать вопросы ему, написано, что выполнять динамически скомпонованные программы Linux из терминала нельзя, так как динамический загрузчик Android отличается от стандартного загрузчика Linux. Мы уже знаем, как обойти данное ограничение, так что это предостережение не для нас (в качестве демонстрации запустим в Terminal IDE скомпонованную динамически программу threads, исходники которой вы найдете на диске).
Пройдя процедуру установки программы и ее настройки через стартовый экран (кстати, самые интересные опции настроек доступны в разделе настроек на стартовом экране, а не в обычном разделе настроек приложения Android), вы сможете запускать терминал (программа позволяет открыть несколько окон терминала, между которыми переключаются, «пролистывая» их на сенсорном экране). Среди набора доступных нам программ, к сожалению, нет компилятора GCC, ведь, как уже было сказано Terminal IDE предназначена для разработки программ на Java. Однако ничто не мешает нам использовать терминал для запуска программ, собранных на ПК с помощью средств ARM GCC.
Копируем исполняемый файл такой программы в одну из директорий нашего устройства, и с помощью Terminal IDE пытаемся присвоить файлу атрибут исполняемого. Ничего не происходит. Причина в том, что мы работаем не там, где надо. Чтобы получить власть над файлом программы, нам надо скопировать или переместить его в собственную файловую систему Terminal IDE. В окне терминала вводим следующую последовательность команд:
cp program ~
cd ~
chmod 777 program
./program
Здесь program – исполняемый файл программы Linux.
Для расположения собственной файловой системы Terminal IDE использует директорию /data/data/com.spartacusrex.spartacuside/files, то есть одну из тех директорий, к которым на нерутованном устройстве получить доступ с помощью обычного терминала нельзя. Terminal IDE получает доступ к этой директории как «честное» приложение Android. Таким образом, мы снова используем возможности приложений Android для того, чтобы расширить возможности приложений Linux.
С точки зрения самой программы Terminal IDE указанная директория представляется как домашняя директория пользователя (именно на нее указывает тильда при работе в bash). Внутри этой директории вы неожиданно найдете поддиректории bin и lib. Директория bin содержит все программы, которыми пользуется Terminal IDE (программы скомпонованы статически), а директория lib ничего не содержит.
В заключение отмечу, что программа весьма требовательна к объемам памяти. В хранилище приложение занимает 104 мегабайта (в моей системе это рекорд). В оперативной памяти занятый объем колеблется в районе 20 мегабайт. В этот объем, разумеется, не входят программы, запущенные из терминала, которые вообще невидимы для системы. Так что при работе с Terminal IDE на устройствах с небольшим объемом оперативной памяти следует соблюдать осторожность. Terminal IDE отнюдь не случайно является одной из тех программ, которые используют строку состояния Android для предупреждения пользователя о том, что они запущены. Кроме того, программа допускает явное завершение своей работы, а не перекладывает этот процесс на плечи Android.
Если хакеров можно в каком-то смысле сравнить с рыцарями, то курс молодого рыцаря на этом закончен. Вы владеете всем необходимым, чтобы продолжить самостоятельное изучение тонкостей механики ARM и Android для расширения возможностей этой ОС. |