分析函数调用的汇编指令

来源:互联网 发布:spps软件 编辑:程序博客网 时间:2024/05/21 13:13

同样一段c++代码生成的汇编指令可能会不一样。有多种原因,例如编译器、调用约定或者底层平台。

今天要分析的是cdecl在x86机器上用visual c++ 2005上的编译结果。

首先需要设置一下项目配置以得到从源代码生成的汇编代码。

项目属性->配置属性->c/c++->输出文件->汇编输出 = Assembly With Source Code (/FAs)。

要被编译的源文件是:


#include "stdafx.h"

struct Point3D
{
    
int X;
    
int Y;
    
int Z;

    Point3D(
int x, int y, int z):X(x),Y(y),Z(z)
    {}
};

Point3D AddPoint3D(Point3D p1, Point3D p2)
{
    Point3D p(p1);
    p.X 
+= p2.X;
    p.Y 
+= p2.Y;
    p.Z 
+= p2.Z;

    
return p;
}

void main()
{
    Point3D p1(
1,2,3);
    Point3D p2(
4,5,6);
    Point3D p3 
= AddPoint3D(p1,p2);
}

 

生成的汇编代码是:

 


; Listing generated by Microsoft (R) Optimizing Compiler Version 14.00.50727.762 

    TITLE    
d:/project/CheckAsm/CheckAsm/CheckAsm.cpp
    .686P
    .XMM
    include listing.
inc
    .model    flat

INCLUDELIB MSVCRTD
INCLUDELIB OLDNAMES

PUBLIC    ?AddPoint3D@@YA?AUPoint3D@@U1@0@Z        
; AddPoint3D
EXTRN    @_RTC_CheckStackVars@8:PROC
EXTRN    
__RTC_Shutdown:PROC
EXTRN    
__RTC_InitBase:PROC
;    COMDAT rtc$TMZ
;
 File d:/project/checkasm/checkasm/checkasm.cpp
rtc$TMZ    SEGMENT
__RTC_Shutdown.rtc$TMZ DD 
FLAT:__RTC_Shutdown
rtc$TMZ    ENDS
;    COMDAT rtc$IMZ
rtc$IMZ    SEGMENT
__RTC_InitBase.rtc$IMZ DD 
FLAT:__RTC_InitBase
; Function compile flags: /Odtp /RTCsu /ZI
rtc$IMZ    ENDS
;    COMDAT ?AddPoint3D@@YA?AUPoint3D@@U1@0@Z
;
上面一堆先不管
_TEXT    SEGMENT;定义PE文件中的Text段
_p$ = -16                        ; size = 12;
___$ReturnUdt$ = 8                    ; size = 4
_p1$ = 12                        ; size = 12
_p2$ = 24                        ; size = 12
;
上面4个符号是AddPoint3D这个方法中的局部变量、返回值和参数的偏移量(相对于ebp)
?AddPoint3D@@YA?AUPoint3D@@U1@0@Z PROC            ; AddPoint3D, COMDAT AddPoint3D方法的定义开始,由于name mangling,名称变为了AddPoint3D@@YA?AUPoint3D@@U1@0@Z
;
 15   : {

    
push    ebp;保存caller的ebp到堆栈
    mov    ebp, esp;设置本方法的ebp。ebp在方法调用的开始阶段被设置,结束阶段被还原,调用过程中保持不变。ebp表示为本次调用所分配的堆栈桢的起始地址
    sub    esp, 212                ; 000000d4H esp减少一定的数量,表示为本次调用在栈上分配了一定的空间。让我们把>ebp && <= 现在的esp 的这段内存称之为locals
    push    ebx;保存现场的3个push
    push    esi
    
push    edi
    
lea    edi, DWORD PTR [ebp-212];把edi设置成刚才sub esp后esp的值,也就是locals的最低地址
    mov    ecx, 53                    ; 00000035H 53 * 4 = 212, you see whats going on here?
    mov    eax, -858993460                ; ccccccccH    设置eax=cccccccch
    rep stosd ;这是一个串操作指令,其意义是
;
while(ecx)
;
{
;
    *(int*)edi = eax;
;
    edi += sizeof(int);//这里就是4
;
    ecx--;
;
}
;
本指令和它上面的三条指令完成了把locals这段内存初始化成一片ccccccccccccccccccccc.
;
当此指令执行完毕,edi == ebp
;
 16   :     Point3D p(p1);

    
mov    eax, DWORD PTR _p1$[ebp]
    
mov    DWORD PTR _p$[ebp], eax
    
mov    ecx, DWORD PTR _p1$[ebp+4]
    
mov    DWORD PTR _p$[ebp+4], ecx
    
mov    edx, DWORD PTR _p1$[ebp+8]
    
mov    DWORD PTR _p$[ebp+8], edx
;复制构造局部变量p。_p1$[ebp]的意思就是[ebp + _p1$],_p1$是在前面定义过的一个偏移量
;
 17   :     p.X += p2.X;

    
mov    eax, DWORD PTR _p$[ebp]
    
add    eax, DWORD PTR _p2$[ebp]
    
mov    DWORD PTR _p$[ebp], eax

; 18   :     p.Y += p2.Y;

    
mov    eax, DWORD PTR _p$[ebp+4]
    
add    eax, DWORD PTR _p2$[ebp+4]
    
mov    DWORD PTR _p$[ebp+4], eax

; 19   :     p.Z += p2.Z;

    
mov    eax, DWORD PTR _p$[ebp+8]
    
add    eax, DWORD PTR _p2$[ebp+8]
    
mov    DWORD PTR _p$[ebp+8], eax
;这些很好理解
;
 20   : 
;
 21   :     return p;

    
mov    eax, DWORD PTR ___$ReturnUdt$[ebp]
;ReturnUdt中的Udt表示user defined type
;
这条指令的意思是,调用方在从ebp开始偏移量是___$ReturnUdt$的dword中保存的返回值应当存放的地址,把这个地址加载到eax中
;
此时eax保存的是一个地址,这个地址实际上call中局部变量p3的地址
    mov    ecx, DWORD PTR _p$[ebp]
    
mov    DWORD PTR [eax], ecx
    
mov    edx, DWORD PTR _p$[ebp+4]
    
mov    DWORD PTR [eax+4], edx
    
mov    ecx, DWORD PTR _p$[ebp+8]
    
mov    DWORD PTR [eax+8], ecx
;从局部变量p复制到call的局部变量p3中
    mov    eax, DWORD PTR ___$ReturnUdt$[ebp]
;在eax中保存返回值的地址
;
 22   : }
