谷歌搜索了一段时间,但我找不到任何与此有关的文件。我一直在努力学习ARM,并且一直在查看已编译的ARM汇编代码以获得我编写的一个简单的calculator.c程序,以便了解我是否能理解发生了什么。我一直看到的是这样的指示:
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语法的任何信息。有人能帮助我理解这个吗?谢谢!
答案 0 :(得分:12)
在LDR指令的第二个操作数的开头使用等号(=)表示使用LDR pseudo-instruction。该pseuo指令用于将任意32位常量值加载到具有单个指令的寄存器中,尽管ARM指令集仅支持更小范围内的立即值。
如果汇编器知道=
之后的值并且符合MOV或MVN指令的立即值的允许范围,则生成MOV或MVN指令。否则,将常量值放入文字池中,并使用PC-relative LDR instruction将值加载到寄存器中。
如果Ida在反汇编代码时生成这些LDR =指令,则它必须检测到汇编器或编译器在生成您正在查看的代码时选择了第二个选项。实际指令类似于LDR R0, loc_1234567
(或更准确地说类似LDR R0, [PC, #-1234]
),Ida正在loc_1234567
为您查找文字池中的值。
答案 1 :(得分:4)
=
通常以立即数为前缀,并指示汇编程序将常量放入附近的文字池中,并生成pc
相对内存操作数来加载它。这很有用,因为ARM指令格式没有足够的空间来存储完整的32位常量。加载不能以8位编码的常量(我认为)加上从附近的文字池转移是避免这个问题的一种有效而有效的方法。