游戏开发论坛

 找回密码
 立即注册
搜索
查看: 2376|回复: 2

一个简单C++程序的汇编代码分析wxh zt

[复制链接]

1367

主题

1993

帖子

2118

积分

金牌会员

Rank: 6Rank: 6

积分
2118
发表于 2006-1-10 23:33:00 | 显示全部楼层 |阅读模式

作者 陈辉东

介绍
本文以一个简单的C++程序的汇编代码作为分析对象,通过该汇编代码我们可以窥视一下C++的函数,变量等成员的内存安排和编译系统的实现机制.

正文
本文以一个简单的C++程序的汇编代码作为分析对象,通过该汇编代码我们可以窥视一下C++的函数,变量等成员的内存安排和编译系统的实现机制.
下面是本文所用到的C++代码:

下面是该代码编译后生成的汇编代码:
    TITLE    E:\pracise\Base\CSimple.cpp
    .386P
include listing.inc
if @Version gt 510
.model FLAT
else
_TEXT    SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT    ENDS
_DATA    SEGMENT DWORD USE32 PUBLIC 'DATA'
_DATA    ENDS
CONST    SEGMENT DWORD USE32 PUBLIC 'CONST'
CONST    ENDS
_BSS    SEGMENT DWORD USE32 PUBLIC 'BSS'
_BSS    ENDS
$$SYMBOLS    SEGMENT BYTE USE32 'DEBSYM'
$$SYMBOLS    ENDS
$$TYPES    SEGMENT BYTE USE32 'DEBTYP'
$$TYPES    ENDS
_TLS    SEGMENT DWORD USE32 PUBLIC 'TLS'
_TLS    ENDS
;    COMDAT ?set_age@IT@@QAEXH@Z
_TEXT    SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT    ENDS
;    COMDAT ?get_age@IT@@QAEHXZ
_TEXT    SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT    ENDS
;    COMDAT _main
_TEXT    SEGMENT PARA USE32 PUBLIC 'CODE'
_TEXT    ENDS
FLAT    GROUP _DATA, CONST, _BSS
    ASSUME    CS: FLAT, DS: FLAT, SS: FLAT
endif
PUBLIC    ?get_age@IT@@QAEHXZ                ; IT::get_age
;    COMDAT ?get_age@IT@@QAEHXZ
_TEXT    SEGMENT
_this$ = -4
?get_age@IT@@QAEHXZ PROC NEAR                ; IT::get_age, COMDAT

; 18   : {

    push    ebp
    mov    ebp, esp
    sub    esp, 68                    ; 00000044H
    push    ebx
    push    esi
    push    edi
    push    ecx
    lea    edi, DWORD PTR [ebp-68]
    mov    ecx, 17                    ; 00000011H
    mov    eax, -858993460                ; ccccccccH
    rep stosd
    pop    ecx
    mov    DWORD PTR _this$[ebp], ecx

; 19   :     return m_age;

    mov    eax, DWORD PTR _this$[ebp]
    mov    eax, DWORD PTR [eax]

; 20   : }

    pop    edi
    pop    esi
    pop    ebx
    mov    esp, ebp
    pop    ebp
    ret    0
?get_age@IT@@QAEHXZ ENDP                ; IT::get_age
_TEXT    ENDS
PUBLIC    ?set_age@IT@@QAEXH@Z                ; IT::set_age
PUBLIC    _main
EXTRN    __chkesp:NEAR
;    COMDAT _main
_TEXT    SEGMENT
_dongdong$ = -4
_main    PROC NEAR                    ; COMDAT

; 23   : {

    push    ebp
    mov    ebp, esp
    sub    esp, 68                    ; 00000044H
    push    ebx
    push    esi
    push    edi
    lea    edi, DWORD PTR [ebp-68]
    mov    ecx, 17                    ; 00000011H
    mov    eax, -858993460                ; ccccccccH
    rep stosd

; 24   :     IT dongdong;
; 25   :     dongdong.set_age(4);

    push    4
    lea    ecx, DWORD PTR _dongdong$[ebp]
    call    ?set_age@IT@@QAEXH@Z            ; IT::set_age

; 26   :     dongdong.get_age();

    lea    ecx, DWORD PTR _dongdong$[ebp]
    call    ?get_age@IT@@QAEHXZ            ; IT::get_age

; 27   :     return 0;

    xor    eax, eax

; 28   : }

    pop    edi
    pop    esi
    pop    ebx
    add    esp, 68                    ; 00000044H
    cmp    ebp, esp
    call    __chkesp
    mov    esp, ebp
    pop    ebp
    ret    0
_main    ENDP
_TEXT    ENDS
;    COMDAT ?set_age@IT@@QAEXH@Z
_TEXT    SEGMENT
_age$ = 8
_this$ = -4
?set_age@IT@@QAEXH@Z PROC NEAR                ; IT::set_age, COMDAT

; 12   :     void set_age(int age){m_age = age;}

    push    ebp
    mov    ebp, esp
    sub    esp, 68                    ; 00000044H
    push    ebx
    push    esi
    push    edi
    push    ecx
    lea    edi, DWORD PTR [ebp-68]
    mov    ecx, 17                    ; 00000011H
    mov    eax, -858993460                ; ccccccccH
    rep stosd
    pop    ecx
    mov    DWORD PTR _this$[ebp], ecx
    mov    eax, DWORD PTR _this$[ebp]
    mov    ecx, DWORD PTR _age$[ebp]
    mov    DWORD PTR [eax], ecx
    pop    edi
    pop    esi
    pop    ebx
    mov    esp, ebp
    pop    ebp
    ret    4
