assembly - 如何在 ARM64 mov 指令中对寄存器进行编码?
问题描述
我想了解 ARM64 mov 指令中的哪个位负责寄存器信息。我使用 clang 编译我的代码,针对 aarch64 架构。
例如,我使用以下机器代码获取此指令:
01418C52 MOVZ W1, #0x6208
查看文档“Arm Architecture Reference Manual Armv8, for Armv8-A architecture profile”页面C6-1123
Rd 是保存文档中指定的寄存器信息的字段:
是通用目的寄存器的 32 位名称,编码在“Rd”字段中。
是通用目的寄存器的 64 位名称,编码在“Rd”字段中。
使用网站armconverter,我更改了寄存器的值。
我按预期获得以下代码:
02418C52 MOVZ W2, #0x6208
左边的十六进制值(最低有效)从 0x01 变为 0x02。似乎代码是小端的,但文档是大端的。但是,如果我将寄存器的字母从 W 更改为 X,则会移动另一位。
02418CD2 MOVZ X2, #0x6208
右边的最后一个值从 0xC52 更改为 0xCD2。为什么 ?
>>> bin(0xCD2)
'0b110011010010'
>>> bin(0xC52)
'0b110001010010'
从文档中,它是字段sf中的最高有效位,负责根据立即值的大小(32b 或 64b)选择寄存器。
32-bit (sf == 0)
MOVZ <Wd>, #<imm>{, LSL #<shift>}
64-bit (sf == 1)
MOVZ <Xd>, #<imm>{, LSL #<shift>}
但是该位不在正确的位置。也许我使用了错误的文档。我想了解 32 位指令中的哪个字段负责寄存器值。
谢谢
解决方案
GNU 和 LLVM 工具做到了这一点: aarch64-linux-gnu-objdump -d
显示528c4102
4 个字节的 32 位整数解释。llvm-objdump -d 显示02 41 8c 52
原始字节序列。这两者是等价的,没有误导性。
但是https://armconverter.com/愚蠢地将其分组02418C52
(在其默认的“GDB”模式下)。这是不好的。如果你想手动编码一些 AArch64 shellcode,你会使用.long 0x528c4102
(在一个 little-endian 汇编器上,例如 x86、AArch64 或其他)来获得MOVZ W2, #0x6208
.
按照惯例,没有空格的单个数字字符串的位值从右到左增加,并表示某个宽度的单个整数值。 不是你,而是https://armconverter.com/这就是问题所在。
armconverter 有一个“GDB/LLDB”切换,可将其固定为528C4102
LLDB 模式,它称之为“大端”。但它不是“大端”字节序列,没有空格,所以它是 32 位整数值。 02418C52
是如果将 4 个字节解释为大端(与 AArch64 CPU 所做的相反)得到的整数,是对这528C4102
4 个字节的正确小端解释。
我认为 armconverter 使用“big endian”实际上意味着“在删除字节之间的空格之前字节反转”。这是对术语的脑残滥用。 同样,GNU binutils 和 LLVM 反汇编程序都正确,问题纯粹是 armconverter。
推荐阅读
- ruby-on-rails - 从 Rails 资产管道中获取未缩小的 JS
- javascript - 传单热图 - 地图未显示在正确的位置
- python - Ansible - 忽略特定单词的正则表达式
- python - 如何使用二维数组每一行的元素压缩一维数组中的每个元素?
- python - 如何使用 BeautifulSoup 中的文本获取元素的值
- javascript - 模型 A 未关联模型 B 续集错误
- azure - 在 Azure 模板存储库中,有没有办法提及 azure 任务“pythonScript”的 filePath 参数的存储库?
- angular - 离子幻灯片在重新加载页面之前不起作用
- python - 将 echo 服务器作为守护进程运行以在 python 中进行测试
- bash - 为什么“哈希/bin/ls”什么都不做?