2

I test the code below, and wonder why that when we affect edx, the whole rdx would change? But why does the same thing not happen to dx v.s? rdx? Is that a feature? Why?

#include <stdio.h>
int main(){
    __asm__("mov $18446744073709551615, %rdx\n\t");
    __asm__("mov $1, %dx\n\t"); // 0xffffffffffff0001

    __asm__("mov $18446744073709551615, %rdx\n\t");
    __asm__("mov $1, %edx\n\t"); // 0x1
    
    __asm__("mov $18446744073709551615, %rdx\n\t");
    __asm__("xor %edx, %edx\n\t"); // 0x1
    
    __asm__("mov $18446744073709551615, %rdx\n\t");
    __asm__("xor %dx, %dx\n\t"); // 0xffffffffffff0000
}
Alex Lai
  • 33
  • 4

1 Answers1

3

In the amd64 architecture, modifying a 32 bit general purpose register clears the upper 32 bit of the corresponding 64 bit register. When modifying an 8 or 16 bit general purpose register, the other bits are instead preserved.

The purpose of this feature is to avoid having dependencies on the previous value of registers when performing the very common 32 bit operations. This is immensely useful for out-of-order CPU designs. The same was not done for 8 and 16 bit operations as these historically always had a merging behaviour; changing this would have made porting code to 64 bit mode quite a bit more difficult.

Refer to the Intel Software Development Manuals for more details.

fuz
  • 88,405
  • 25
  • 200
  • 352