When looking at some decompiled C code I saw this:
movl -0xc(%rbp), %esi movl %esi, -0x8(%rbp)
This corresponds to this C code:
x = y;
This got me thinking: how come gcc moves y
to %esi
and then move %esi
to x
instead of just moving y
to x
directly?
This is the entire C and decompiled code, if it matters:
int main(void) { int x, y, z; while(1) { x = 0; y = 1; do { printf("%d\n", x); z = x + y; x = y; y = z; } while(x < 255); } }
pushq %rbp movq %rsp, %rbp subq $0x20, %rsp movl $0x0, -0x4(%rbp) movl $0x0, -0x8(%rbp) ; x = 0 movl $0x1, -0xc(%rbp) ; y = 1 ; printf leaq 0x56(%rip), %rdi movl -0x8(%rbp), %esi movb $0x0, %al callq 0x100000f78 ; z = x + y movl -0x8(%rbp), %esi ; x -> esi addl -0xc(%rbp), %esi ; y + esi movl %esi, -0x10(%rbp) ; z = esi ; x = y movl -0xc(%rbp), %esi movl %esi, -0x8(%rbp) ; y = z movl -0x10(%rbp), %esi movl %esi, -0xc(%rbp) movl %eax, -0x14(%rbp) ; not sure... I believe printf return value? cmpl $0xff, -0x8(%rbp) ; x < 255 jl 0x100000f3d ; do...while(x < 255) jmp 0x100000f2f ; while(1)
Most x86 instructions (other than some specialized instructions such as movsb
) can only access one memory location. Therefore a move from memory to memory requires going through a register with two mov
instructions.
The mov
instruction can be used in the following ways:
mov mem, reg mov reg, mem mov reg, reg mov reg, imm mov mem, imm
There is no mov mem, mem
.
Note that if you had compiled with optimizations, the variables would be placed in registers so this wouldn't be an issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With