【问题标题】:why is there severals encodings for one instruction in ARMv7为什么ARMv7中的一条指令有多个编码
【发布时间】:2013-04-13 01:00:46
【问题描述】:

我目前正在尝试为实现 ARMv7 指令集的 ARM cortex A9 实现反汇编程序。

为此,我正在使用可以在此处下载的手册“DDI0406C_b_arm_architecture_reference_manual.pdf”(在 arm 网站上注册后):

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.set.architecture/index.html

在本手册中,在 A8.8 部分的指令详细信息中,我无​​法理解为什么一条指令有多种编码(如 A1、A2、...),这些似乎都是用 ARMv7 实现的.

另外,由于 ARM 皮质 A9 使用 thumb-2,它是否也实现了 A1/A2/... 编码,还是仅实现 T1/T2...?

我确实阅读了本手册的所有部分都与编码有关,但我仍然不明白我们如何知道程序使用哪种编码。

【问题讨论】:

  • 非常感谢大家,你们的回答都非常有用。没想到这么快就有答案了。

标签: encoding binary arm thumb instruction-set


【解决方案1】:

没有办法在指令流中真正区分 ARM 和 Thumb。您只能根据调用函数的方式来决定(如果最低位设置为 1,则为拇指,否则为手臂)。

ARM-Encoding 相当“稳定”,你只会发现少数 A1 编码,BLX 是一个给出 A2 编码的例子,但这主要是因为新的 ARM-ARM 的结构与旧的不同那些。 BL 和 BLX 是两条不同的指令,BLX 是在额外的指令空间中添加的(通常用于条件的高 4 位设置为 1111,在 v5 之前的 ARM 中意味着“从不执行”。

对于 Thumb-Encodings 它是不同的,它们有很多,因为它们必须被放置在一个更压缩的指令空间中,A6-220 页有关于如何决定一个 Thumb 指令由两个或两个组成的信息的信息只有一个半字。

【讨论】:

    【解决方案2】:

    当处理器处于 arm 模式时,Ax 编码是 arm 的,它将使用这些编码对找到的位进行解码。如果有不止一个 A1、A2,那么显然存在不同的特征或原因。这两条指令可以被认为是分开的(例如,看看 x86 中 mov 指令的过度使用,它有很多编码)。将每个编码视为单独的“指令”。

    然后是 Tx 变体,即 thumb 和 thumb2 扩展。 thumb 都是 16 位的(bl 可以被解码为两个单独的 16 位指令),它们下面的描述表示“所有 thumb 变体”或“armv4t to the present”或一些这样的语言。 thumb2 扩展都是 32 位的,前 16 位是拇指世界中未定义的指令。这些对支持它们的架构有更多限制。

    您将无法为这些处理器之一完全创建反汇编程序,原因与您不能为 x86 或许多其他处理器(全部?)做一个相同的原因。如果您假设所有指令都是一种模式(手臂或拇指或拇指+拇指2)但没有模式混合(手臂+拇指),那么您可以,因为一切都是固定的指令长度,您可以简单地反汇编所有数据和代码,您不会运行任何问题。为了反汇编混合模式,您必须基本上模拟/执行指令并遵循指令流(就像可变字长指令集反汇编器一样)来尝试找到转换,这里的问题当然是在最小负载下的多指令一个寄存器然后 bx 该寄存器,有时指令计算涉及数学,并且不能保证地址计算或加载发生在 bx 之前的指令。所以你可以做一些这样的事情,并通过反汇编程序获得很长的路要走。

    如果您使用的处理器支持/允许 thumb2,那么您在检测到 thumb 代码的入口点时会遇到可变指令长度问题。除非你已经这样做了,否则你必须遵循代码的执行来确定指令从哪里开始(基本可变指令长度反汇编的东西)。

    技术参考手册和架构参考手册的组合将告诉您该架构 (trm) 的架构和实现是否允许手臂和拇指模式。我假设 A9 支持 arm thumb 和 thumb2,所有这三个。

    cortex-m 家族是迄今为止唯一仅限于不支持手臂的家族,它们的 thumb2 变化很大,因为 cortex-m0(和 m1)是 armv6m,m3 和 m4 是 armv7m(几十个( armv6m) 对 armv7m 中的许多 thumb2 扩展的说明)。有专门针对 -m 变体的单独架构参考手册,例如 armv7-m 与 armv7-ar 手册。

    【讨论】:

    • 真的很困扰我,我不能真正正确地反汇编一个混合手臂和拇指指令的程序。但现在我想知道像 objdump 这样的著名反汇编程序是如何处理这个问题的?
    • 在某种程度上他们作弊,elf 文件可以/确实(?)包含告诉他们二进制文件的哪些部分是什么的信息,因此他们不必从数据中挑选代码,从拇指中挑选手臂,等等。大多数指令集都是可变指令长度的,所以反汇编程序总是有这个问题。 mips 和 arm 暂时缓解了固定指令长度,然后又添加了不同长度的指令集,将它们与规范混为一谈。
    • 你可以反汇编其中的大部分,但就像任何其他指令集一样,如果你只有二进制文件,那么可能会有一些你无法静态确定的东西。今天的优势是大部分代码都是编译器生成的,大部分是干净的,所以不太可能有反汇编程序陷阱。
    • 好吧,我拥有的是可执行文件,所以对我来说它与“二进制”相同,但也许我错了......因为我想我也可以使用包含在 elf 文件中的信息帮我。再次感谢您。
    【解决方案3】:

    指令的不同编码在功能上做不同的事情。

    使用不同编码的一个例子是A8.9.12 ADR

    该指令将立即数加到 PC 值上以形成 PC 相对地址,并将结果写入 目的地寄存器。

    如果指令编码为A1,则偏移量必须解释为零或正数,如果编码为A2,则偏移量为负数。

    另一个例子是A8.8.132 POP

    如果列表包含多个寄存器,则将指令汇编为编码​​ A1。如果列表只包含一个寄存器,则将指令汇编为编码​​ A2。

    我可以想象创建不同的POP 编码可能是出于性能原因创建不同的微码。

    对于您问题的第二部分,Cortex-A9 是一个 ARMv7-A 架构 CPU,它支持您指出的手册中指定的所有指令。也许你也应该阅读Cortex™-A9 Technical Reference Manual

    【讨论】:

    • 好,简洁的答案。 Nitpick:Cortex-A9 不支持架构参考手册中定义的所有指令;它不支持 VFPv4/AdvSIMDv2 和虚拟化扩展引入的那些指令。
    猜你喜欢
    • 2015-02-13
    • 2013-03-08
    • 2017-06-21
    • 1970-01-01
    • 2016-03-04
    • 1970-01-01
    • 2014-04-05
    • 2023-03-14
    • 2016-12-13
    相关资源
    最近更新 更多