Нужна помощь, чтобы понять эти инструкции ARM - PullRequest
4 голосов
/ 27 августа 2010

Я смотрел на вывод ассемблера моего кода и мне нужна помощь с инструкциями ниже.

- // -

    0x00000fe8:    e28fc000    ....    ADR      r12,{pc}+8 ; 0xff0

    0x00000fec:    e28cca08    ....    ADD      r12,r12,#8, 20 ; #0x8000

- // -

Насколько я понимаю, первая инструкция приводит к загрузке r12 с

"{pc value} + 8", то есть

"{Адрес текущей команды в исполнении (0xfe8) плюс 2 инструкции впереди (8)} + 8"

так же, как и r12 после выполнения 1-й инструкции, загруженной с 0xff8 (0xfe8 + 8 + 8)

Также относительно 2-й инструкции -

Как рассчитать значение, добавляемое и сохраняемое в r12? (в комментарии написано, что это 0x8000, хотя я не могу понять, как это получилось)

Ответы [ 2 ]

9 голосов
/ 27 августа 2010

Первая инструкция (на самом деле псевдоинструкция) загружает относительный адрес ПК в R12. Поскольку инструкция находится по адресу 0xFE8, выражение {pc} +8 оценивается как 0xFF0. Таким образом, результатом первой инструкции является загрузка значения 0xFF0 в R12. Комментарий фактически указывает на это.

(Обратите внимание, что ADR не является реальной инструкцией ARM, ассемблер заменяет ее такой инструкцией, как ADD. Также обратите внимание, что значение этого выражения вычисляется в время сборки . Во время выполнения программы , ПК указывает впереди текущей инструкции из-за конвейера процессора. Как много впереди зависит от архитектуры (например, ARM7 и т. Д.) И режима работы (Thumb / ARM).) Я рискую дать здесь «слишком много информации» об ADR и относящихся к ПК выражениях / адресации, но это легко укусить, если вы не понимаете, что происходит за кулисами.)

Вторая инструкция (фактически читающая справа налево) фактически говорит: «возьмите константу 0x8, поверните ее вправо на 20 бит (, что равно сдвигу влево на 12 бит, 32-20 = 12 ), ДОБАВЬТЕ его в R12 (который в настоящее время содержит 0xFF0) и сохраните его в R12. " 0x8 << 12 = 0x8000, поэтому вторая инструкция приводит к тому, что R12 удерживает 0x8000 + 0xFF0 = 0x8FF0. </p>

Примечание: в своем объяснении, когда вы сказали "2 инструкции впереди", не впадайте в эту привычку, думайте о ней как о 8 байтах, а не 2 инструкциях. В инструкции написано добавить 8 байт, ничего не сказано в инструкциях. Инструкции не обязательно должны иметь длину 4 байта (например, в Thumb они составляют 2 байта; в Thumb2 это 2 байта или 4 байта, в зависимости от инструкции).

3 голосов
/ 27 августа 2010

Я с уважением не согласен с Дэном, это две инструкции впереди, именно так работает конвейер. Размер инструкции составляет либо 2 байта для большого пальца, либо 4 байта для руки, поэтому две инструкции вперед приводят либо к 4, либо к 8 байтам. Это не произвольные X байтов впереди, это две выборки команд впереди.

Большинство людей просто используют ярлыки и никогда не должны знать, как это работает. Для обработчиков исключений, если вы используете режим большого пальца, вам придется иметь дело с ним, и не все версии ARM ARM ясно представляют это, некоторые версии просто говорят, что регистр возврата содержит адрес + 8, когда они означают адрес + две инструкции (что означает 4 или 8, в зависимости от режима, который обозначен lsbit адреса), со временем ARM ARM улучшается, но в старых есть много ошибок. Большинству людей никогда не нужно знать или беспокоиться об этих двух инструкциях.

Основной ответ на ваши вопросы лежит в ARM ARM (ARM Architectural Reference Manual), в кодировке инструкций. Чтобы иметь инструкции фиксированной длины, то есть все команды режима ARM являются 32-битными, непосредственные значения должны быть весьма ограничены. Таким образом, для многих инструкций, таких как сложение, вы можете сказать только 8 «значащих бит» и несколько бит для сдвига. Таким образом, число 0x1001 не будет работать, в двоичном виде это значение 0b0001000000000001. Первый и последний ненулевые биты (значащие биты) требуют 13 бит памяти. но 0x8000 в вашем примере имеет только 1 значащий бит, так что его можно легко сохранить и сместить несколькими способами в инструкции. Для наборов команд, которые имеют инструкции переменной длины, например x86, вы можете иметь полные немедленные значения, вы можете загрузить или добавить значение 0x12345678, поскольку этот 0x12345678 не кодируется в самом основном коде операции, он следует коду операции в памяти и может иметь различные размеры для удовлетворения потребностей набора инструкций. Есть плюсы и минусы фиксированной и переменной длины, что выходит за рамки этого обсуждения. Дело в том, что ARM ARM включает в себя не только определения битовых полей, но каждая инструкция имеет псевдокод, объясняющий, как используются разные битовые поля, включая такие вещи, как pc на две выборки впереди выполняемой в настоящее время инструкции.

Относительная адресация компьютера - это не то, с чем вы обычно сталкиваетесь с ограниченными немедленными действиями, с которыми вы будете иметь дело все время, полезно знать, какие инструкции имеют какие немедленные значения. С режимом большого пальца становится труднее запомнить, какие операции разрешают, какой размер немедленно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...