计算机世界--函数调用
来源:互联网 发布:张国荣同性恋 知乎 编辑:程序博客网 时间:2024/06/18 00:00
汇编和可执行文件
编译
链接
汇编代码
1.汇编和可执行文件
我们知道:汇编≈机器码,汇编是用来给我们人类看的。那么可执行文件是怎么生成的呢?它是由源代码通过编译,得到汇编代码,汇编代码通过链接,得到可执行文件。
Java语言,并不是直接将我们的c/c++翻译成汇编语言,而是拿着c/c++代码在执行的时候一步一步的翻译成其他语言,为什么会这样呢?因为在编译的时候,有多种平台(但是我们所有的CPU是只认识汇编语言的,那么按道理我直接将源代码1翻译成汇编,那么所有的平台下面不就都能应该认识我翻译的语言,因为我翻译出来的就直接是汇编呀!为什么还要这么麻烦的翻译成三个版本出来呢?难道在不同的操作系统下面,用的就不是汇编了吗?其实并不是这样的,编译只是我们的第一个步骤,从我们的源代码最终是要到一个可执行文件,可执行文件和我们生成的汇编是不同的,汇编代码并不是可执行的,而是还需要一个步骤就是链接,也就是link)。
我们在写代码的时候,我们需要时候各种各样的API,也是就是说我们的代码中90%的代码并没有与之对应的汇编代码,那么什么是没有与之对应的代码呢?假设在我们的代码中,有一句很简单的语句,printf函数,那么我们要实现这句代码的时候,它需要做很多事情,比如说要与各种各样的显卡交互,而我们软件工程师只需要管软件的事情,并不需要管硬件的事情,因为中间恰好有一个东西叫做操作系统。而我们是没有硬件上的汇编代码,如果真的没有硬件汇编代码,那么我们的代码将变得没有任何意义。所以,如果你让是想在不同的操作系统中运行这句代码,那么你需要根据不同的操作系统的规则来Link(连接)硬件汇编代码。
link:就是把操作系统提供的与硬件相关的汇编代码,与我们的自己写的代码链接到一起的过程。
其实在任何一个操作系统下面编译都是这么一回事,首先会产生一个obj的文件,即程序产生的汇编代码,这个汇编代码是没有意义的,因为它并不能被操作系统执行,它不符合操作系统的要求,还需要进行Link才能达到操作系统的要求。
所以从源代码到可执行文件,中间需要经过两步,第一步是编译,第二步是Link(生成与平台对应的文件格式),Link的时候,相当于深加工(比如说Windows平台下,我们加上PE结构,比如说加载dll或者函数),这样Windows平台下面的可执行文件就生成了。
编译器:其实就是做一样事情,即将c/c++代码变成与之对应的汇编代码,这种对应关系是非常稳定和可靠的。所以平时我们的程序会非常的稳定,但是,也会有例外的情况,这种例外的情况指的是什么呢?我们的编译器会对我们的程序进行一些优化,就是将我们没有用的代码给去掉,也有可能根据我们生成模式的不同,编译器可能生成不同的代码,比如说debug版本和release版本。归根结底,就是编译器对我们的程序进行了一些优化。
所谓编译器,就是将我们的复杂逻辑,分解成简单的逻辑,我们平时写的代码中会有很多种逻辑,但是到了汇编中,可能就会有这样几种逻辑:1、赋值语句;2、跳转语句;3、计算语句
汇编代码包括:
1、赋值语句;
2、跳转语句
3、计算语句
赋值语句; 例如: mov (移动) 目标 , 源 临时的变量 临时变量是否占用内存空间呢?肯定是占用的,程序里面的任何东西都要占用内存,而临时变量占用的内存,我们称之为栈;
我们会整体的将我们的内存划分为四大块,分别为:栈、堆、代码、常量。
栈:读写都可以
堆:读写都可以
代码:只读不写
常量区:只读不写
为什么要进行这样的一个分区呢?因为这样会更加的安全,为什么会更加安全呢?无论是从CPU还是内存角度来看,这些数据都是一模一样的,这样的话,如果是一门能够操作内存的语言,比如c/c++,万一不小心把指针指向了代码区,而且不小心的把它给修改了,那么这样程序就会挂了。所以我们将代码区划分出来,并且是受保护的,这样即使指向了代码区,那么这个指针是不能指向这个区的,就会报错。
栈区是用来做什么呢?在Windows下默认为我们的每一个程序会生成1M的内存,但是这也是可增长的,以后我们会经常碰到一个问题,就是栈溢出,比如 char array[1024*1024] = {0};//这样就会栈溢出的错误,解决的办法是,在堆中申请,比如 char *p = new char[1024*1024]; // 这样就不会出错了
栈会为我们做什么呢?它会存储一些临时变量,因为临时变量都会占用内存的,而申请内存,释放内存,都需要占用一定时间的,导致效率降低,所以干脆在我们的程序里面直接申请一片内存,作为栈控件,而这一片空间在程序运行的过程中都不会释放,直到程序运行完成之后,来自动释放这片内存。
原理:用栈寄存器 ebp(游标) 来记录栈底的位置,然后每一次需要使用新的变量的时候,我在使用另外一个栈寄存器 esp 来记录栈的最高点,当我们使用完成之后,将最高点的游标和最低点的游标相等,也就是将这一段区间的数据作废,就相当于我们的临时变量被释放掉了。这就解释了为什么栈的效率高,因为它能够反复的这片内存空间。
当然了,栈不仅仅是用来存储临时变量的,数据回溯,传递参数,函数地址等等。比如说,保存跳转后返回地址,每次调用函数(API)
函数执行的汇编过程(有时间再补吧)
1 0
- 计算机世界--函数调用
- 计算机世界
- 计算机世界--内存
- 计算机世界--磁盘
- 计算机世界--操作系统
- 计算机世界1000期特刊
- 致计算机世界的公开信
- 计算机世界的黑客帝国
- 计算机世界里总有新名词
- 计算机世界中的道德伦理
- 计算机世界:“XXXX”腾讯
- 计算机世界:免费的代价
- 那些电影中的计算机世界
- 关于计算机世界的猜想
- 计算机世界中的编码问题
- 计算机世界的乐趣之一
- 走进计算机世界--计算机科学
- 计算机世界--软件和硬件
- 记一次FPGA特别低级的错误
- Android BroadCast广播
- CSU 1087 就多了两分钟【恶心题,时间计算】
- Leetcode题解:First Unique Character in a String
- 自定义view
- 计算机世界--函数调用
- 【LeetCode】169.Majority Element (Easy)
- 第29篇 JS及html
- maven工程pom文件标签详解
- UVA10494 - If We Were a Child Again
- 计算机世界--软件和硬件
- (2016)京东笔试校招编程题目
- Forbidden:You don't have permission to access /index.php on this server
- 开始Docker