gpt4 book ai didi

gcc - 为什么 gcc 在 main 的开头推送 %rbx?

转载 作者:行者123 更新时间:2023-12-04 13:17:07 24 4
gpt4 key购买 nike

最新版本的 gcc 正在生成对我来说没有意义的程序集。我没有使用优化编译代码;但是,即使没有优化,此代码的某些部分也没有意义。

这是C源代码:

  #include <stdio.h>

int main()
{
int a = 1324;
int b = 5657;
int difference = 9876;
int printf_answer = 2221;

difference = a - b;

printf_answer = printf("%d + %d = %d\n", a, b, difference);

return difference;
}

它产生这个程序集:
    .file   "exampleIML-1b.c"
.section .rodata
.LC0:
.string "%d + %d = %d\n"
.text
.globl main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
pushq %rbx
subq $24, %rsp
movl $1324, -32(%rbp)
movl $5657, -28(%rbp)
movl $9876, -24(%rbp)
movl $2221, -20(%rbp)
movl -28(%rbp), %eax
movl -32(%rbp), %edx
movl %edx, %ecx
subl %eax, %ecx
movl %ecx, %eax
movl %eax, -24(%rbp)
movl $.LC0, %eax
movl -24(%rbp), %ecx
movl -28(%rbp), %edx
movl -32(%rbp), %ebx
.cfi_offset 3, -24
movl %ebx, %esi
movq %rax, %rdi
movl $0, %eax
call printf
movl %eax, -20(%rbp)
movl -24(%rbp), %eax
addq $24, %rsp
popq %rbx
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (GNU) 4.4.6 20120305 (Red Hat 4.4.6-4)"
.section .note.GNU-stack,"",@progbits

有几件事没有意义:

(1) 我们为什么要推送 %rbx? %rbx 中有什么需要保存?

(2) 为什么我们在减法之前将 %edx 移动到 %ecx?它不只是做什么 sub %eax, %edx ?

(3) 同样,为什么在存储值之前从 %ecx 移回 %eax?

(4) 编译器将变量 a 放在内存位置 -32(%rbp) 中。除非我添加错误,否则 -32(%rbp) 不是等于堆栈指针吗?不应该将所有局部变量存储在小于当前堆栈指针的值中吗?

我正在使用这个版本的 gcc:

[eos17:~/Courses/CS451/IntelMachineLanguage]$ gcc -v
使用内置规范。
目标:x86_64-redhat-linux
配置为:../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique -object --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj. jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
线程模型:posix
gcc 版本 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC)

最佳答案

GCC dictates how the stack is used. Contract between caller and callee on x86:

* after call instruction:
o %eip points at first instruction of function
o %esp+4 points at first argument
o %esp points at return address
* after ret instruction:
o %eip contains return address
o %esp points at arguments pushed by caller
o called function may have trashed arguments
o %eax contains return value (or trash if function is void)
o %ecx, %edx may be trashed
o %ebp, %ebx, %esi, %edi must contain contents from time of call
* Terminology:
o %eax, %ecx, %edx are "caller save" registers
o %ebp, %ebx, %esi, %edi are "callee save" registers

main 函数与此上下文中的任何其他函数一样。 gcc 决定使用 ebx用于中间计算,因此它保留其值。

关于gcc - 为什么 gcc 在 main 的开头推送 %rbx?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12736437/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com