问题描述
GCC的最新版本是生产大会,没有任何意义了我。我编不使用优化code;但是,这code的某些部分没有意义,甚至没有任何优化。
下面是C源代码:
的#include<&stdio.h中GT; 诠释的main()
{
int类型的= 1324;
INT B = 5657;
INT差= 9876;
INT printf_answer = 2221; 差值= A - B: printf_answer =的printf(%d个+%D =%d个\\ N,A,B,差); 回差;
}
它产生该组件:
.fileexampleIML-1b.c
.section伪.RODATA
.LC0:
.string%D +%D =%d个\\ N
。文本
.globl主
.TYPE为主,@function
主要:
.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
调用printf
MOVL%eax中,-20(RBP%)
MOVL -24(RBP%),%EAX
addq $ 24%RSP
popq%RBX
离开
.cfi_def_cfa 7,8
RET
.cfi_endproc
.LFE0:
.size为主,。,主
.identGCC(GNU)4.4.6 20120305(红帽4.4.6-4)
.section伪.note.GNU堆栈,,@ PROGBITS
有几件事情是没有意义的:
(1)我们为什么力推%RBX?什么是%RBX需要被拯救?
(2)我们为什么要减去前移动EDX%到%ECX?什么不只是做子%EAX,EDX%
?
(3)同样,为什么要从%ECX回到%EAX移动存储值之前?
(4)编译器投入内存位置-32(RBP%)的变量。除非我添加错了,是不是-32(RBP%)等于堆栈指针?应该不是所有的局部变量保存在值小于的当前堆栈指针?
我使用这个版本的GCC的:
[eos17:〜/课程/ CS451 / IntelMachineLanguage] $ gcc的-v
使用内置的规格。
目标:x86_64的-红帽Linux的
配置:../configure - preFIX =的/ usr --mandir =的/ usr / share / man的--infodir =的/ usr /共享/信息--with-bugurl = HTTP://bugzilla.redhat。 COM / Bugzilla的--enable-引导--enable-共享--enable-线程= POSIX --enable-检查=发行--with-系统的zlib --enable -__ cxa_atexit --disable-libunwind的异常--enable- GNU的唯一对象--enable-语言= C,C ++,objc,OBJ-C ++,JAVA,FORTRAN,ADA --enable-java的AWT = GTK --disable-DSSI --with-java主=的/ usr /lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj里,多文件--enable-java的维护者模式--with-ECJ-JAR =的/ usr /股/ JAVA /月食-ecj.jar --disable-libjava-multilib的--with-PPL --with-cloog --with调=通用--with-arch_32 = i686的--build = x86_64的-红帽Linux的
线程模型:POSIX
gcc版本4.4.6 20120305(红帽4.4.6-4)(GCC)
GCC决定堆栈的使用方式。主叫方和被叫方在x86之间的合同: *后调用指令:
在函数第一个指令的0%EIP点
0%ESP + 4点,第一个参数
0%ESP指向的返回地址
*后ret指令:
0%EIP包含返回地址
0%尤指争论点由主叫方推
Ø调用的函数可能已经丢弃参数
0%eax中包含的返回值(或垃圾,如果功能无效)
0%ECX,EDX%可丢弃
0%EBP,EBX%,%ESI,EDI%必须包含从通话时间的内容
*术语:
0%EAX,ECX%,%edx中的来电者保存寄存器
0%EBP,EBX%,%ESI,EDI%是被调用者保存寄存器
的主要功能是像在这种情况下的任何其他功能。海湾合作委员会决定使用 EBX
中间计算,所以preserves它的价值。
The latest version of gcc is producing assembly that doesn't make sense to me. I compiled the code using no optimization; but, some parts of this code don't make sense, even with no optimization.
Here is the C source:
#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;
}
It produces this assembly:
.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
Several things don't make sense:
(1) Why are we pushing %rbx? What is in %rbx that needs to be saved?
(2) Why are we moving %edx to %ecx before subtracting? What doesn't it just do sub %eax, %edx
?
(3) Similarly, why the move from %ecx back to %eax before storing the value?
(4) The compiler is putting the variable a in memory location -32(%rbp). Unless I'm adding wrong, isn't -32(%rbp) equal to the stack pointer? Shouldn't all local variables be stored at values less than the current stack pointer?
I'm using this version of gcc:
[eos17:~/Courses/CS451/IntelMachineLanguage]$ gcc -vUsing built-in specs.Target: x86_64-redhat-linuxConfigured with: ../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-linuxThread model: posixgcc version 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
The main function is like any other function in this context. gcc decided to use ebx
for intermediate calculations, so it preserves its value.
这篇关于为什么在主力开始做gcc的推%RBX?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!