Вывод дизассемблера ARM: когда вместо трех есть два аргумента - PullRequest
3 голосов
/ 10 июня 2011

Я пытаюсь аннотировать блок разборки для экзаменационной практики. Вот что я сделал до сих пор:

00000190 <mystery>:
190:   2300      movs    r3, #0            // move address 190 (offset 0) into r3 ?
192:   e004      b.n     19e <mystery+0xe> // if 19e then branch to mystery
194:   f010 0f01 tst.w   r0, #1  ; 0x1     // update flags to 1 in status register
198:   bf18      it      ne                // if 198 not equal to ??? then ???
19a:   3301      addne   r3, #1            // add to r3 if not equal to 19a offset 1?
19c:   1040      asrs    r0, r0, #1        // shift r0 right one spot (leave it in r0)
19e:   2800      cmp     r0, #0            // compare contents of r0 against 0 ?
1a0:   d1f8      bne.n   194 <mystery+0x4> // branch to 194 if not equal to something at line 194?
1a2:   4618      mov     r0, r3            // move r3 wholecloth into r0
1a4:   4770      bx      lr                // branch(return from the mystery function)
1a6:   bf00      nop                       // No operation

Так что мои комментарии довольно зачаточны и, вероятно, в корне неверны, но больше всего я действительно не понимаю, что означают инструкции, подобные тем, которые приведены на 190 или 19а. Есть только два аргумента вместо трех, так как они работают?

В качестве примера

19a:   3301      addne   r3, #1

Моя интерпретация этого до сих пор такова: если не равно X, то добавить Y к r3? Что такое X и Y? Должен ли я использовать результат из предыдущей строки? Если да, то какой аргумент (из стандартных трех) занимает место?

Мля!

Я готов признать, что понятия не имею, что я делаю, и полностью неверно истолковываю все.

Пожалуйста, отправьте помощь!

Ответы [ 3 ]

3 голосов
/ 10 июня 2011

1) TST инструкция в основном такая же, как ANDS , за исключением того, что она не меняет первый операнд.Итак, TST r0, #1 устанавливает флаги на основе результата (r0 & 1).В частности, он установит флаг Z (ноль), если результат был нулевым, то есть бит 0 в r0 не был установлен.

2) IT означает "If-Then«.Он проверяет указанное условие и условно выполняет до 4 следующих инструкций.В вашем примере у вас есть только одна условная инструкция, которую дизассемблер услужливо снабдил суффиксом NE из инструкции IT (суффикс не закодирован в самой инструкции для Thumb-2).NE означает «не равный», но в этом случае не было никакого сравнения, так что дает?Хитрость в том, что проверка на равенство проверяет флаг Z, так что вы можете думать об этом как о «не ноль».Таким образом, наше ADD будет выполнено в том случае, если флаг Z не был установлен, то есть r0 did установили бит 0.

3) Подобная ситуация происходит вокруг CMP / BNE .CMP в основном вычитает операнды и устанавливает флаги на основе результата.В нашем случае он установит Z, если r0 был равен 0. Затем BNE проверит флаг Z и ответвление, если он не был установлен (т. Е. R0 было не равно 0).

Преобразовав все это в псевдо-C, мы получим:

r3 = 0
goto test_loop;
loop:
  Z = (r0 & 1) == 0;
  if (!Z)
    r3 += 1;
  r0 = r0 >> 1
test_loop:
  Z = (r0 - 0) == 0;
  if (!Z) goto loop;
  r0 = r3;
  return;

Или, в «нормальном» C:

r3 = 0;
while ( r0 != 0 )
{
  if ( r0 & 1 )
    r3++;
  r0 >>= 1;
}
return r3;

Похоже, он считает биты в r0.

Посмотрите здесь для таблицы кодов условий и какие флаги они проверяют. Это описывает, как и когда устанавливаются флаги.


Редактировать : Я просто перечитал ваш вопрос и понял один источник вашего замешательства.В такой строке:

b.n     19e <mystery+0xe>

есть один операнд, а не два.Дизассемблер пытается помочь и показывает не только абсолютный адрес назначения (19e), но и его представление в виде смещения от ближайшего символа (тайна равна 190, поэтому 19e является тайна + 0xe).

Другая вещьВы должны понимать, что в ARM (и многих других процессорах) установка флагов и использование флагов обычно выполняется в отдельных инструкциях.Вот почему вы сначала выполняете TST или CMP (или другую инструкцию по установке флага), а затем используете условные инструкции, IT или условные ветви.

3 голосов
/ 10 июня 2011
190:   2300      movs    r3, #0    // assign the value 0 to R3, affecting
                                   // the status flags (the S suffix)

19a:   3301      addne   r3, #1    // add 1 to r3 IF the previous comparison was
                                   // Not Equal to 0

Суффикс ne проверяет флаги состояния, ранее установленные командой movs.

2 голосов
/ 10 июня 2011

Если вы посмотрите на ARM ARM (ARM Architectural Reference Manual), у него есть раздел ближе к передней части о флагах. В отличие от многих других наборов инструкций, если вы посмотрите на инструкции ARM, в особенности ARM, в частности (не большой палец), верхние четыре бита каждой команды являются условными битами. В отличие от большинства других процессоров, с помощью рычага вы можете условно выполнять любую инструкцию, большинство других допускают только условные переходы. Коды условий ne, nz, cs, nc и т. Д. Перечислены в этом раннем разделе кодов условий. Таким образом, добавление, если нулевой флаг очищен, было бы добавлением. Также в отличие от большинства других процессоров ARM (в режиме arm) позволяет выбирать, когда вы хотите уничтожить / записать флаги. Большинство других всегда обновляют флаги на add, например, arm делает только если вы добавляете s, add не добавляет делает. Это сложно, когда вы комбинируете условное выполнение и эти другие модификаторы в инструкции, например, это addne или addnes? это требует проб и ошибок, чтобы выяснить. Я бы предположил addnes, но я использую такие комбинации настолько редко, что не запоминаю их.

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

Похоже, вы смотрите на код thumb2, который представляет собой смесь Франкена и ARM. Таким образом, у вас будут некоторые возможности для рук и некоторые большие пальцы и, по крайней мере, с binutils некоторые раздражающие binutils-isms (больше не нужно иметь набор инструментов arm для сравнения). Например, даже если мы знаем, что многие инструкции большого пальца изменяют флаги без опции, и дизассемблер показывает это, добавляя вместо add добавление, вы не можете использовать add r1, r2 для режима thumb, поскольку он жалуется, он хочет, чтобы вы использовали добавьте r1, r2, даже если вы изменяете флаг. ARM работает над созданием единого синтаксиса сборки рука / большой палец, который, вероятно, уже работает с их цепочкой инструментов, но должен будет увидеть, что происходит с инструментами gnu.

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

...