You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ARM64架构ADRP指令地址解析疑问:是否需偏移PC值

ADRP指令地址解析逻辑疑问

我正在查阅ARM64架构下ADRP指令的官方文档,对其中一处实现细节有疑问,以下通过代码示例说明:

ULONG64 uiAddr = 0xfffff80198964c08;    // 当前ADRP指令的地址
ULONG32 opcode = 0x900016d0;            // ADRP指令编码

// 校验指令合法性
if((opcode & 0x9F000000) != 0x90000000)
{
    // 非法指令
    wprintf(L"非法ADRP指令编码: 0x%X\n", opcode);
    return -1;
}

ULONG64 imm;
imm = (opcode & 0x60000000) >> 29;
imm |= (opcode & 0x00FFFFE0) >> 3;

// 是否需要执行这一步?
// uiAddr += sizeof(opcode);             // 将PC偏移指令长度

uiAddr += imm << 12;
uiAddr &= ~((0x1LL << 12) - 1);

ULONG uiReg = opcode & 0x1F;

wprintf(L"ADRP解析结果: x%u=0x%I64X\n", uiReg, uiAddr);

请问上述ADRP指令的地址解析逻辑是否正确?是否需要执行注释中的uiAddr += sizeof(opcode)步骤来偏移PC地址?


回答

1. 必须执行PC偏移步骤

是的,必须加上uiAddr += sizeof(opcode)。ARM64架构中,PC寄存器的值定义为当前指令地址 + 4(因为ARM64指令固定为4字节对齐,PC始终指向当前指令的下一条指令),而ADRP指令的地址计算正是基于这个PC值来做相对偏移的。如果跳过这一步,你会用当前指令的地址而非正确的PC值来计算,最终得到的目标地址会差4字节,导致错误。

2. 原代码的立即数解析逻辑存在错误

原代码中提取立即数的逻辑有问题:

  • ADRP的21位立即数由两部分组成:高2位来自指令的bit29-28,中间16位来自bit20-5,低3位固定为0。
  • 原代码用0x60000000掩码提取的是bit31-30,这是错误的,正确的掩码应该是0x18000000(对应bit29-28),然后右移28位得到高两位的值。

另外,ADRP的立即数是有符号数,需要做符号扩展到64位,否则处理负偏移(即目标地址在当前PC页的前序页)时会计算错误。

修正后的代码示例

ULONG64 uiAddr = 0xfffff80198964c08;    // 当前ADRP指令的地址
ULONG32 opcode = 0x900016d0;            // ADRP指令编码

// 校验指令合法性
if((opcode & 0x9F000000) != 0x90000000)
{
    wprintf(L"非法ADRP指令编码: 0x%X\n", opcode);
    return -1;
}

// 正确提取21位有符号立即数
ULONG64 imm;
// 提取bit29-28作为高2位
imm = (opcode & 0x18000000) >> 28;
// 提取bit20-5并拼接到低16位
imm |= (opcode & 0x00FFFFE0) >> 3;
// 符号扩展21位立即数到64位(处理负偏移)
if (imm & (1ULL << 20)) {
    imm |= ~((1ULL << 21) - 1);
}

// 必须偏移PC到下一条指令地址
uiAddr += sizeof(opcode);

// 计算目标地址:PC对齐到4KB页 + 立即数<<12
uiAddr &= ~((0x1LL << 12) - 1);
uiAddr += imm << 12;

ULONG uiReg = opcode & 0x1F;

wprintf(L"ADRP解析结果: x%u=0x%I64X\n", uiReg, uiAddr);

总结

  • 原代码缺少PC偏移步骤,这是核心错误,必须补上。
  • 立即数提取的掩码和移位逻辑错误,需要修正。
  • 遗漏了有符号立即数的符号扩展,否则负偏移场景下计算结果会出错。

内容的提问来源于stack exchange,提问作者c00000fd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 15:28:11