Получите выравнивание в предварительной обработке сборки ARM

Я нахожусь в ситуации, когда мне нужно сохранить указатель на следующую инструкцию в ассемблерном коде Thumb-2. Инструкции Thumb-2 могут быть 16- и 32-битными и, таким образом, выравниваются по полуслову. Когда я использую PC в качестве исходного операнда в add, я фактически считываю выровненный по словам счетчик программ плюс 4 (то есть либо на 2, либо на 4 больше, чем текущая инструкция). Поэтому мне нужно добавить либо 0, либо 2 к текущему программному счетчику, чтобы получить адрес следующей инструкции.

Теперь я мог бы использовать .align, чтобы получить эту инструкцию на границе слова, и в этом случае я могу просто добавить 0. Однако я хотел бы не использовать nop без необходимости.

Возможно ли что-то вроде следующего?

.if alignment_of_next_instruction % 4 == 2
        add r12,pc,#2
.else
        add r12,pc,#0       @ just an example, mov would be better
.endif
        str r12,[sp,#-4]!

Причина, по которой я не могу использовать nop, заключается в том, что в некоторых случаях мне нужно получить не адрес следующей инструкции, а инструкцию после нее или даже еще одну. В этих случаях необходимо add, но нужно ли мне добавить 10 или 12 (например), зависит от выравнивания.

Если это неясно, вот как будет выглядеть .align с моим предложенным синтаксисом:

.if alignment_of_next_instruction % 4 == 2
        nop
.endif

Я ничего не могу найти в справочном руководстве ARM SDK, раздел Выражения и операторы ассемблера (5.9), но, возможно, мне следует поискать в другом месте.


person Community    schedule 19.09.2016    source источник
comment
Использование более длинной, но эквивалентной инструкции вместо заполнения с помощью NOP — известная техника для x86 (где часто можно использовать другую кодировку для точно такой же инструкции), но редко используется, потому что ассемблеры не сделают это за вас. Надеюсь, кто-то знает или хочет реализовать что-то подобное на ассемблере с открытым исходным кодом, потому что это хорошая идея для жизнеспособного синтаксиса для такого рода вещей.   -  person Peter Cordes    schedule 20.09.2016
comment
@PeterCordes Я не думаю, что существует более длинная (или более короткая) эквивалентная инструкция, эти add уже являются 32-битными, и я не вижу способа сделать их 16-битными - и в ARM это все возможные варианты. Утром я посмотрю, как выглядит исходный код as, или, возможно, напишу письмо по списку binutils.   -  person    schedule 20.09.2016
comment
Можете ли вы сделать что-то с инструкцией где-то перед добавлением, чтобы она всегда выравнивалась так, как вы хотите для mov? (Для защиты от поломки в будущем поставьте перед ним .p2align 2, чтобы вы получили NOP, если кто-то изменит код между местом, где вы создаете выравнивание, и тем, где оно необходимо. Так что на данный момент его не нужно будет заполнять, но в будущем вы получите заполнение вместо поломки. Или используйте эту условную вещь, чтобы создать ошибку времени сборки, если требование нарушено.)   -  person Peter Cordes    schedule 20.09.2016
comment
@PeterCordes хорошо, в реальном коде в некоторых случаях нам нужно хранить адрес следующей инструкции, поэтому mov не сработает. Извините, возможно, я должен был написать это в вопросе. В любом случае добавление .align уже добавит не более одного nop. Дело в том, что в тех случаях, когда add действительно необходим (нельзя заменить mov), немедленная добавленная стоимость должна быть разной в зависимости от выравнивания.   -  person    schedule 20.09.2016
comment
Я предполагаю, что есть несколько вариантов использования для запроса времени сборки текущего выравнивания. Я предложил один из них; использование альтернативных инструкций для управления выравниванием на более позднем этапе. Ваш вариант использования может быть не решен именно этим (в зависимости от того, каким вы хотите, чтобы было выравнивание каждой инструкции), поэтому он считается другим.   -  person Peter Cordes    schedule 20.09.2016
comment
@PeterCordes ах, да. В общем, то, что вы предлагаете, может быть полезным :)   -  person    schedule 20.09.2016
comment
Что не так с mov.w r12, pc? Обратите внимание, что предпосылка вопроса неверна, так как это не когда я читаю ПК, который дает выровненное по словам значение, а когда я использую ПК в качестве операнда в непосредственной инструкции add/sub (которые, по устаревшим причинам, на самом деле псевдонимы adr).   -  person Notlikethat    schedule 20.09.2016
comment
@ Не нравится, что это не работает, если смещение должно быть другим. Я добавлю это к вопросу (первоначально он был опущен, потому что я не думал, что это актуально).   -  person    schedule 20.09.2016
comment
Таким образом, 1_? Или, если вы можете использовать младший регистр вместо r12, mov.n r6, pc; add.n r6, #offset по-прежнему будет 4 байта.   -  person Notlikethat    schedule 20.09.2016
comment
@Notlikethat это возможно, но тогда мне нужна дополнительная инструкция, а я просто пытался сохранить nop. (Я не могу использовать низкий регистр)   -  person    schedule 20.09.2016


Ответы (1)


Вместо того, чтобы пытаться работать с адресами и смещениями, просто укажите вещи с точки зрения инструкций, то есть с помощью метки:

   adr r12, 1f
   ...
1: <instruction of interest>

Ассемблер и компоновщик знают, что делать.

person Notlikethat    schedule 20.09.2016
comment
Думаю, это проще всего, и я должен был это увидеть, спасибо. - person ; 20.09.2016