码迷,mamicode.com
首页 > 编程语言 > 详细

汇编语言1:初识汇编

时间:2015-10-13 22:30:43      阅读:292      评论:0      收藏:0      [点我收藏+]

标签:

我这里学习汇编语言的思路就是逆向C++源码。

先从最简单的一个程序入手:

技术分享

技术分享

为什么程序的开头两句总会是

push ebp

mov ebp,esp

先来看一个程序:

技术分享

这个程序调用fun()时,fun的汇编代码也是如此,开头调用这两句汇编:

技术分享

其实,这里ebp中保存的是你当前的函数(main函数)的栈基址,当你进入一个子函数(func函数)的时候,你要使用这个子函数的栈空间,此时进入子函数的栈空间就要先保存当前函数的栈基址。将此时的 esp 赋予 ebp 以便后面用 ebp 来作为栈基并以此通过 [ebp+??] 来访问函数的参数、以 [ebp-??] 来访问函数的变量

可以用一个图表示:

技术分享

ebp其实可以当做是一个fun和main的“分界线”。

sub esp,0C0h,就是开辟了一块栈空间。

push ebx

push esi

push edi

用来保存main函数的“现场环境”。

lea edi,[ebp-0C0h]

mov ecx,30h

mov eax,0CCCCCCCCh

rep stos dword ptr es:[edi]

rep指令的目的是重复其上面的指令.ECX的值是重复的次数.
STOS指令的作用是将eax中的值拷贝到ES:EDI指向的地址.

这样就将这片栈空间中的数据都初始化为“CCCCCC...”

xor eax,eax

这个很简单,就是设置返回值,eax作为返回值。

技术分享

这几句实现真正的return。

那么问题来了?为什么要将栈空间初始化为“CCCCC...”?

从网上摘录了三句话来解释:

“int 3 的机器码就是 0xcc,对没初始化或变量之间填充这些,一旦程序异常,执行到这些位置来了,就会中断到调试器里面”

“vc debug初始化填充0xCC,为了方便调试查看,防止未初始化的情况发生,要知道release模式是不会自动帮你填任何东西的,也就是所谓初始化,C++不会做任何多余的事”

“这是一种防御式的代码调试方法,CC除了作为无效区域的标记,还是x86指令集中的INT 3单步中断的机器码,可以暂时停止指令的执行。”

看到网友的回答,原以为是因为如果访问未初始化的栈空间就会报错,但事实并非如此。

验证如下,我写了一个测试程序:

#include <iostream>

int fun()
{
    int i = 0;
    int *p = &i - 30;
    *p = 1;
    return 0;
}

int main()
{
    fun();
    return 0;
}

当初始化栈空间之后,我们可以查看下ebp的值:

技术分享

在内存中找到这个地址,查看内存:

技术分享

栈空间的绝大部分已经被“CC”填充。

当单步调试过int *p = &i - 30;时,p就有了值,它所指向的位置就是fun的栈空间

技术分享

下面我们就用*p = 1;来测试下这个空间是否可以访问

技术分享

结果,栈空间的位置被改变了。没有报告任何异常。

那么我们只能认为,这段"CC"只是起一个标识作用。如果有更好的解释,也欢迎大家提出。

 

汇编语言1:初识汇编

标签:

原文地址:http://www.cnblogs.com/predator-wang/p/4875883.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!