没画完的画

喂马 劈柴 BBQ~
posts - 37, comments - 55, trackbacks - 0, articles - 0
  C++博客 ::  :: 新随笔 :: 联系 :: 聚合  :: 管理

第一集中,终于知道调用函数 func1() 之后,就分配了堆栈的空间,然后将堆栈空间的内容初始化为 0xCC
------------------------------------------------------------------------------------------------
6:        int j;
7:        char c;
8:        short k;
9:
10:       j = 0;
00401038   mov         dword ptr [ebp-4],0
11:       c = 'a';
0040103F   mov         byte ptr [ebp-8],61h
12:       k = 1;
00401043   mov         word ptr [ebp-0Ch],offset func1+27h (00401047)
13:
14:       printf("sum=%d\n", input1+input2);
00401049   mov         eax,dword ptr [ebp+8]
0040104C   add         eax,dword ptr [ebp+0Ch]
0040104F   push        eax
00401050   push        offset string "sum=%d\n" (0042201c)
00401055   call        printf (00401130)
0040105A   add         esp,8
15:
16:       return;
17:   }
0040105D   pop         edi
0040105E   pop         esi
0040105F   pop         ebx
00401060   add         esp,4Ch
00401063   cmp         ebp,esp
00401065   call        __chkesp (004011b0)
0040106A   mov         esp,ebp
0040106C   pop         ebp
0040106D   ret
------------------------------------------------------------------------------------------------
上面代码为 将堆栈初始化为 0xCC 之后的代码
程序是如何读取 [函数内部的局部变量] 和 [入口参数] 的呢?
 
首先看下[入口参数],
在上一集,知道在调用 func1()  之前,参数已经 push 到堆栈了
 
ebp 为 栈内存基地址, 即栈底
esp 为 当前的栈顶地址
在内存中 栈底处于高地址,栈顶处于底地址
 
10:       j = 0;
00401038   mov         dword ptr [ebp-4],0          ; 放至于 [ebp] - 4  的地址
11:       c = 'a';
0040103F   mov         byte ptr [ebp-8],61h         ; 主至于 [ebp] - 8 的地址,这里虽然 c 只需占用一个字节,但实际上它占用了四个字节,
                                                                   ; 因为编译器作了优化,传说中的“字节对齐”
12:       k = 1;
00401043   mov         word ptr [ebp-0Ch],offset func1+27h (00401047)
 
当执行完 0040103F   mov         byte ptr [ebp-8],61h 后,
-------------------------------------------------------
 EAX = CCCCCCCC EBX = 7FFD3000 ECX = 00000000
 EDX = 00000002 ESI = 00000000 EDI = 0012FF14
 EIP = 00401043 ESP = 0012FEBC EBP = 0012FF14
-------------------------------------------------------
0012FF06  CC CC CC CC CC CC 61  烫烫烫a
0012FF0D  CC CC CC 00 00 00 00  烫.....
0012FF14  80 FF 12 00 E4 10 40  ......@
 
从内存的内容不难看出,c实际上占用了四个字节,而多余的三个字节依然还是 0xCC 的内容
 
在执行这一句之前,
mov         word ptr [ebp-0Ch],offset func1+27h (00401047)
offset 是编译器提供的伪指令,它不是真正的cpu指令,他被编译器执行。
而 lea 是cpu指令,他被cpu执行。
一般情况下offset 跟mov连用的!而lea是直接使的!
 
mov dx, offset buf
lea   dx, buf
---------------------------------------
编译以后:
mov dx, 0004h    ;相对地址
lea   dx, [0061h] ;DS:[0061h]

突然发现汇编指令的寻址方式忘光了,  offset 都忘记是干嘛的
好困,需要~~~需要先睡一会~~

Feedback

# re: 函数堆栈是这么回事 第2集  回复  更多评论   

2008-09-28 08:35 by 908971
不错的内容,支持

# re: 函数堆栈是这么回事 第2集  回复  更多评论   

2008-09-28 09:22 by ljbxc
呵呵,有点一休的风格

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理