For example, can we do:
movl %eax,%rdx // l means 32 bits while rdx is 64 biregister
so if we move 32 bits content of %eax to %rdx, then only the low order 32 bits of %rdx get updated?
For example, can we do:
movl %eax,%rdx // l means 32 bits while rdx is 64 biregister
so if we move 32 bits content of %eax to %rdx, then only the low order 32 bits of %rdx get updated?
There is no direct way to write to only the low 32 bits of a 64 bit GPR, but it could be emulated by clearing the low 32 bits and bitwise OR-ing the value into it:
shr rdx, 32
shl rdx, 32
or rdx, rax ; assumes top 32 bits of rax are zero
Or using a double precision shift and rotate:
shrd rdx, rax, 32
ror rdx, 32
Unfortunately this has a higher latency than the first version on most processors (except maybe Core2 and its direct ancestors), because
(this form of) the double precision shift commonly takes 3 cycles. For typical Intel processors it has a potential benefit in some situations because it takes fewer µops overall, but on AMD Zen and Intel Atom the shrd takes a handful of µops. So in general the first version should be preferred, but in specific cases there may be a reason to use the second version.
It's also possible with two overlapping stores and a load (this is slow, for example 16 cycles on Haswell due to store-forwarding fail, and even without hitting such a bad microarchitectural edge case it would not have beaten the register-only solutions):
mov [rsp], rdx
mov [rsp], eax
mov rdx, [rsp]
movl %eax,%rdx (equivalent to mov %eax,%rdx) is not a valid instruction. The valid combinations for MOV can be found in the Instruction Set Architecture reference.
There are a couple of instructions that can move from smaller registers to larger registers. You can use MOVZX for zero extension (upper bits set to 0), or MOVSX sign extension where the top most bit of the source register is copied into all the higher bits of the destination register. In 64-bit long mode if the destination of any instruction (including MOV) is a 32-bit register then the upper 32-bits of the corresponding 64-bit register are set to 0 automatically by the processor.
These examples represent valid moves available that go from smaller registers to larger registers:
movzx %al, %dx # move 8-bit register to 16-bit register. Upper 8 bits of DX set to 0
movzx %al, %edx # move 8-bit register to 32-bit register. Upper 24 bits of EDX set to 0
# Upper 32 bits of RDX also set to zero because EDX is 32-bit dest
movzx %al, %rdx # move 8-bit register to 64-bit register. Upper 56 bits of RDX set to 0
movzx %ax, %edx # move 16-bit register to 32-bit register.Upper 16 bits of EDX set to 0
# Upper 32 bits of RDX also set to zero because EDX is 32-bit dest
#movzx %eax, %rdx # This instruction doesn't exist. Use mov %eax, %edx
movsx %al, %dx # Sign extend 8-bit register to 16-bit register
movsx %al, %edx # Sign extend 8-bit register to 32-bit register
# Upper 32 bits of RDX set to ZERO because EDX is 32-bit dest
movsx %al, %rdx # Sign extend 8-bit register to 64-bit register
movsx %ax, %edx # Sign extend 16-bit register to 32-bit register
# Upper 32 bits of RDX set to ZERO because EDX is 32-bit dest
movsx %ax, %rdx # Sign extend 16-bit register to 64-bit register
movsx %eax, %rdx # Sign extend 32-bit register to 64-bit register