代码之家  ›  专栏  ›  技术社区  ›  Charanor

为什么GCC在分配变量之前将其移动到临时位置?

  •  37
  • Charanor  · 技术社区  · 7 年前

    movl    -0xc(%rbp), %esi
    movl    %esi, -0x8(%rbp)
    

    这对应于C代码:

    x = y;
    

    这让我思考:为什么gcc会移动 y %esi 然后移动 x y 直接地


    这是完整的C和反编译代码,如果有必要的话:

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

    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)
    
    1 回复  |  直到 7 年前
        1
  •  75
  •   interjay    7 年前

    大多数x86指令(而不是一些专用指令,例如 movsb )只能访问一个内存位置。因此,从内存到内存的移动需要通过带有两个 mov

    这个 压敏电阻 指令可以以下列方式使用:

    mov mem, reg
    mov reg, mem
    mov reg, reg
    mov reg, imm
    mov mem, imm
    

    mov mem, mem .

    请注意,如果您使用优化进行编译,那么变量将放在寄存器中,这样就不会出现问题。