intel编译器编译斐波拉契数列出现的疑问,求指点!!!!

麦子粒粒香 发布于 2012/12/07 11:10
阅读 810
收藏 0
使用icc编译器编译斐波拉契数列,c代码详见下方,得到汇编代码,出现以下疑问:
1。函数入口处保护寄存器时,为何对于esi寄存器入栈两次,而出栈时却对应于esi,ecx,明明没有入栈ecx,而出栈时却多出个ecx,不知有何寓意?
2。icc生成的汇编代码中的注释很多都不知道什么意思,譬如“;2.1”“; LOE eax ebx ebp edi”“; Preds .B1.2”这些都是什么意思呢?
3。在链接时会出错,报错主要是因为生成的asm文件中的一些库文件找不到,我找到的解决办法是,将vc中的这些库手动复制到当前目录下,不过觉得这不是根本解决办法,因该与环境变量的设置有关,不过不太清楚如何修改。 
另外,使用命令行模式调用icc时,我想对于生成的汇编代码重命名,譬如:“icl -S -o fibo_111.s fibo.c”,不过在生成汇编文件时好像默认生成的是“fibo.asm”,为什么呢?

  请教大牛指点一二!

c代码:

int fibonacci(int n) 
{  if (n < 2) 
	{    
		return n;  
	}  
	return fibonacci(n - 2) + fibonacci(n - 1);
}
生成的汇编代码:

; -- Machine type PW
; mark_description "Intel(R) C++ Compiler XE for applications running on IA-32, Version 12.0.0.104 Build 20101006";
; mark_description "-S";
	.686P
 	.387
	OPTION DOTNAME
	ASSUME	CS:FLAT,DS:FLAT,SS:FLAT
_TEXT	SEGMENT  PARA PUBLIC FLAT  'CODE'
;	COMDAT _fibonacci
TXTST0:
; -- Begin  _fibonacci
; mark_begin;
IF @Version GE 800
  .MMX
ELSEIF @Version GE 612
  .MMX
  MMWORD TEXTEQU <QWORD>
ENDIF
IF @Version GE 800
  .XMM
ELSEIF @Version GE 614
  .XMM
  XMMWORD TEXTEQU <OWORD>
ENDIF
       ALIGN     16
	PUBLIC _fibonacci
_fibonacci	PROC NEAR 
; parameter 1: eax
.B1.1:                          ; Preds .B1.0
        mov       eax, DWORD PTR [4+esp]                        ;2.1
	PUBLIC _fibonacci.
_fibonacci.::
        push      esi                                           ;2.1
        push      ebp                                           ;2.1
        push      esi                                           ;2.1
        mov       ebp, eax                                      ;2.1
        cmp       ebp, 2                                        ;2.12
        jl        .B1.3         ; Prob 5%                       ;2.12
                                ; LOE ebx ebp edi
.B1.2:                          ; Preds .B1.1
        lea       eax, DWORD PTR [-2+ebp]                       ;6.23
        call      _fibonacci.                                   ;6.9
                                ; LOE eax ebx ebp edi
.B1.8:                          ; Preds .B1.2
        dec       ebp                                           ;6.42
        mov       esi, eax                                      ;6.9
        mov       eax, ebp                                      ;6.28
        call      _fibonacci.                                   ;6.28
                                ; LOE eax ebx esi edi
.B1.7:                          ; Preds .B1.8
        mov       ebp, eax                                      ;6.28
        add       ebp, esi                                      ;6.28
                                ; LOE ebx ebp edi
.B1.3:                          ; Preds .B1.1 .B1.7
        mov       eax, ebp                                      ;
        pop       ecx                                           ;
        pop       ebp                                           ;
        pop       esi                                           ;
        ret                                                     ;
        ALIGN     16
                                ; LOE
; mark_end;
_fibonacci ENDP
;_fibonacci	ENDS
_TEXT	ENDS
_DATA	SEGMENT  DWORD PUBLIC FLAT  'DATA'
_DATA	ENDS
; -- End  _fibonacci
_DATA	SEGMENT  DWORD PUBLIC FLAT  'DATA'
_DATA	ENDS
	INCLUDELIB <libmmt>
	INCLUDELIB <LIBCMT>
	INCLUDELIB <libirc>
	INCLUDELIB <svml_disp>
	INCLUDELIB <OLDNAMES>
	INCLUDELIB <libdecimal>
	END

加载中
0
zhcosin
zhcosin
编译程序还是编译数列。。。。。。。
七液
七液
回复 @麦子粒粒香 : add esp,4速度慢,pop ecx速度快,ecx是不需要保存的所以一般恢复堆栈都是一句pop ecx.
麦子粒粒香
编译c程序啊,c代码已经贴出来了~
0
修改登录密码
修改登录密码

.b1.2 这是汇编语句标号,就是地址

2.1应该是对应了C语句行号

0
修改登录密码
修改登录密码

 ; Preds .B1.1 .B1.7

是描述代码短的前驱关系



修改登录密码
修改登录密码
回复 @麦子粒粒香 : 注释是给人看的,让你知道从哪些语句能跳转到本段代码。 编译器内部会画DAG图进行编译优化,找到代码间的数据相关、控制相关逻辑
麦子粒粒香
描述这种关系是用来干什么的呢
0
修改登录密码
修改登录密码

那个pop ecx真得很奇怪。。。

估计需要看编译器的约定, 不清楚icc的编译规则 

0
七液
七液

引用来自“eel”的答案

那个pop ecx真得很奇怪。。。

估计需要看编译器的约定, 不清楚icc的编译规则 

int fibonacci(int n)

C调用需要自己恢复堆栈,一般如果传递参数多的话直接就上add esp, (4*n)可是这里就一个参数不值得用add esp, (4*n).由于eax,ecx,edx是不需要保存的,而且pop ecx只占用一个字节.本来按照c调用约定是应该调用者恢复,可是这里代码优化就自己内部帮你恢复了。Intel 编译器就这样,不然怎么会速度快呢。其实有的时候许多函数很短的话它还给你直接inline了即使你没有inline标志。

返回顶部
顶部