;
这一段{
    push    edx
    
mov    ecx, ebp
    
push    eax
    
lea    edx, DWORD PTR $LN5@AddPoint3D
    
call    @_RTC_CheckStackVars@8
    
pop    eax
    
pop    edx
;这一段}可以忽略掉,并不是我们程序逻辑的一部分
    pop    edi
    
pop    esi
    
pop    ebx
    
mov    esp, ebp
    
pop    ebp
    
ret    0;函数返回,返回值的保存地址存放在eax中
    npad    2
$
LN5@AddPoint3D:
    DD    
1
    DD    $LN4@AddPoint3D
$
LN4@AddPoint3D:
    DD    -
16                    ; fffffff0H
    DD    12                    ; 0000000cH
    DD    $LN3@AddPoint3D
$
LN3@AddPoint3D:
    DB    
112                    ; 00000070H
    DB    0
?AddPoint3D@@YA?AUPoint3D@@U1@0@Z ENDP            
; AddPoint3D
_TEXT    ENDS
PUBLIC    ??0Point3D@@QAE@HHH@Z                
; Point3D::Point3D
PUBLIC    _main
EXTRN    
__RTC_CheckEsp:PROC
; Function compile flags: /Odtp /RTCsu /ZI
;
    COMDAT _main
_TEXT    SEGMENT
_p3$ = -
56                        ; size = 12
_p2$ = -36                        ; size = 12
_p1$ = -16                        ; size = 12
_main    PROC                        ; COMDAT

