您的位置:首页 > 理论基础

Poedu_计算机基础_lesson06_20160902_函数调用过程

2016-09-04 14:52 260 查看
汇编和可执行文件

1.编译:得到obj文件 :  源代码----->机器码(约等于汇编)

 =>通过编译器实现这个过程

  =>编译器:将一行行的c/c++代码翻译成与之一一对应的汇编代码,将复杂逻辑分解成简单逻辑逻辑(c/c++中有很多种的语句,但是汇编中只有三种语句(见下方)) 

 =>编译器是稳定可靠的,但是也有例外的情况  

=>相同的代码,编译的时候可能会生成不一样的代码:因为编译器会进行优化  

=>当代码中出现废代码的时候,现在的编译器较为强大,会进行优化而不翻译成汇编代码

显然,同一段代码,在不同的条件下编译,所得到的汇编代码是不相同的,Debug下,会对每句代码都生成汇编代码如输入无意义的int num=10;Debug依旧有生成相应的汇编代码(调试的时候,建议用Debug,它会对每句代码生成对应的汇编,不会省略);Release下,同样输入无意义代码,不会生成汇编(发布版,要求快速、精悍)。这同时也解释了,为什么通过Release得到的exe文件会小于Debug,如下图:

有一个疑点:为什么这两个应用程序的大小和所占用空间不相等呢?

=>这是因为“簇”的存在(可看第四课笔记)

软件通过调用硬件起作用,当我们写完printf("hello")这一行代码时,能够得到这一行代码所对应的汇编代码(通过编译实现),但是如何将“helllo”显示在显示屏上?这就需要我们的CPU进行对显卡的调用,而我们并没有写这些代码。是由操作系统给我们提供了这一功能。但是,每一个操作系统都有自己的独特的API,我们要将我们所写的代码符合该操作系统的编写规范,才能够调用CPU,进而调用硬件。

=>由汇编代码得到符合该操作系统编写规范的可执行文件的过程,称之为链接(告诉该系统,我想要干什么的过程)

2.链接:加上PE结构,得到可执行文件

=>会生成与当前平台对应的格式

代码到可执行文件的类比:

源代码:生猪
编译:将生猪宰杀干净
链接:把肉进行再处理,加入各种调料,做成一道可以吃的菜

3.汇编代码
汇编代码约等于机器码
有三种类型:1)赋值语句   2)跳转语句   3)计算语句

4.计算机内部是怎样执行的?
上图所示的程序中,我用到了printf这个函数,那么其内部是怎样运行的呢?
程序的运行与栈区有关

=>栈区:存储临时变量、参数(默认生成1024KB供本程序使用)

=>栈溢出:如果数组的大小超出了最大的长度,那么就会发生栈溢出:如char arr[1024*1024]

=>解决:把这个数组放在堆上:char *arr=new char[1024*1024]

=>栈内存的使用与释放:划出一整段内存作为栈,用ebp存储当前栈底的地址,esp存储当前栈顶的地址(ebp~esp之间的空间即为当前运行函数所使用的栈空间),当要运行另一个函数的时候,会有保存当前ebp位置、发生ebp与esp置同、esp上游等动作。(详情请看这这节课的作业)

5.知识补充:

1)汇编指令  mov  目标,源
2)内存分区:栈、堆、代码、常量

=>这样分区更为安全:内存里的数据都是0和1,对于能够操作内存的语言,如果程序员把指针指向代码段,而且不小心修改了,那么程序就挂了

=>把所有的代码放在一个区段(只读不写),如果指针指向了代码段,那么就会报错,达到保护的作用

6作业:写一个“I Love Mark”,转到反汇编记录其中的各个信息

=>总结:函数是如何进行调用、传参、如何清理里面的临时变量的

EAX:累加寄存器

EBX:基址寄存器

ECX:计数器

EDX:存放放整数除法产生的余数

ESI: DS:ESI指向源串

EDI: DS:EDI指向目标串

===>以上都用来做通用寄存器

EIP:程序计数器

ESP:栈顶

EBP:栈底

EFL:标志寄存器
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: