Подтвердить что ты не робот

Почему GCC перемещает переменные во временное местоположение, прежде чем назначать их?

Если посмотреть на какой-то декомпилированный код C, я увидел это:

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

Это соответствует этому коду C:

x = y;

Это заставило меня задуматься: как происходит gcc перемещается y в %esi, а затем перемещается %esi в x вместо того, чтобы просто перемещать y в x напрямую?


Это весь 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)
4b9b3361

Ответ 1

Большинство инструкций x86 (кроме некоторых специализированных инструкций, таких как movsb) могут обращаться только к одному месту памяти. Поэтому переход из памяти в память требует прохождения через регистр с двумя инструкциями mov.

Инструкция mov может использоваться следующими способами:

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

Нет mov mem, mem.

Обратите внимание, что если вы скомпилировали с оптимизацией, переменные будут помещены в регистры, чтобы это не было проблемой.