вторник, 7 июля 2015 г.

Зачем нам нужно знать ARM ассемблер? Пример практического применения.

Этот пост, вопреки названию, не будет пространным размышлением на тему "Зачем нам нужно знать ARM ассемблер?", скорее я покажу одну практическую задачу и успешный метод применения знаний. Но для начала расскажу один из своих любимых анекдотов:

Приходит программист в библиотеку и спрашивает библиотекаря:
- Книги по программированию где?
Ему объясняют, что заканчивать предложение на вопросительном слове стилистически неправильно. Программист: - Понял! Книги по программированию где, дурья твоя башка?

Так вот, ситуаций в которых знания ARM'а нам пригодятся может быть крайне много. Например, чтобы слегка пропатчить какой-нибудь бинарник собранный для архитектуры ARM и т.п. Приведу пример из жизни, как вы уже успели заметить по моим предыдущим постам, частенько я выкладываю CWM, TWRP и другие кастомные recovery для различных устройств. Наиболее простым путем создания кастомных recovery, является портирование с аналогичной платформы. Беда в том, что для девайса с которого производилось портирование TWRP был собран с PIXEL_FORMAT_BGR_565, а для моего девайса был нужен RGB_565. При этом все остальное успешно работало. Не поднимать же сборочную платформу и не пересобирать recovery целиком из-за пары смещений в структуре fb_var_screeninfo. Но и смотреть на искаженные цвета в TWRP тоже вроде бы не хочется. Можно поступить проще. Для начала давайте разберемся, чем же отличается RGB_565 от BGR_565. Для этого заглянем в исходники TWRP, благо они доступны:

    } else if (PIXEL_FORMAT == GGL_PIXEL_FORMAT_RGB_565) {
#ifdef RECOVERY_RGB_565
  fprintf(stderr, "Pixel format: RGB_565\n");
  vi.blue.offset    = 0;
  vi.green.offset   = 5;
  vi.red.offset     = 11;
#else
        fprintf(stderr, "Pixel format: BGR_565\n");
  vi.blue.offset    = 11;
  vi.green.offset   = 5;
  vi.red.offset     = 0;

Как и следовало ожидать все отличается смещениями красного и синего цвета относительно начала структуры. Этот исходный код после сборки попадает в библиотеку libminuitwrp.so ... давайте возьмем HIEW и с помощью встроенного ARM-дизассемблера попробуем найти это место:


У меня получилось следующее. Т.е. здесь мы видим что vi.red.offset - это r4+0x20, в него как раз попадает 0 из r6 (напомним что исходный бинарник у нас собран для BGR), vi.green.offset - это r4+0x2C, туда попадает 5 из r0 и наконец - vi.blue.offset - это r4+0x38. Все что нам нужно это поменять местами 11 и 0 в red и blue. Пример такой замены приведен на картинке выше. Итого мы меняем всего 4 байта в файле libminuitwrp.so и Pixel Format BGR_565 превращается у нас в RGB_565. В результате цвета на экране отображаются корректно. Профит ;)

Комментариев нет :

Отправить комментарий