Assembly 将CPU寄存器中的所有位有效设置为1
要清除所有位,您通常会看到异或eax、eax中的异或。对相反的人也有这样的把戏吗Assembly 将CPU寄存器中的所有位有效设置为1,assembly,arm,mips,x86-64,Assembly,Arm,Mips,X86 64,要清除所有位,您通常会看到异或eax、eax中的异或。对相反的人也有这样的把戏吗 我所能想到的就是用一条额外的指令来反转零。对于大多数具有固定宽度指令的体系结构,答案可能是一条无聊的单指令mov,即符号扩展或反转立即数,或mov lo/high对。e、 g.在手臂上,mvn r0,#0(不移动)。请参阅x86、ARM、ARM64和MIPS的gcc asm输出。IDK任何关于zseries asm或机器代码的信息 在ARM中,eor r0、r0、r0明显低于mov立即测试。它取决于旧值,没有特殊情
我所能想到的就是用一条额外的指令来反转零。对于大多数具有固定宽度指令的体系结构,答案可能是一条无聊的单指令
mov
,即符号扩展或反转立即数,或mov lo/high对。e、 g.在手臂上,mvn r0,#0
(不移动)。请参阅x86、ARM、ARM64和MIPS的gcc asm输出。IDK任何关于zseries asm或机器代码的信息
在ARM中,eor r0、r0、r0
明显低于mov立即测试。它取决于旧值,没有特殊情况处理。内存依赖顺序规则同样适用于大多数其他具有弱顺序内存的RISC ISA,但对于内存_顺序_消耗
(在C++11术语中)不需要障碍
x86 xor归零是一种特殊的方法,因为它的指令集长度可变。 从历史上看,8086
xor ax,ax
之所以直接快是因为它很小。由于这个习惯用法被广泛使用(归零比所有的都普遍),CPU设计人员给了它特殊的支持,现在xor eax,eax
比英特尔Sandybridge系列和其他一些CPU上的mov eax,0
更快,即使不考虑直接和间接的代码大小影响。看看我能挖掘到的微体系结构优势
如果x86有一个固定宽度的指令集,我想知道mov reg,0
是否会得到像xor调零那样多的特殊处理?也许,因为在编写low8或low16之前打破依赖关系很重要
最佳性能的标准选项:
:5个字节,使用mov eax,-1
编码。(不幸的是,没有迹象扩展mov r32、imm8)。在所有CPU上都有出色的性能。r8-r15为6字节(REX前缀)mov r32、imm32
:7个字节,使用mov-rax,-1
编码。(不是REX.W=1版本的mov r/m64,sign-extended-imm32
版本。这将是10字节eax
)。在所有CPU上都有出色的性能mov r64,imm64
节省一些代码大小的奇怪选项通常以牺牲性能为代价:
/异或eax,eax
(或dec rax
):5个字节(4个字节代表32位非rax
)。缺点:前端有两个UOP。仍然只有一个未使用的域uop用于最新Intel上的调度程序/执行单元,其中在前端处理eax
-immediate始终需要一个执行单元。(但整数ALU吞吐量很少成为可以使用任何端口的指令的瓶颈;额外的前端压力是问题所在)mov
/xor ecx,ecx
两个常量总共5个字节(6个字节用于lea eax,[rcx-1]
):保留一个单独的调零寄存器。如果您已经想要一个归零寄存器,那么这几乎没有什么坏处rax
可以在比大多数CPU上的mov r,i更少的端口上运行,但由于这是一个新依赖链的开始,CPU可以在它发出后的任何空闲执行端口周期中运行它 如果使用lea
执行第一个,使用mov reg,imm32
执行第二个,则相同的技巧适用于附近的任意两个常量。disp8的范围为-128到+127,否则需要一个lea r32,[base+disp8]
disp32
:使用或eax,-1
编码的3个字节(4个用于或r/m32符号扩展-imm8
)。缺点:错误地依赖于寄存器的旧值rax
/push-1
:3个字节。慢但小。仅推荐用于漏洞利用/代码高尔夫适用于任何sign-extended-imm8,与大多数其他产品不同 缺点:pop-rax
- 使用存储和加载执行单元,而不是ALU。(在AMD推土机系列上,只有两个整数执行管道,但解码/发布/退出吞吐量高于此值,这在极少数情况下可能是一个吞吐量优势。但在未经测试的情况下不要尝试。)
- 例如,存储/重新加载延迟意味着
在Skylake上执行后约5个周期内无法准备就绪rax
- (英特尔):将堆栈引擎置于rsp修改模式,因此下次直接读取
时,它将采用堆栈同步uop。(例如,对于rsp
,或对于添加rsp,28
)mov eax,[rsp+8]
- 存储可能在缓存中丢失,从而触发额外的内存流量。(如果没有接触长循环中的堆栈,则可能)
向量reg是不同的 将向量寄存器设置为具有pcmpeqd xmm0、xmm0的所有寄存器在大多数CPU上都是特殊情况,即依赖关系破坏(不是Silvermont/KNL),但仍然需要一个执行单元来实际写入这些寄存器
pcmpeqb/w/d/q
所有工作,但在某些CPU上q
速度较慢
对于AVX2,与ymm
等效的vpcmpeqd ymm0、ymm0、ymm0
也是最佳选择
对于没有AVX2的AVX,选择不太明确:没有一种明显的最佳方法。编译器使用:gcc更喜欢加载带有vmovdqa
的32字节常量,而较旧的clang使用128位vpcmpeqd
后跟一个交叉通道vinsertf128
来填充高半部分。较新的clang使用vxorps
将寄存器归零,然后vcmtrueps
将寄存器填充为零。这在道德上等同于vpcmpeqd
方法,但需要vxorps
来打破对先前版本寄存器和vmptrueps