; 25   : {
;
主函数的调用过程
;
参见上面的注释{
    push    ebp
    
mov    ebp, esp
    
sub    esp, 252                ; 000000fcH
    push    ebx
    
push    esi
    
push    edi
    
lea    edi, DWORD PTR [ebp-252]
    
mov    ecx, 63                    ; 0000003fH
    mov    eax, -858993460                ; ccccccccH
    rep stosd
;参见上面的注释}
;
 26   :     Point3D p1(1,2,3);

    
push    3
    
push    2
    
push    1
    
lea    ecx, DWORD PTR _p1$[ebp];ecx传递this指针,thiscall
    call    ??0Point3D@@QAE@HHH@Z            ; Point3D::Point3D

; 27   :     Point3D p2(4,5,6);

    
push    6
    
push    5
    
push    4
    
lea    ecx, DWORD PTR _p2$[ebp]
    
call    ??0Point3D@@QAE@HHH@Z            ; Point3D::Point3D

; 28   :     Point3D p3 = AddPoint3D(p1,p2);

    
sub    esp, 12                    ; 0000000cH 分配实参p1的空间并按值传递
    mov    eax, esp
    
mov    ecx, DWORD PTR _p2$[ebp]
    
mov    DWORD PTR [eax], ecx
    
mov    edx, DWORD PTR _p2$[ebp+4]
    
mov    DWORD PTR [eax+4], edx
    
mov    ecx, DWORD PTR _p2$[ebp+8]
    
mov    DWORD PTR [eax+8], ecx
    
sub    esp, 12                    ; 0000000cH 分配实参p2的空间并按值传递
    mov    edx, esp
    
mov    eax, DWORD PTR _p1$[ebp]
    
mov    DWORD PTR [edx], eax
    
mov    ecx, DWORD PTR _p1$[ebp+4]
    
mov    DWORD PTR [edx+4], ecx
    
mov    eax, DWORD PTR _p1$[ebp+8]
    
mov    DWORD PTR [edx+8], eax
    
lea    ecx, DWORD PTR _p3$[ebp]
    
push    ecx    ;注意这个地方,p3的地址被保存在这里,也就是返回值的地址
    call    ?AddPoint3D@@YA?AUPoint3D@@U1@0@Z    ; AddPoint3D
    add    esp, 28                    ; 0000001cH 调用方清理参数堆栈28=12+12+4

; 29   : }

    
xor    eax, eax
    
push    edx
    
mov    ecx, ebp
    
push    eax
    
lea    edx, DWORD PTR $LN7@main
    
call    @_RTC_CheckStackVars@8
    
pop    eax
    
pop    edx
    
pop    edi
    
pop    esi
    
pop    ebx
    
add    esp, 252                ; 000000fcH
    cmp    ebp, esp
    
call    __RTC_CheckEsp
    
mov    esp, ebp
    
pop    ebp
    
ret    0
    npad    
3
$
LN7@main:
    DD    
3
    DD    $LN6@main
$
LN6@main:
    DD    -
16                    ; fffffff0H
    DD    12                    ; 0000000cH
    DD    $LN3@main
    DD    -
36                    ; ffffffdcH
    DD    12                    ; 0000000cH
    DD    $LN4@main
    DD    -
56                    ; ffffffc8H
    DD    12                    ; 0000000cH
    DD    $LN5@main
$
LN5@main:
    DB    
112                    ; 00000070H
    DB    51                    ; 00000033H
    DB    0
$
LN4@main:
    DB    
112                    ; 00000070H
    DB    50                    ; 00000032H
    DB    0
$
LN3@main:
    DB    
112                    ; 00000070H
    DB    49                    ; 00000031H
    DB    0
_main    ENDP
; Function compile flags: /Odtp /RTCsu /ZI
_TEXT    ENDS
;    COMDAT ??0Point3D@@QAE@HHH@Z
_TEXT    SEGMENT
_this$ = -
8                        ; size = 4
_x$ = 8                            ; size = 4
_y$ = 12                        ; size = 4
_z$ = 16                        ; size = 4
??0Point3D@@QAE@HHH@Z PROC                ; Point3D::Point3D, COMDAT
;
 _this$ = ecx

; 11   :     {}

    
push    ebp
    
mov    ebp, esp
    
sub    esp, 204                ; 000000ccH
    push    ebx
    
push    esi
    
push    edi
    
push    ecx
    
lea    edi, DWORD PTR [ebp-204]
    
mov    ecx, 51                    ; 00000033H
    mov    eax, -858993460                ; ccccccccH
    rep stosd
    
pop    ecx
    
mov    DWORD PTR _this$[ebp], ecx
    
mov    eax, DWORD PTR _this$[ebp]
    
mov    ecx, DWORD PTR _x$[ebp]
    
mov    DWORD PTR [eax], ecx
    
mov    eax, DWORD PTR _this$[ebp]
    
mov    ecx, DWORD PTR _y$[ebp]
    
mov    DWORD PTR [eax+4], ecx
    
mov    eax, DWORD PTR _this$[ebp]
    
mov    ecx, DWORD PTR _z$[ebp]
    
mov    DWORD PTR [eax+8], ecx
    
mov    eax, DWORD PTR _this$[ebp]
    
pop    edi
    
pop    esi
    
pop    ebx
    
mov    esp, ebp
    
pop    ebp
    
ret    12                    ; 0000000cH
??0Point3D@@QAE@HHH@Z ENDP                ; Point3D::Point3D
_TEXT    ENDS
END
摘自:http://www.cnblogs.com/zhy2002/archive/2008/12/10/1351796.html

 

原创粉丝点击