为什么GCC在分配variables之前将variables移动到临时位置?
在看一些反编译的C代码时,我看到了这个:
movl -0xc(%rbp), %esi movl %esi, -0x8(%rbp)
这对应于这个C代码:
x = y;
这让我想到:gcc如何将y
移动到%esi
,然后将%esi
移动到x
而不是直接将y
移动到x
?
这是整个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)
大多数x86指令(除了某些专用指令,如movsb
)只能访问一个内存位置。 因此,从内存移动到内存需要通过两个mov
指令通过一个寄存器。
mov
指令可以通过以下方式使用:
mov mem, reg mov reg, mem mov reg, reg mov reg, imm mov mem, imm
没有mov mem, mem
。
请注意,如果您使用优化进行编译,则variables将被放置在寄存器中,所以这不会成为问题。