计算机是如何解读高级语言的
2016-02-27 21:02
375 查看
大家都知道,C语言是一种应用非常广泛的高级语言,而且标准的C语言程序可以在很多电脑平台上进行编译,但是大家是否知道计算机是怎么解读C语言的呢?
下面我通过一个小小的例子来为大家分析一下:首先是编写一段简单的C语言程序,如下图所示:
然后我们把它反编译成汇编语言,因为汇编语言是最接近机器语言的,如图:
接下来我们通过这段汇编语言来分析这段C语言是怎么运行的:
g:
1 pushl %ebp //寄存器esp由地址1976开始-4,再将寄存器ebp的内容放入esp;
2 movl %esp, %ebp ///将esp的值放入ebp中,即让ebp=1972;
3 movl 8(%ebp), %eax //将ebp+8=1980中的内容放入寄存器eax中,即eax=9;
4 addl $5, %eax //将当前寄存器eax中的内容+5,即eax=14;
5 popl %ebp //将当前esp中的内容存到寄存器ebp中,即ebp=1984,esp+4=1976;
6 ret //相当于popl %eip,将当前esp的内容存到eip,即eip=13,跳转到地址13;
f:
7 pushl %ebp //寄存器esp由地址1980开始-4,再将寄存器ebp的内容放入esp;
8 movl %esp, %ebp //将esp的值放入ebp中,即让ebp=1984;
9 subl $4,%esp // esp再-4,即esp=1980;
10 movl 8(%ebp),%eax //将ebp+8=1992中的内容放入寄存器eax中,即eax=9;
11 movl %eax,(%esp) //将eax中的内容9存入当前esp中;
12 call g //可以理解为pushl %eip; movl $g, %eip,即将当前寄存器eip的值13入栈,将g函数所在的地址1存入eip寄存器中,然后跳转到g函数;
13 leave //相当于movl %ebp,%esp;popl %ebp;将ebp的内容存到esp中,即esp=1984,再将当前esp中的内容存到寄存器ebp中,即ebp=1996,esp+4=1988;
14 ret //将当前esp的内容存到eip,即eip=20,跳转到地址20;
main:
15 pushl %ebp //寄存器esp由栈底2000开始-4,再将寄存器ebp的内容放入esp;
16 movl %esp, %ebp //将esp的值放入ebp中,即让ebp=1996;
17 subl $4,%esp //esp再-4,即esp=1992;
18 movl $9, (%esp) //将9存入esp中,即栈地址1992中存入9;
19 call f //可以理解为pushl %eip; movl $f, %eip,即将当前寄存器eip的值20入栈,将f函数所在的地址7存入eip寄存器中,然后跳转到f函数;
20 addl $3, %eax //将当前寄存器eax中的内容+3,即eax=17;
21 leave //将ebp的内容存到esp中,清空堆栈;
22 ret
又因为X86是满递减堆栈,所以堆栈的工作方式是先往低地址增长,再进行操作,首先从main函数开始分析,见函数注释;堆栈的变化见下表1-1:
实验总结:
由于汇编语言是最接近机器语言的,所以高级语言需要通过编译器编译成汇编语言,然后再由计算机翻译成机器语言开始运行操作的。而程序的执行都是通过一些寄存器与存储器进行交互操作完成的。上面的例子就是一个很好的说明
作者:叶涛
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
下面我通过一个小小的例子来为大家分析一下:首先是编写一段简单的C语言程序,如下图所示:
然后我们把它反编译成汇编语言,因为汇编语言是最接近机器语言的,如图:
接下来我们通过这段汇编语言来分析这段C语言是怎么运行的:
g:
1 pushl %ebp //寄存器esp由地址1976开始-4,再将寄存器ebp的内容放入esp;
2 movl %esp, %ebp ///将esp的值放入ebp中,即让ebp=1972;
3 movl 8(%ebp), %eax //将ebp+8=1980中的内容放入寄存器eax中,即eax=9;
4 addl $5, %eax //将当前寄存器eax中的内容+5,即eax=14;
5 popl %ebp //将当前esp中的内容存到寄存器ebp中,即ebp=1984,esp+4=1976;
6 ret //相当于popl %eip,将当前esp的内容存到eip,即eip=13,跳转到地址13;
f:
7 pushl %ebp //寄存器esp由地址1980开始-4,再将寄存器ebp的内容放入esp;
8 movl %esp, %ebp //将esp的值放入ebp中,即让ebp=1984;
9 subl $4,%esp // esp再-4,即esp=1980;
10 movl 8(%ebp),%eax //将ebp+8=1992中的内容放入寄存器eax中,即eax=9;
11 movl %eax,(%esp) //将eax中的内容9存入当前esp中;
12 call g //可以理解为pushl %eip; movl $g, %eip,即将当前寄存器eip的值13入栈,将g函数所在的地址1存入eip寄存器中,然后跳转到g函数;
13 leave //相当于movl %ebp,%esp;popl %ebp;将ebp的内容存到esp中,即esp=1984,再将当前esp中的内容存到寄存器ebp中,即ebp=1996,esp+4=1988;
14 ret //将当前esp的内容存到eip,即eip=20,跳转到地址20;
main:
15 pushl %ebp //寄存器esp由栈底2000开始-4,再将寄存器ebp的内容放入esp;
16 movl %esp, %ebp //将esp的值放入ebp中,即让ebp=1996;
17 subl $4,%esp //esp再-4,即esp=1992;
18 movl $9, (%esp) //将9存入esp中,即栈地址1992中存入9;
19 call f //可以理解为pushl %eip; movl $f, %eip,即将当前寄存器eip的值20入栈,将f函数所在的地址7存入eip寄存器中,然后跳转到f函数;
20 addl $3, %eax //将当前寄存器eax中的内容+3,即eax=17;
21 leave //将ebp的内容存到esp中,清空堆栈;
22 ret
又因为X86是满递减堆栈,所以堆栈的工作方式是先往低地址增长,再进行操作,首先从main函数开始分析,见函数注释;堆栈的变化见下表1-1:
实验总结:
由于汇编语言是最接近机器语言的,所以高级语言需要通过编译器编译成汇编语言,然后再由计算机翻译成机器语言开始运行操作的。而程序的执行都是通过一些寄存器与存储器进行交互操作完成的。上面的例子就是一个很好的说明
作者:叶涛
《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
相关文章推荐
- poj 1273 Drainage Ditches 经典网络流 Dinic算法
- atitit.跨架构 bs cs解决方案. 自定义web服务器的实现方案 java .net jetty HttpListener
- atitit.跨架构 bs cs解决方案. 自定义web服务器的实现方案 java .net jetty HttpListener
- atitit.跨架构 bs cs解决方案. 自定义web服务器的实现方案 java .net jetty HttpListener
- 《数据结构》带头结点单链表的合并
- 深度学习材料:从感知机到深度网络A Deep Learning Tutorial: From Perceptrons to Deep Networks
- 中国计算机学会CCF推荐国际学术会议和期刊目录(PDF版,2015年)
- 深度学习材料:从感知机到深度网络A Deep Learning Tutorial: From Perceptrons to Deep Networks
- HDU 3549 网络最大流再试
- 关于AsyncHttpClient的cz.msebera.android.httpclient.Header
- POJ 1273 网络流(最大流)模板
- linux内核分析作业:以一简单C程序为例,分析汇编代码理解计算机如何工作
- 深入理解计算机系统-之-内存寻址(六)--linux中的分页机制
- 中国计算机学会CCF推荐国际学术会议和期刊目录(PDF版,2015年)
- 中国计算机学会CCF推荐国际学术会议和期刊目录-交叉/综合/新兴
- 中国计算机学会CCF推荐国际学术会议和期刊目录-人机交互与普适计算
- 中国计算机学会CCF推荐国际学术会议和期刊目录-计算机科学理论
- 中国计算机学会CCF推荐国际学术会议和期刊目录-软件工程/系统软件/程序设计语言
- 中国计算机学会CCF推荐国际学术会议和期刊目录-网络与信息安全
- 中国计算机学会CCF推荐国际学术会议和期刊目录-计算机网络