?set_age@IT@@QAEXH@Z ENDP                ; IT::set_age
_TEXT    ENDS
END
下面,我们来分析该汇编代码。
首先是汇编代码的标题版本等。如下:


第1行指定本汇编程序的标题,此处用该程序全路径的名称作为标题;
第2行”.386”告诉编译器,程序要用到80386的指令集;
第3行是将listing.inc包含进来;
接下来的代码(4-32行)进行编译器版本判断,如果版本大于5.1,则编译模式为FLAT模式,否则得进行段的定义,并指定段_DATA,CONST,_BSS在组FLAT中,同时设置CS,DS等段寄存器的值为FLAT的起始地址。
所谓FLAT模式,即平坦模式,是Win32平台中特有的内存模式。在这种模式下,段的基地址用32位来表示,故一个段的大小为4G。由于Win32平台中只有这种内存模式,因此不存在段的区别,所有的应用程序都在这4G的空间上运行,不过windows将它们放在各自独立的虚拟地址空间上运行,每一个程序都可以拥有4G空间的寻址能力。在平坦模式下,汇编代码中的段只是表明这个大的共享段中的一个内存区域。这些区域包括数据段(_DATA, _BSS),代码段(_TEXT),静态数据段(CONST),堆栈段(STACK)等。

下面我们从程序的入口地址main来开始分析:

&quotUBLIC _main"指明main是全局标志符,可以被其他外部模块调用;
"EXTRN __chkesp"指明chkesp已经在别的模块中定义;
"_TEXT SEGMENT"指明下面是代码段开始;"_dongdong$ = -4"指对象dongdong的位置为ebp-4;
"push ebp"保存当前环境,
"mov ebp, esp"将当前栈顶指针赋给ebp,
"sub esp, 68"将栈顶指针上移68个字节(中间空出的这些地址是给main里的变量预留的);
"push ebx"…保存当前寄存器的内容;
"lea edi, DWORD PTR [ebp-68]”获取指令"sub esp, 68"执行后esp所指的地址,存入edi中;
"mov ecx,17"..是对几个寄存器进行初始化;
"push 4"将4入栈;
"lea ecx,DWORD PTR _dongdong$ [ebp]",将对象dongdong所在的地址存入ecx中;
"call ?set_age@IT@@QAEXH@Z"调用set_age函数。

现在来看函数set_age的汇编代码:

“_age $ = 8” “_this $ = -4”表明变量age存放在ebp+8处,当前对象指针地址存放在ebp-4处;
行128-138与函数main类似,先保存当前环境,对寄存器赋初值;
“pop ecx”此处ecx就是前面main中对象dongdong的地址;
“mov    DWORD PTR _this$[ebp], ecx”将对象dongdong的地址存入_this$[ebp]中(就是前面声明的用来存放对象地址的);
“mov    eax, DWORD PTR _this$[ebp]” ”    mov    ecx, DWORD PTR _age$[ebp]”
将对象的地址存入eax中,age的地址存入ecx中;
“mov    DWORD PTR [eax], ecx”将ecx的内容存入eax所指的地址中去,即将age的值赋给m_age.怎么知道是m_age呢?因为m_age是对象dongdong中的第一个成员变量,dongdong的首地址就是m_age的首地址。
接下去是出栈,函数返回。
函数get_age的执行过程和set_age差不多,这里不再赘述。

看了上面的分析,也许你搞晕了。其实,过程并不复杂:
比如在main里,步骤总结如下:
1.    保存ebp(ebp入栈);
2.    ebp指向esp所指;
3.    esp指向esp-68位置(为变量腾出空间);
4.    几个寄存器(ebx..)入栈;
5.    edi指向3中的esp的位置;
6.    初始化几个寄存器(ecx,eax..);
7.    4压入栈;
8.    将对象dongdong的地址存入ecx中
9.    调用函数set_age.
然后系统转入函数set_age中,与上面类似,函数set_age开始也是进行环境地址的保存和寄存器的初始化,之后在获得对象的地址,再进行赋值。
同时,从上面汇编代码可以看出,程序的代码存储在代码段_TEXT中,一般变量在堆栈中。一个类的对象声明后,其地址位于堆栈中,对象的数据成员存放的地址紧随在对象之后。



248

主题

2674

帖子

2702

积分

金牌会员

Rank: 6Rank: 6

积分
2702
QQ
发表于 2006-1-12 02:00:00 | 显示全部楼层

Re:一个简单C++程序的汇编代码分析wxh zt

中国的东西就是喜欢浅尝辄止,如果能深入做成一个系列,和外国的作风就有得拼了!
期待作者能再接再厉吧。

6

主题

110

帖子

110

积分

注册会员

Rank: 2

积分
110
发表于 2006-1-13 12:17:00 | 显示全部楼层

Re:一个简单C++程序的汇编代码分析wxh zt

初级教程,顶上去.把汇编发扬光大
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-23 05:16

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表