一个源代码与反汇编代码对照的实例

电脑杂谈  发布时间:2019-09-11 09:04:20  来源:网络整理

esp文件是什么意思_esp故障是什么意思_汇编esp是什么意思

如下的C++代码,对应的汇编代码会是哪个样子呢?

 

#include <stdio.h>
int Addemup(int,int);
void main(void)
{
    int x = 5;
    int y = 10;
    int z = 0;
    z = Addemup(x,y);
    printf("z= %i\n",z);
}
int Addemup(int a, int b)
{
    int c = 0;
    c=a+b;
    return(c);
}

 

1:    #include <stdio.h>
2:
3:    int Addemup(int,int);
4:
5:    void main(void)
6:    {
            addemup!main:
            00401000 55               push    ebp            ; save base pointer
            00401001 8bec            mov     ebp,esp        ; set stack pointer
            00401003 83ec0c         sub      esp,0xc        ; make room for locals
           //在这一段中,我们先保存了栈底指针(ebp),以便稍后恢复它。
         //之后让栈基指向栈顶,把原来的栈顶作为新栈底了,形象点的说,就是栈向上移动了原来栈长度的一段距离。
         //在这里,我们可以看出,若要访问函数参数,那么采用的相对于ebp的位移就是正的,
         //而函数的局部变量的位移就是负的。
7:         int x = 5;
8:         int y = 10;
9:         int z = 0;
            00401006 c745fc05000000   mov     dword ptr [ebp-0x4],0x5    ; local x = 5
            0040100d c745f80a000000   mov     dword ptr [ebp-0x8],0xa    ; local y = 10
            00401014 c745f400000000   mov     dword ptr [ebp-0xc],0x0    ; local z = 0
            //ptr指令是修改属性运算符,用来明确指出变量、标号或地址表达式的类型属性(只在所在的指令内有效)。
         //类型放在PTR 之前,可以是BYTE、WORD、DWORD、NEAR、FAR。
         //这里的操作是将x5这个操作数扩展成dword存入地址为[ebp-0x4]的内存中
10:
11:        z = Addemup(x,y);
            0040101b 8b45f8         mov     eax,[ebp-0x8]    ; load eax with y
            0040101e 50               push    eax                    ; push y on stack
            0040101f 8b4dfc          mov     ecx,[ebp-0x4]    ; load ecx with x
            00401022 51               push    ecx                    ; push x on stack
            00401023 e81b000000    call    addemup!Addemup    ; call Addemup
            00401028 8308           add     esp,0x8            ; fixup stack for args
            0040102b 8945f4           mov     [ebp-0xc],eax   ; z returned in eax
           //这里是Addemup函数的调用部分。先将x,y压入栈中,作为调用的参数。
         //压入了两个dword型参数,每个dword占4个字节,所以栈顶指针在压栈之后向上移动了8个字节.
           //调用结束之后,指示栈顶的esp被加回了8个字节,也就是恢复了栈的状态。
         //这里注意,一般函数调用的返回值都是放在eax之中的,
         //所以将eax的值拷贝到[ebp-0xc]中完成的就是给z赋予函数返回结果的动作。
         //可以看出,这里在函数调用结束后,去掉参数的栈顶的恢复工作是由调用者完成的。
12:
13:       printf("z= %i\n",z);
            0040102e 8b55f4           mov     edx,[ebp-0xc]     ; load edx with z
            00401031 52                 push    edx                   ; push z on the stack
            00401032 6830704000    push    0x407030           ; push ptr to “z=%i\n”
         00401037 e822000000   call      addemup!printf    ; call printf
            0040103c 8308          add      esp,0x8             ; fix stack for args
             //这里是一个对printf函数的调用,过程与上面的函数调用一样。
         //1.先将参数压栈; 2.保存当前栈底位置; 3.调用函数; 4.恢复栈顶位置
14:    }
        0040103f 8be5            mov     esp,ebp        ; restore stack ptr
        00401041 5d               pop     ebp            ; restore base ptr
        00401042 c3               ret                ; return
        
        //这里还是main函数。函数的调用者负责调整栈顶指针,被调用的函数体要将栈顶,栈底都恢复到被调用之前的状态。
15:
16:    int Addemup(int a, int b)
17:    {
              addemup!Addemup:
              00401043 55               push    ebp            ; save base pointer
              00401044 8bec            mov     ebp,esp      ; set stack pointer
              00401046 51               push    ecx            ; make room for local
              //1. 保存栈底,2. 设置栈底,3. 修改栈顶,为本地变量分配空间
18:         int c = 0;
19:
20:         c = a + b;
              00401047 c745fc00000000   mov     dword ptr [ebp-0x4],0x0    ; local c = 0
              0040104e 8b4508           mov     eax,[ebp+0x8]    ; set eax to local a
              00401051 03450c           add      eax,[ebp+0xc]    ; eax = eax + local b
              00401054 8945fc            mov     [ebp-0x4],eax    ; local c = a + b
             //eax是累加器
21:        return(c);
             00401057 8b45fc             mov     eax,[ebp-0x4]  ; set eax to result c
             //eax被用来返回值
22:    }
0040105a 8be5             mov     esp,ebp    ; restore stack ptr
0040105c 5d                 pop     ebp          ; restore base ptr
0040105d c3                 ret                ; return to caller
//恢复栈顶,恢复栈底

 

总结一下变量调用的过程中,栈的运作吧。该实例中使用的调用约定是CDECL汇编esp是什么意思,后面的文章会提到。

调用者负责的部分:

阶段

动作

esp文件是什么意思_汇编esp是什么意思_esp故障是什么意思

细节

调用之前(状态一)

今天栈拥有一个调用函数之前的状态。假设ebp=a;esp=b;

准备工作

将所有参数压入栈

随着压栈的动作,栈顶指针向低地址端移动。esp=b-x。(状态二)

调用函数

见下表

收尾工作

修改栈顶指针

esp故障是什么意思_汇编esp是什么意思_esp文件是什么意思

恢复到状况一。esp=b,ebp=a

 

被调用者负责的个别:

阶段

动作

细节

初进函数(状态二)

今天栈拥有一个状态。假设ebp=a;esp=b-x;

初始化

1.保存栈底,2.设置栈底汇编esp是什么意思,3.修改栈顶,为本地变量分配空间

汇编esp是什么意思_esp文件是什么意思_esp故障是什么意思

ebp=b-x;esp=b-x-y;值a在栈中。(状态三)

执行函数体

 

收尾工作

1.恢复栈顶,2.恢复栈底

恢复到状况二。esp=b-x;ebp=a;(状态二)

表格注:

x是参数所占的空间

y是局部变量所占的空间

 

esp故障是什么意思_esp文件是什么意思_汇编esp是什么意思

有点帮忙,要多想几次就能记得出来。不过相信汇编代码多看一些,见得多了自然也就烂熟于心了。

 

练习:

if(i==0)gotoLabel1;

C代码:

对应的汇编代码:

moveax,[ebp–4]  ;这里假如i是第一个局部变量,如果是第一个参数,那需要是[ebp+8]

cmpeax,0x0

jzLabel1

 

问题:

为什么代码中第七行后面的一句pushecx的目的是makeroomforlocal?如何做到的?

答:注释错误。PUSHECX的目的是为了保存ECX的值。

postedon2009-11-0100:59中道学友阅读(...)评论(...)编辑


本文来自电脑杂谈,转载请注明本文网址:
http://xinshanjie.com/a/jisuanjixue/article-122493-1.html

    相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    热点图片
    拼命载入中...