arm64汇编adrp指令作用和使用举例

本文详细介绍了ARM64架构中的ADRP指令,包括其作用、计算规则和实际应用。通过实例展示了如何计算目标地址,并在C代码转化为汇编代码的过程中解释了ADRP指令如何配合其他指令实现字符串地址的存储。通过LLDB调试器验证了计算过程的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

adrp作用

adrp 寄存器,立即数,作用是把pc寄存器跟立即数按照一定规则计算后赋值给寄存器.

计算规则举例1

adrp x8,1

adrp指令是给寄存器赋值.赋值的规则是:
先把pc寄存器里的数值先按照16进制表示,后3位清零,再把adrp 右边的立即数,左移3位,也就是在末尾+3个0 .然后让2个结果相加.
例如上面的例子
pc = 0x0000000104ff6754
然后把pc后3位清零 得到0x0000000104ff6000
adrp x8,1 右边的立即数是1,左移3位,得到 0x1000
然后让0x0000000104ff6000+0x1000 = 0x0000000104ff7000
再把0x0000000104ff7000 赋值给 x8

下面是lldb的调试结果得到 x8 = 0x0000000104ff7000,跟上面分析结果一样

(lldb) re read pc
      pc = 0x0000000104ff6754  arm64Demo`test1 + 20 at ViewController.m
(lldb) si
(lldb) re read x8
      x8 = 0x0000000104ff7000  "tifier:forLocalNotification:withResponseInfo:completionHandler:"

计算规则举例2

adrp x9,0x22

pc = 0x0000000104ff6754
把pc 后3位清零 = 0x0000000104ff6000
然后把0x22左移3位 = 0x22000
0x0000000104ff6000 + 0x22000 = 0x105018000
然后把0x105018000赋值给x9

adrp的使用举例

下面c代码是给字符串赋值.

char * str = "123456";

xcode翻译成下面4行汇编代码
前3行作用是先把x8中存入"123456"的地址
第4行作用是把函数栈中的栈底指针x29(fp) -0x10的地址存入"123456"的地址值

    0x104d36740 <+16>: stur   w8, [x29, #-0x4]
    0x104d36744 <+20>: adrp   x8, 1
    0x104d36748 <+24>: add    x8, x8, #0x600            ; =0x600 
    0x104d3674c <+28>: stur   x8, [x29, #-0x10]

下面是lldb调试过程,可以看到x8被计算出字符串的地址值0x0000000104d37600,然后存入到栈中

(lldb) si
(lldb) re read x8
      x8 = 0x0000000104d37000  "ication:withResponseInfo:completionHandler:"
(lldb) si
(lldb) re read x8
      x8 = 0x0000000104d37600  "123456"
(lldb) si
(lldb) x $x29-0x10
0x16b0cce40: 00 76 d3 04 01 00 00 00 65 00 3d ba 03 00 00 00  .v......e.=.....
0x16b0cce50: b0 ce 0c 6b 01 00 00 00 0c 67 d3 04 01 00 00 00  ...k.....g......
<think>嗯,用户问的是关于“ADRP X20, #sub_150F0@PAGE”这条指令的问题。首先,我需要确认ADRP是什么,以及这条指令ARM架构中的作用ADRPARM中的一种指令,用于地址计算,通常用于加载地址的高位部分。然后,后面的操作数部分有#sub_150F0@PAGE,可能涉及到某个特定的链接器符号或者地址修饰符。 首先,ADRP指令作用是将一个地址的页对齐部分加载到寄存器中。具体来说,它会计算当前PC值的页基址,加上一个偏移量,然后将结果存入目标寄存器。这里的页大小通常是4KB,所以ADRP会处理高21位,然后左移12位,形成最终的地址基址。接着,用户可能使用ADD或LDR指令来补充低12位的偏移,以得到完整的地址。 接下来,操作数中的#sub_150F0@PAGE可能是一个符号修饰符。在ARM汇编中,特别是在macOS或iOS的上下文中,@PAGE@PAGEOFF是常见的修饰符,用于处理地址的相对偏移。@PAGE表示符号所在页的地址,而@PAGEOFF表示符号在页内的偏移。因此,ADRP X20, #sub_150F0@PAGE的作用是将sub_150F0符号所在页的基地址加载到X20寄存器中。之后,可能会有一条指令如ADD X20, X20, #sub_150F0@PAGEOFF,将页内偏移加上,得到完整的sub_150F0地址。 需要确认的是,用户可能是在反汇编代码中看到这条指令,特别是在处理位置无关代码或动态链接库时,ADRPADD的组合用于获取符号的地址。这种情况下,ADRP有助于减少指令数量,提高效率,因为直接使用LDR可能会需要更多的指令或占用更多的空间。 另外,需要注意sub_150F0可能是一个函数或数据的标签,@PAGE@PAGEOFF是链接器生成的修饰符,帮助在链接时正确计算地址。这可能涉及到ARM64架构的ABI规范,特别是在使用Mach-O格式的可执行文件时,如iOS或macOS的应用。 用户可能想了解这条指令的具体作用,或者是在调试、逆向工程中遇到它,需要理解其含义。因此,在回答时要解释ADRP作用,操作数各部分的含义,以及整个指令在程序中的用途,比如用于准备跳转到某个子程序或访问某个数据结构的地址。 还需要考虑用户可能的背景,可能是开发者或逆向工程师,对ARM汇编有一定了解,但需要更详细的解释。因此,回答需要结构清晰,逐步解释每个部分,并举例可能的后续指令,帮助用户构建完整的理解。 最后,要确保使用中文,并且避免使用Markdown格式,保持口语化,但内容准确专业。需要检查是否有语法错误,以及是否符合用户提供的系统级指令,比如数学公式的格式,但在这个问题中可能不涉及数学公式,所以主要确保LaTeX的正确使用,如果有相关符号的话。</think>ADRP指令ARM架构中用于地址计算的常见指令。这条指令的具体作用及结构分析如下: 1. **指令格式** `ADRP X20, #sub_150F0@PAGE` 这是ARM64汇编指令,包含以下关键部分: - **ADRP**:ARM64的"Address of Page"指令,用于计算目标符号所在内存页的基地址。 - **X20**:目标寄存器,存储计算结果。 - **#sub_150F0@PAGE**:符号修饰符,表示符号`sub_150F0`所在页的基地址。 2. **ADRP的工作原理** - 将当前PC(程序计数器)值与21位立即数偏移结合,计算目标地址所在页的基地址。 - 页大小为4KB(即地址低12位为0),因此ADRP计算结果为页对齐的基地址。 - 结果存入目标寄存器X20。 3. **@PAGE修饰符的作用** - `@PAGE`是链接器支持的符号修饰符,表示取符号所在页的基地址。 - 配合后续指令(如`ADD`或`LDR`)的`@PAGEOFF`修饰符,可完整定位符号地址: ```armasm ADRP X20, #sub_150F0@PAGE ; 取页基地址 ADD X20, X20, #sub_150F0@PAGEOFF ; 加页内偏移 ``` 4. **典型应用场景** - **位置无关代码(PIC)**:在动态链接库中通过相对寻址访问全局符号。 - **减少指令数量**:相比直接加载64位地址(需多条指令),ADRP+ADD组合更高效。 - **函数跳转准备**:为后续`BLR X20`等跳转指令提供目标地址。 5. **技术细节对比** | 指令类型 | 操作范围 | 典型用途 | |----------|------------------|--------------------| | ADRP | ±4GB内存范围寻址 | 获取页基地址 | | ADR | ±1MB内存范围寻址 | 小范围地址计算 | | LDR | 全64位地址加载 | 直接加载绝对地址 | **总结**:此指令用于高效计算符号`sub_150F0`所在内存页的基地址。在逆向工程中,这种模式常见于函数跳转或全局数据访问的准备工作。完整的地址解析需要结合后续的`@PAGEOFF`偏移计算指令
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值