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

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

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

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

要被编译的源文件是:

Code
#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);
}

生成的汇编代码是:

Code
; 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

That's it.

转载于:https://www.cnblogs.com/zhy2002/archive/2008/12/10/1351796.html

分析函数调用的汇编指令相关推荐

  1. go语言调度器源代码情景分析之五:汇编指令

    本文是<go调度器源代码情景分析>系列 第一章 预备知识的第4小节. 汇编语言是每位后端程序员都应该掌握的一门语言,因为学会了汇编语言,不管是对我们调试程序还是研究与理解计算机底层的一些运 ...

  2. inc si指令的作用_C|函数调用、汇编指令、栈空间及操作

    函数是任何编程语言不可缺少的语法机制,函数通常包括函数声明.定义.调用.调用及多层嵌套调用时会有一个回溯的问题,也就是回到原来函数调用的位置,如何实现呢,使用栈的后进先出机制.类似于你去一个地方,经过 ...

  3. arm汇编指令——分析问题的利器

    文章目录 arm汇编指令为什么重要 1. 主导问题 2. arm汇编指令分类介绍 通用寄存器 状态寄存器 数据转移指令 寻址格式 运算指令 比较指令 跳转指令 3. 反汇编接口 4. 反汇编分析举例 ...

  4. 【JVM】通过javap命令分析Java汇编指令

    文章目录 javap命令简述 javap测试及内容详解 例子1 例子2 总结 转载说明 javap命令简述 javap是jdk自带的反解析工具.它的作用就是根据class字节码文件,反解析出当前类对应 ...

  5. ARM汇编指令学习---基于启动文件startup.S分析

    本文主要是基于启动文件startup.s对ARM汇编指令进行学习分析. 以 . 开头一般是伪汇编/操作指令,形如: .section伪操作来定义一个段,形如: .section .testsectio ...

  6. 通过javap命令分析java汇编指令

    一.javap命令简述 javap是jdk自带的反解析工具.它的作用就是根据class字节码文件,反解析出当前类对应的code区(汇编指令).本地变量表.异常表和代码行偏移量映射表.常量池等等信息. ...

  7. Windows内核 基本汇编指令

    1)用VS2010新建Win32 Console Application,工程名为ACECore,工程建立完成后得到打开文件ACECore.cpp,代码如下: #include "stdaf ...

  8. 【C 语言】编译过程 分析 ( 预处理 | 编译 | 汇编 | 链接 | 宏定义 | 条件编译 | 编译器指示字 )

    相关文章链接 : 1.[嵌入式开发]C语言 指针数组 多维数组 2.[嵌入式开发]C语言 命令行参数 函数指针 gdb调试 3.[嵌入式开发]C语言 结构体相关 的 函数 指针 数组 4.[嵌入式开发 ...

  9. 浅谈函数调用的汇编实现细节(用栈来传递参数)

    文章目录 前言 程序分析 总结 前言 要想理解函数调用的汇编实现,需要清楚几个基本概念.在此针对的是用栈来传递参数.       1,调用现场的保护:假设函数A调用函数B,一旦程序执行进入函数B中,当 ...

最新文章

  1. python中计算1到_如何在Python中计算-1 /(-343)^(1/3)为1/7?
  2. UVA11419 我是SAM
  3. 使用ansible批量部署开机启动时为字符界面
  4. 如何破解无线路由器密码,如何破解WEP密码,破解无线路由器
  5. Android Service(7)--完结篇
  6. Frame - 快速创建高品质的 Web 应用原型
  7. ubuntu 一张网卡绑定多个ip
  8. 用gallery展示图片,实现中间图片稍大,两边较小的效果
  9. 从键盘上打开 Mac 应用程序的 4 种方法
  10. 8. PHP 5 echo 和 print 语句
  11. 安卓接入高德地图3dmap黑屏问题解决
  12. 各家关节机器人示教器特点
  13. syn包发送(拒绝攻击,但是有问题)
  14. 机械师笔记本电脑屏幕使用过程中忽然变暗
  15. 重磅!腾讯优图20篇论文入选CVPR 2021
  16. C#界面程序设计——04导入并修改word文件
  17. 浅谈导航数据中POI搜索技术原理
  18. 深度学习基础-损失函数详解
  19. 数据库--sql文件
  20. 云服务器、VPS、虚拟主机三者之间的区别?

热门文章

  1. Java UDP 编程简介.
  2. html 渐变透明写法,CSS3透明度+渐变
  3. 如何设计LRU Cache算法
  4. 教你从0到1搭建秒杀系统-缓存与数据库双写一致
  5. java元空间扩容_JVM元空间(Metaspace)
  6. java游戏一开始去山上打狐狸_。。。这才是Java的第一个程序------HelloWorld
  7. 【收藏】网络故障处理手册大全,看完再也不怕出问题了
  8. 实习就参与“服务过亿用户的项目”,是什么体验?
  9. matlab求图形的聚类系数,求助,为什么画不出来聚类系数的图?一直为0啊
  10. 长安大学二级c语言考试题,长安大学03-04C语言A卷试题