问题描述
我的理解是 ARMv8 A64 汇编中的立即数参数可以是 12 位长.如果是这样,那为什么会有这行汇编代码:
My understanding is that immediate parameters in ARMv8 A64 assembly can be 12 bits long. If that is the case, why does this line of assembly code:
AND X12, X10, 0xFEF
产生这个错误(当用gcc编译时)
Produce this error (when compiled with gcc)
Error: immediate out of range at operand 3 -- `AND X12, X10, 0xFEF'
有趣的是,这行汇编代码编译得很好:
Interestingly enough, this line of assembly code compiles fine:
ADD X12, X10, 0xFEF
我使用的是 aarch64-linux-gnu-gcc (Linaro GCC 2014.11) 4.9.3(预发行版)
I'm using aarch64-linux-gnu-gcc (Linaro GCC 2014.11) 4.9.3 (prerelease)
推荐答案
与 A32 的灵活第二操作数"不同,A64 中没有通用的立即数格式.对于立即操作数数据处理指令(忽略像移位这样无聊和直接的指令),
Unlike A32's "flexible second operand", there is no common immediate format in A64. For immediate-operand data-processing instructions (ignoring the boring and straightforward ones like shifts),
- 算术指令(
add{s}
、sub{s}
、cmp
、cmn
)带有可选的 12 位左移的 12 位无符号立即数. - 移动指令(
movz
、movn
、movk
)采用 16 位立即数,可选择移位到任意 16 位对齐位置登记簿. - 地址计算(
adr
、adrp
)采用 21 位有符号立即数,尽管没有直接指定它的实际语法 - 要这样做,您必须诉诸汇编表达式技巧以生成适当的标签". - 逻辑指令(
and{s}
、orr
、eor
、tst
)采用位掩码立即",我不确定我什至可以解释,所以我只引用 令人难以置信的复杂定义:
- Arithmetic instructions (
add{s}
,sub{s}
,cmp
,cmn
) take a 12-bit unsigned immediate with an optional 12-bit left shift. - Move instructions (
movz
,movn
,movk
) take a 16-bit immediate optionally shifted to any 16-bit-aligned position within the register. - Address calculations (
adr
,adrp
) take a 21-bit signed immediate, although there's no actual syntax to specify it directly - to do so you'd have to resort to assembler expression trickery to generate an appropriate "label". - Logical instructions (
and{s}
,orr
,eor
,tst
) take a "bitmask immediate", which I'm not sure I can even explain, so I'll just quote the mind-bogglingly complicated definition:
这种立即数是 32 位或 64 位模式,被视为大小为 e = 2、4、8、16、32 或 64 位的相同元素的向量.每个元素包含相同的子模式:1 到 e-1 非零位的单次运行,循环 0 到 e-1 位.这种机制可以生成 5,334 个独特的 64 位模式(作为 2,667 对模式及其按位逆).
这篇关于ARMv8 A64 程序集中的立即数范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!