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 NULL.
The opcode is 33 D2. And cross-referencing that with the reference or looking at it in ODA yields the same as with IDA: xor edx, edx.
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.
Figures.
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?
xor r10d, r10dis not shorter thanxor r10,r10, but Silvermont only recognizes 32-bit operand size as a zeroing idiom!)