ARM64架构下向32位寄存器移入大数是否需拆分?
ARMv8 AArch64 32位寄存器加载大数的问题解答
是否需要拆分数值移入?
是的,你要加载的36383899(十六进制0x22B2C9B)无法通过单条mov wX, #imm指令直接加载到32位寄存器中。
ARM64的mov wX, #imm指令对立即数有严格限制:立即数必须是8位无符号数左移0/16位,或是该值的按位取反。而36383899的高低16位分别是0x22B(555)和0x2C9B(11419),都超过了8位范围,不符合单条mov指令的编码规则。
你循环范围(-50,000,000到50,000,000)内的绝大多数数值,也都无法满足上述立即数规则,因此都需要拆分数值后加载。
拆分方法
推荐使用ARM64专门设计的movz和movk指令,比你原来的lsl+orr组合更简洁高效:
- 将32位数值拆分为高16位和低16位两部分;
- 用
movz加载高16位并清零低16位; - 用
movk加载低16位并保留已加载的高16位。
以加载36383899为例:
movz w20, #0x22B, lsl #16 ; 加载高16位0x22B,低16位清零 movk w20, #0x2C9B ; 加载低16位0x2C9B,高16位保持不变
针对负数(比如-36383899),直接处理其32位补码形式即可,拆分逻辑和正数一致:
- -36383899的32位补码是
0xDD4D0365
movz w20, #0xDD4D, lsl #16 ; 加载高16位0xDD4D movk w20, #0x0365 ; 加载低16位0x0365
如果坚持使用你原来的指令组合,逻辑是将数值拆分为高16位值 <<16 | 低16位值,然后通过mov+lsl+orr实现,比如:
mov w20, #0x22B ; 加载高16位值 lsl w20, w20, #16 ; 左移16位到高位置 mov w19, #0x2C9B ; 加载低16位值 orr w20, w20, w19 ; 合并高低位
但这种方式比movz+movk多一条指令,效率更低,不推荐。
内容的提问来源于stack exchange,提问作者user16342430
相关产品推荐
相关产品推荐

