ARM反汇编输出:当有两个参数而不是三个时

时间:2011-06-10 11:40:19

标签: assembly arm tracing disassembly

我正在尝试为检查练习注释反汇编块。以下是我到目前为止所做的事情:

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或19a那些指令是什么意思。只有两个参数而不是三个,所以它们如何工作?

以身作为例

19a:   3301      addne   r3, #1

到目前为止,我对此的解释是:如果不等于X,那么将Y添加到r3?什么是X和Y?我应该使用上一行的结果吗?如果是这样,它取代了哪个(标准的三个)?

布拉赫!

我愿意接受我不知道自己在做什么,完全误解了一切。

请发送帮助!

3 个答案:

答案 0 :(得分:3)

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指令设置的状态标志。

答案 1 :(得分:3)

1) TST 指令与 ANDS 基本相同,只是它不会更改第一个操作数。因此,TST r0, #1根据(r0&amp; 1)的结果设置标志。具体来说,如果结果为零,它将设置Z(零)标志,即没有设置r0的第0位。

2) IT 代表"If-Then"。它检查指示的条件,并有条件地执行最多4条以下指令。在您的示例中,您只有一条条件指令,反汇编程序通过IT指令帮助提供了NE后缀(后缀未在Thumb-2的指令本身中编码)。 NE意味着“不相等”,但在这种情况下没有比较,那么是什么给出了?诀窍是等式检查检查Z标志,因此您可以将此视为“非零”。因此,如果未设置Z标志,则执行ADD,即r0 设置了位0。

3)围绕 CMP / BNE 发生类似情况。 CMP基本上减去操作数并根据结果设置标志。在我们的例子中,如果r0等于0,它将设置Z.接下来,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中的位。

查看条件代码表以及它们检查的标志hereThis描述了标志的设置方式和时间。


编辑:我只是重新阅读您的问题,并意识到您的困惑的一个来源。像这样:

b.n     19e <mystery+0xe>

一个操作数,而不是两个。反汇编程序试图提供帮助,不仅显示绝对目标地址(19e),而且还显示它与最近符号的偏移量(神秘度为190,因此19e是神秘的+ 0xe)。

您需要意识到的另一件事是,在ARM(以及许多其他处理器)中,设置标志和使用标志通常在单独的指令中完成。这就是你首先做TST或CMP(或其他标志设置指令),然后使用条件指令,IT或条件分支的原因。

答案 2 :(得分:2)

如果你看看ARM ARM(ARM架构参考手册),它有一个关于标志的前面部分。与许多其他指令集不同,如果你看一下ARM指令,特别是ARM风格(不是拇指),每条指令的前四位都是条件位。与大多数其他处理器不同,使用arm可以有条件地执行任何指令,大多数其他处理器只允许条件分支。条件代码ne,nz,cs,nc等列在条件代码的早期部分中。因此,如果零标志清除则添加将是addne。与大多数其他处理器不同,ARM(在arm模式下)允许您选择何时销毁/写入标志。大多数其他人总是会更新添加的标志,例如,只有你添加s时才会更新,而添加不会添加。将条件执行和其他修饰符组合到指令时会变得棘手,例如它是addsne还是addnes?需要反复试验来解决问题。我会猜想addnes,但我很少使用这样的组合,我没有记住它。

如前所述,反汇编程序会创建一些不可组合的东西,输出上还有其他项目可帮助您解码指令。

看起来你正在看thumb2代码,它是ARM和拇指的frankenstein混合物。所以你将拥有一些手臂功能和一些拇指功能,至少与binutils一些令人讨厌的binutils-isms(没有一个手臂工具链可以比较)。例如,即使我们知道很多拇指指令修改标志而不是一个选项,并且反汇编程序通过添加而不是添加来显示这个,你不能使用添加r1,r2作为拇指模式,因为它抱怨,它希望你使用即使您正在修改标志,也要添加r1,r2。 ARM正在努力推动统一的arm / thumb汇编语法,这可能已经适用于他们的工具链,但必须看看gnu工具会发生什么。

因此,我不希望能够采用反汇编输出并重新组装该语法,原因有两个。额外的东西可以帮助您理解编码的特定指令。