在谷歌上搜索了一段时间,但我找不到与此相关的任何文档。 我一直在尝试学习 ARM,并一直在查看我编写的一个简单的calculator.c 程序的已编译 ARM 汇编代码,以便看看我是否能理解发生了什么。 我不断看到的是这样的说明:
LDR R3, =__stack_chk_guard__GLIBC_2.4
或
LDR R0, =aEnterOperator ; "Enter operator: "
或
LDR R0, =aSIsNotAValidOp ; "%s is not a valid operator. Enter +, -"
注意:分号后面的内容只是IDA自动添加的注释。
我的问题是,这些LDR右边的‘=’是什么意思? 在第一种情况下,它似乎是一些指示库加载的标签;在第二种和第三种情况下,“=a”似乎是 printf 的前缀。 我只是不太确定这一点,因为我在文档中找不到有关 LDR 语法的任何信息。 有人可以帮助我理解这一点吗? 谢谢你!
在 LDR 指令的第二个操作数开头使用等号 (=) 表示使用 LDR 伪指令。该伪指令用于通过一条指令将任意 32 位常量值加载到寄存器中,尽管 ARM 指令集仅支持较小范围内的立即值。
如果汇编程序已知
=
之后的值并且符合 MOV 或 MVN 指令立即值的允许范围,则生成 MOV 或 MVN 指令。否则,常量值将被放入文字池中,并使用PC相关的LDR指令将值加载到寄存器中。
如果 IDA 在反汇编代码时生成这些 LDR= 指令,那么它一定检测到汇编器或编译器在生成您正在查看的代码时选择了第二个选项。实际的指令类似于
LDR R0, loc_1234567
(或更准确地说,类似于 LDR R0, [PC, #-1234]
),IDA 正在为您在 loc_1234567
处的文字池中查找值。
=
通常以立即常量为后缀,指示汇编器将常量放入附近的文字池中,并生成pc
相对内存操作数来加载它。这很有用,因为 ARM 指令格式没有足够的空间来存储完整的 32 位常量。加载无法以 8 位编码的常量(我认为)加上从附近文字池的移位是规避此问题的有效且高效的方法。