在 DEC PDP-8 小型机的每个程序开始时,我没有失败地发出的第一条指令是CLA CLL
清除累加器和链接(溢出)位。
8086 系列处理器中似乎不存在这种简单的指令,我在各种技术网站上看到了很多关于最快方法的讨论,比如与自身进行异或运算。
这是否已经由处理器逻辑处理?那么在程序启动前就保证为0?
在 DEC PDP-8 小型机的每个程序开始时,我没有失败地发出的第一条指令是CLA CLL
清除累加器和链接(溢出)位。
8086 系列处理器中似乎不存在这种简单的指令,我在各种技术网站上看到了很多关于最快方法的讨论,比如与自身进行异或运算。
这是否已经由处理器逻辑处理?那么在程序启动前就保证为0?
对于 8086,清除 AX 寄存器(不是 EAX)的最快和更短的方法是发出一些执行操作的 ALU 指令。那是:
xor ax,ax ; opcode: 29 C0
或者
sub ax,ax ; opcode: 31 C0
最短,因为常规mov ax,0
需要 3 个字节:B8 00 00
,多一个字节。最快,因为xor
使用sub
3 个时钟周期。mov
使用 4 个周期。
另一方面,xor
andsub
会改变标志,而 mov 不会。有时您不介意在需要清除寄存器时更改标志,有时您不想更改标志。关于代码清除,xor/sub“技巧”广为人知,编译器确实使用它来快速清除寄存器,所以任何汇编程序员都会意识到你想要做什么。
程序启动时处理器寄存器中的内容无关紧要(x86堆栈指针除外)。如果您不喜欢寄存器中的垃圾,只需将它们设置为您喜欢的值。
这可能会在代码开头花费您全部 10 条指令。实际上,您不需要初始化您没有立即使用的寄存器,因此它只有 1 或 2 条指令。更重要的是,大多数汇编程序都比这大得多,所以没人关心。
如果您坚持,您可以通过将寄存器归零(xor reg,reg/sub reg,reg/mov reg,0)来初始化您的寄存器。
值得知道的是,处理器可以利用某些指令。在现代 Intel 芯片(不一定是 x86)上,“xor reg,reg”打破了对“reg”的管道依赖,从而实现了更快的代码,因此您应该尽可能坚持使用此类指令。
如果我们首先使用同一寄存器的 16 位部分并且想要在我们的以下说明中将访问更改为 32 位,则还建议对 32 位寄存器使用“xor reg,reg”。
例子:
LOCATION DW 3
xor eax, eax
mov ax, [LOCATION] ; first a 16 bit access to the lower part of EAX
shl eax, 2 ; following by a 32 bit access
xor 指令可以更快地执行我们的代码。我认为 movzx 指令的执行速度会较慢。
短剑
xor
并mov
做不同的事情。xor
将设置条件位并且mov
不会。如果您的目标是将寄存器设置为特定值,mov
则将清楚地传达给软件的读者。
优化汇编器有时可以安全地转换mov reg, 0
为xor reg, reg
or sub reg, reg
。
sub reg, reg
并且xor reg, reg
不一定会一直以同样快的速度执行。减法需要携带和异或不需要。携带通常以极其有效的方式实施,并且难以衡量所花费的额外时间,因此出于实际目的,人们倾向于将它们称为具有同样快速的执行。