Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does GCC move variables to a temporary location before assigning them?

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:

C

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);     } } 

Decompiled

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) 
like image 737
Charanor Avatar asked Aug 06 '17 14:08

Charanor


1 Answers

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.

like image 73
interjay Avatar answered Oct 06 '22 04:10

interjay