How many bytes does it take to encode the assembly-code line "xorq, %rdx, %rdx"?

Viewed 893

It is common to find assembly-code lines of the form

xorq, %rdx, %rdx

One use for this operation is setting the register %rd to zero, exploiting the fact that x^x = 0. In C, it is the same as setting x = 0.

Another, more straightforward way to express this operation is

movq $0, %rdx

My question is, how do we calculate the number of bytes it takes to encode these two different implementations? I believe the first answer is 3 bytes, while the second requires 7 bytes.

2 Answers

You can dig the answer to questions of this type out of the x86 reference manual but it's usually much faster and easier to write a tiny test assembly program, assemble it, and then disassemble it.

$ cat > test.s <<EOF
        .text
        .globl x
x:
        xorl %edx, %edx
        xorq %rdx, %rdx
        movl $0, %edx
        movq $0, %rdx
EOF
$ as test.s -o test.o
$ objdump -d test.o

test.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 <x>:
   0:   31 d2                   xor    %edx,%edx
   2:   48 31 d2                xor    %rdx,%rdx
   5:   ba 00 00 00 00          mov    $0x0,%edx
   a:   48 c7 c2 00 00 00 00    mov    $0x0,%rdx

All four of these instructions clear RDX, because x86-64 automatically zero-extends the result of any 32-bit operation to the full width of the register. You can see from the disassembly dump that they are encoded with two, three, five, and seven bytes respectively, so your original surmise was correct.

A reason to use the longer instructions is that XOR sets the condition codes (so after xor %edx, %edx you will have ZF=1, OF=SF=PF=CF=0, and AF undefined) but MOV does not. This could matter if you were trying to fine-tune the scheduling of some hand-written assembly.

In the old days, assemblers would produce listing files showing the encoded instructions, and you could see how many bytes each instruction took. Failing that, you can put this code in some file.s:

a:  xorq  %rdx, %rdx
b:  movq $0, %rdx
c:

then assemble it with as -o file.o file.s and look at the symbols with nm file.o, which shows something like:

0000000000000000 t a
0000000000000003 t b
000000000000000a t c

from which you can see xorq %rdx, %rdx requires 316āˆ’016 = 3 bytes, and movq $0, %rdx requires a16āˆ’316 = 7 bytes.

You can also disassemble the object file with objdump -disassemble file.o or otool -tv file.o. (Commands and their switches may vary; these are current Apple tools.)

Related