将寄存器设置为零的方法有多少?

时间:2011-01-28 15:30:08

标签: assembly x86 x86-16 tasm

我很好奇有多少种方法可以在x86汇编中将寄存器设置为零。使用一条指令。有人告诉我,他设法找到了至少10种方法。

我能想到的是:

xor ax,ax
mov ax, 0
and ax, 0

7 个答案:

答案 0 :(得分:12)

如果在IA32 ...

下将0移入ax,有很多可能性
    lea eax, [0]
    mov eax, 0FFFF0000h         //All constants form 0..0FFFFh << 16
    shr eax, 16                 //All constants form 16..31
    shl eax, 16                 //All constants form 16..31

也许最奇怪......:)

@movzx:
    movzx eax, byte ptr[@movzx + 6]   //Because the last byte of this instruction is 0

和...

  @movzx:
    movzx ax, byte ptr[@movzx + 7]

修改:

对于16位x86 cpu模式,未经测试......:

    lea  ax, [0]

和...

  @movzx:
    movzx ax, byte ptr cs:[@movzx + 7]   //Check if 7 is right offset

如果 ds 段寄存器不等于cs段寄存器, cs:前缀是可选的。

答案 1 :(得分:4)

还有几种可能性:

sub ax, ax

movxz, eax, ah

编辑:我应该注意movzx并非所有eax都为零 - 它只是零ah(加上无法作为寄存器访问的前16位)本身)。

至于速度最快,如果内存服务于subxor是等效的。它们比(大多数)其他人更快,因为它们很常见,CPU设计者为它们添加了特殊优化。具体而言,对于正常subxor,结果取决于寄存器中的先前值。 CPU特别识别xor-with-self和subtract-from-self,因此它知道依赖链在那里被破坏。之后的任何指令都不依赖于任何先前的值,因此它可以使用重命名寄存器并行执行上一条和后续指令。

特别是在较旧的处理器上,我们预计'mov reg,0'会因为它有额外的16位数据而变慢,大多数早期处理器(特别是8088)主要受限于它们加载流的能力从内存中 - 事实上,在8088上你可以用任何参考表完全准确地估计运行时间,并且只需要注意所涉及的字节数。对于dividiv说明,这确实有所不同,但这就是它。 OTOH,我应该闭嘴,因为8088确实对任何人都没什么兴趣(现在至少十年)。

答案 2 :(得分:3)

您可以使用LOOP $将寄存器CX设置为0。

答案 3 :(得分:1)

当然,特定情况下还有其他方法可以将寄存器设置为0:例如如果您将eax设置为正整数,则可以使用edxcdq/cltd设置为0(此技巧用于着名的24字节shellcode,出现在“不安全的编程”中例子“)。

答案 4 :(得分:1)

这个帖子已经陈旧,但还有其他一些例子。简单的:

xor eax,eax

sub eax,eax

and eax,0

lea eax,[0] ; it doesn't look "natural" in the binary

更复杂的组合:

; flip all those 1111... bits to 0000
or  eax,-1  ;  eax = 0FFFFFFFFh
not eax     ; ~eax = 0

; XOR EAX,-1 works the same as NOT EAX instruction in this case, flipping 1 bits to 0
or  eax,-1  ;  eax = 0FFFFFFFFh
xor eax,-1  ; ~eax = 0

; -1 + 1 = 0
or  eax,-1 ;  eax = 0FFFFFFFFh or signed int = -1
not eax    ;++eax = 0

答案 5 :(得分:1)

DEF CON 25 - XlogicX - Assembly Language is Too High Level

立即基数为0的AAD将始终将AH设为零,而将AL保持不变。从Intel's pseudocode出发:
AL ← (oldAL + (oldAH ∗ imm8)) AND FFH;

在asm来源中:

AAD 0         ; assemblers like NASM accept this

db 0xd5,0x00  ; others many need you to encode it manually

显然(至少在某些CPU上),bswap eax前面有66个操作数大小的前缀(即尝试对66 0F C8进行编码的bswap ax)将AX设为零。

答案 6 :(得分:0)

mov eax,0  
shl eax,32  
shr eax,32  
imul eax,0 
sub eax,eax 
xor eax,eax   
and eax,0  
andn eax,eax,eax 

loop $ ;ecx only  
pause  ;ecx only (pause="rep nop" or better="rep xchg eax,eax")

;twogether:  
push dword 0    
pop eax

or eax,0xFFFFFFFF  
not eax

xor al,al ;("mov al,0","sub al,al",...)  
movzx eax,al
...