NB: I normally dabble with disassembly (i.e. mnemonics) and only ever look at the raw opcodes when I can't avoid it.
I have the following line of disassembly of a Windows x64 kernel mode driver, created by IDA Pro 7.1.180227:
xor edx, edx
Now I know for a fact that this is in preparation of passing the second parameter to a function via
rdx. I also know that the intention of that code is to set said pointer argument to
Now what itches me wrong with this disassembly is that
rdx, as a superset of
edx, is used elsewhere on that exact code path to store other pointers. So in theory the upper double-word of
rdx could be "dirty".
And going by the fact that this is x64 code, I'd expect this to read
xor rdx, rdx. Why is that not how it's presented in the disassembly?
Now I understand that, as per section 3.6.1 (Table 3-4) of the Intel SDM (05/2018) the REX.W Prefix of the opcode can affect the operand size.
For this opcode neither the operand-size (66h) nor the address-size (67h) prefix are present.
So going by the Intel SDM (section "XOR—Logical Exclusive OR") I should indeed be dealing with opcode
33 /r or instruction
XOR r32, r/m32, confirming IDAs translation of the opcode. Referring to section 2.1.5 ("Addressing-Mode Encoding of ModR/M and SIB Bytes") of the Intel SDM gives us a clue as to how the operand (
D2) is encoded and so gives us, from Table 2-2 ("32-Bit Addressing Forms with the ModR/M Byte"):
EDX/DX/DL/MM2/XMM2 as operand.
However, that would mean that the "dirty" upper double-word in
rdx would not be zeroed out and thus a garbled/truncated pointer would end up being passed. Given this is kernel mode code, the consequences should be clear.
I just can't believe that the compiler would make such mistake. So what am I missing?