我正在查看代码的汇编输出,并需要以下说明的帮助。
- // -
0x00000fe8: e28fc000 .... ADR r12,{pc}+8 ; 0xff0
0x00000fec: e28cca08 .... ADD r12,r12,#8, 20 ; #0x8000
- // -
根据我的理解,第一条指令会导致r12加载
“{pc value} + 8”即
“{当前执行指令的地址(0xfe8)加上2条指令(8)} + 8”
在第一条指令执行加载0xff8(0xfe8 + 8 + 8)
后r12也是如此关于第二条指令 -
如何计算添加并存储到r12的值? (评论说它的0x8000,虽然我无法理解它是如何得到的)
答案 0 :(得分:9)
第一条指令(实际上是伪指令)将PC相对地址加载到R12中。由于指令位于地址0xFE8,因此表达式{pc} +8的计算结果为0xFF0。因此第一条指令的结果是将值0xFF0加载到R12中。评论实际上表明了这一点。
(注意,ADR不是真正的ARM指令,汇编程序将其替换为ADD等指令。另请注意,此表达式的值是在汇编时计算的。在程序期间执行,由于处理器的流水线,PC指向当前指令的提前。未来多少取决于架构(例如ARM7等)和操作模式(Thumb / ARM) )。)我冒险在这里提供关于ADR& amp;的太多信息。 PC相对表达式/寻址,但如果您不了解幕后发生的事情,很容易被咬住。)
第二条指令(实际从右向左读)有效地说“取常数0x8,向右旋转20位(与左移12位相同,32-20 = 12 < / em>),将其添加到R12(当前保持0xFF0),并将其存储在R12中。“ 0x8&lt;&lt; 12 = 0x8000,因此第二条指令导致R12保持0x8000 + 0xFF0 = 0x8FF0。
注意:在您的解释中,当您说“提前2条指令”时,不要陷入这种习惯,将其视为8字节,而不是2条指令。该指令说添加8个字节,它没有说明任何指令。指令不一定是4个字节长(例如,在Thumb中,它们是2个字节;在Thumb2中,它们是2个字节或4个字节,具体取决于指令。)
答案 1 :(得分:3)
我恭敬地不同意丹,这是前面的两条指令,这就是管道的工作原理。指令的大小为拇指2个字节或arm 4个字节,因此前面的两个指令会导致4个或8个字节。它不是前面的任意X字节,它是前面的两个指令提取。
大多数人只会使用标签,而不必知道这是如何工作的。对于异常处理程序,如果你使用拇指模式,你将不得不处理它而不是所有版本的ARM ARM都清楚这一点,有些版本只是说返回寄存器保存地址+ 8,当它们表示地址+两条指令时(这意味着4或8,取决于地址的lsbit指示的模式),随着时间的推移ARM ARM改进,但旧的有很多错误。大多数人都不需要知道或担心前两个指令。
您的问题的主要答案在于ARM ARM(ARM架构参考手册),在指令编码中。为了具有固定长度指令,意味着所有ARM模式指令都是32位,立即值必须非常有限。所以对于像添加这样的许多指令,你只能说8个“有效位”和几个位用于移位。所以数字0x1001不起作用,二进制这个值是0b0001000000000001。第一个和最后一个非零位(有效位)需要13位存储。但是示例中的0x8000只有1个有效位,因此可以在指令中以多种方式轻松存储和移位。对于具有可变长度指令的指令集,例如x86,您可以拥有完整的immediates,您可以加载或添加值0x12345678,因为0x12345678未在主操作码本身中编码,它遵循内存中的操作码并且可以具有不同的大小满足指令集的需要。固定和可变长度的优缺点超出了本次讨论范围。虽然ARM ARM不仅包括位字段定义,但每条指令都有伪代码,解释了如何使用不同的位字段,包括pc在当前正在执行的指令之前两次取出。
pc相对寻址不是你通常会处理你将要处理的有限时间内容的东西,最好知道哪些指令具有直接的长度。使用拇指模式比使用手臂模式更难以记住哪些操作允许大小适中。