Odd ways to zeroing some x86_64 registers


Hi there! Here are some ways (retrocompatible instructions [1-3] and xmm) to fill registers with zero (NULL) bytes without have any zero bytes in bytecode.

Zeroing (1) %RAX at 5 bytes cost (very known indeed).

400091:    6a 01                    pushq  $0x1
400093:    58                       pop    %rax
400094:    ff c8                    dec    %eax

Zeroing (1) %RDI at 6 bytes cost.

40008b:    97                       xchg   %eax,%edi
40008c:    48 c1 c8 20              ror    $0x20,%rax
400090:    97                       xchg   %eax,%edi

Zeroing (1) %RDX at 3 bytes cost.

40008b:    92                       xchg   %eax,%edx
40008c:    48 99                    cqto

Zeroing (2) %RDX e %RAX at 5 bytes cost.

40008b:    92                       xchg   %eax,%edx
40008c:    48 99                    cqto
40008e:    52                       push   %rdx
40008f:    58                       pop    %rax

Zeroing (3) %RAX, %RDX e %RDI at 6 bytes cost (however, widely known).

40008b:    48 31 ff                 xor    %rdi,%rdi
40008e:    48 f7 e7                 mul    %rdi

Zeroing (3) %RAX, %RDX e %RDI at 9 bytes cost.

40008b:    97                       xchg   %eax,%edi
40008c:    48 c1 c8 20              ror    $0x20,%rax
400090:    f7 e7                    mul    %edi
400092:    50                       push   %rax
400093:    5f                       pop    %rdi

Zeroing (1) general-purpose reg %RDX and (all) YMM at 8 bytes cost.

400090:    c5 fc 77                 vzeroall
400093:    66 48 0f 7e c2           movq   %xmm0,%rdx

Zeroing (1) general-purpose reg %RDX and (1) %XMM0 at 9 bytes cost.

400090:    66 0f df c0              pandn  %xmm0,%xmm0
400094:    66 48 0f 7e c2           movq   %xmm0,%rdx

Zeroing (1) %RAX at 8 bytes cost.

400090:    50                       push   %rax
400091:    5a                       pop    %rdx
400092:    48 f7 d2                 not    %rdx
400095:    48 21 d0                 and    %rdx,%rax

Zeroing (1) %RDX at 6 bytes cost.

400097:    52                       push   %rdx
400098:    58                       pop    %rax
400099:    f7 d0                    not    %eax
40009b:    21 c2                    and    %eax,%edx

Update - December 23, 2015

Zeroing (1) %RDI at 9 bytes cost.

400078:    0f c2 c9 04              cmpneqps %xmm1,%xmm1
40007c:    66 48 0f 7e cf           movq   %xmm1,%rdi

Use them at will.

[1] - How NOP nearly became a non-NOP on AMD64
[2] - x86oddities
[3] - The Surprising Subtleties of Zeroing a Register


This post was written in markup language. You can find it here.

Geyslan G. Bem
Just an ordinary guy who frequently introduces bugs and still want to be paid for that. Just kidding, sometimes there are free bugs too.
               

comments powered by Disqus