I recently picked up the book xchg rax,rax. This book is fascinating to me, so I thought I would blog about my interpretations of it one page at a time. I’m not an assembler expert, but I want to get better at it. I’m not going to go over how to run the assembly, there are a lot of posts out there to get started.

A little background on the book, in case this blog series doesn’t make sense: neither does the book. The book is 63 pages of x86-64 assembly snippets. Other than the requisite copyright notices, there are no words. There is no context to each snippet, it’s up to reader to interpret them. Fun! The book is also freely available online.

The first page, 0x00 is fairly simple. It demonstrates different ways to zero a register.

The first instruction zeros the eax register:

xor      eax,eax

This is the most common way I see to zero a register. XORing any number with itself will produce zero. It offers a very compact encoding size. Almost every function prolog is zeroing registers, so it’s a task that needs to be done quite often.

The second instruction zeros the ebx/rbx register:

lea      rbx,[0]

lea, or load effective address simply loads the address zero and stores it in the destination operand, rbx. There isn’t anything better about this approach, but it’s a way you can do it.

The next one is a bit more interesting:

loop     $

The loop instruction does what it implies: it loops. The $ in this case means the current address counter. So, we’re looping to the same place, over and over again. However each time the loop executes, it decrements the ecx/rcx register. When the register reaches zero, the execution continues with the instruction after the loop instruction. It’s a very inefficient way to zero the ecx/rcx register.

The next one is bit more obvious:

mov      rdx,0

This moves the value zero into the edx/rdx register. This is a much quicker way to zero a register, but it has a higher encoding size. The zero ends up getting encoded as a 64-bit value to move into the rdx register. That’s several bytes just to zero a register.

The next is similar, too:

and      esi,0

This does a bitwise AND with the esi/rsi register (the source) and zero, and stores the result in esi/rsi. ANDing any number with zero will always produce zero.

The next one uses subtraction:

sub      edi,edi

It subtracts the edi register from itself and stores the result in the first operand, the edi register.

And finally, it ends with this:

push     0
pop      rbp

The first instruction pushes zero onto the the stack, and the second pops the value off the stack into the rbp register. This uses two whole instructions for zeroing a register, it isn’t exactly efficient.

That wraps up the first page.