计算机程序的工作原理
2013-05-17 00:28
225 查看
计算机的工作原理-实验一
中科大-SA*****6178-叶*冬实验代码:
int g(int x)
{
return x+3;
}
int f(int x)
{
return g(x);
}
int main(void)
{
return f(x)+1;
}
分析过程:
对于一个c源程序来说,如果想运行,需要经过一下步骤:
1.预处理
2.编译
3.链接
在Ubuntu10 环境下,来一步一步分析:
1.预处理阶段:
预处理器根据源程序中以#号开头的关键字,在我们的程序中,引用了stdio.h的头文件,
预处理器会把该头文件的内容插入到程序中,得到了一个完整的C源程序。
在linux系统中使用的命令是:gcc -E -o example.cpp example.c。可以查看预处理之后
的程序。
2.编译阶段
编译器将预处理后的example.cpp文件编译成example.s,里面就包含了该程序对应的汇编
指令。
在linux系统中使用的命令是:gcc -s -o example.s example.cpp
然后汇编器进而将example.s翻译成机器语言指令,并且这些指令组成的有意义的二进制代码
按一定的格式存储在example.o中。
生成该文件的linux命令是:gcc -o example.o example.s
4.链接阶段:
在我们的程序中没有用到其他的库函数,或者其他文件中的函数,那么就不需要再链接其他的
.o文件。但是如果我们假设在该程序中有一个调用系统库函数的语句,那么程序在链接时就需要
把该被调用的函数的.o文件加载到内存中来,以使我们的程序完整。
最后在我们的例子中,就可以通过如下的linux命令得到可执行文件:gcc -o example example.o
那么,到现在为止,就可以直接运行了。
运行的命令如下:/example
实际运行结果如下:
mars@Mars:~$ gcc -E -o example.cpp example.c
mars@Mars:~$ gcc -x cpp-output -S -o example.s example.cpp
mars@Mars:~$ gcc example.o -o example
接下来通过反汇编代码分析该过程:
返回汇编代码如下:
析过程如下:
由于函数调用栈格式如下:
注:此图来自百度图片
在我们的例子中:
Main函数的过程分析:
0x08048362 <+0>: lea 0x4(%esp),ecx //保存上一栈帧栈顶地址
0x08048366 <+4>: and $0xfffffff0,%esp //调整栈指针的地址,与内存地址对齐
0x08048369 <+7>: pushl -0x4(%exx) //保存4(%esp)中的参数,以便将来恢复
0x0804836c <+10>: push ebpp //入栈保存上一栈帧的基地址
0x0804836d <+11>: mov %esp,ebp //将调用者函数的栈顶指针ESP赋值给被调函数的EBP作为被调函数的栈底
0x0804836f <+13>: push eax //保存存放在eax中的地址参数
0x08048370 <+14>: sub $0x4,%esp //栈顶指针由高地址向低地址移动四个字节,用来存放即将到来的参数
0x08048373 <+17>: movl $0x8,(%esp) //保存局部变量 8
0x0804837a <+24>: call 0x804834f <f> //调用子函数f ,子函数的入口地址即为0x804834f
0x0804837f <+29>: add $0x1,eax // eax=eax+1 ==12+1 =13
0x08048382 <+32>: add $0x4,%esp // 栈顶指针%esp向高地址移动四个字节,
0x08048385 <+35>: pop ecx // ecx出栈
0x08048386 <+36>: pop ebpp // ebp = %esp,esp= esp-4 ebp指向上一帧函数的基地址
0x08048387 <+37>: lea -0x4(ecx),%esp // 恢复上一栈帧栈顶地址
0x0804838a <+40>: ret // 消毁main函数整个栈
f函数的过程分析:
0x0804834f <+0>: push ebp // 入栈保存main函数的基地址,保存返回地址以便将来返回
0x08048350 <+1>: mov %esp,ebp // 开辟新的函数栈,开始子函数栈操作
0x08048352 <+3>: sub $0x4,%esp //栈顶指针由高地址向低地址移动四个字节
0x08048355 <+6>: mov 0x8(ebp),eax //调用main函数局部变量8(实参副本)并保存在寄存器eax中
0x08048358 <+9>: mov eax,(%esp) //开辟空间 保存实参副本
0x0804835b <+12>: call 0x8048344 <g> //调用子函数g
0x08048360 <+17>: leave //ebp = %esp,esp = esp-4 ebp指向main函数的基地址,释放地址空间
0x08048361 <+18>: ret // %eip执行调用main函数调用地址下一处地址0x0804837f
g 函数的过程分析:
0x08048344 <+0>: push ebp //入栈保存f函数的基地址,以便将来返回
0x08048345 <+1>: mov %esp,ebp //开辟新的函数栈
0x08048347 <+3>: mov 0x8(ebp),eax //传递参数 eax = ebp + 8 内存地址的值(8)
0x0804834a <+6>: add $0x3,eax //eax = eax +3 ==8+3=11
0x0804834d <+9>: pop ebp // ebp = %esp,esp =esp-4 ebp指向f函数的基地址
0x0804834e <+10>: ret //ret之前,esp指向的是返回f函数的下一个指令的地址,即上述说的leave地址,ret后,eip将指向leave地址 0x08048360,此时程序会跳转到该处执行
实验总结:
通过本次实验,
首先:熟悉了c源程序到可执行程序的一个生成流程;
再次:深刻了计算机内存在程序执行过程中发生的故事,明确了栈空间对于函数的正确工作的重要意义。
最后:加深了对单个任务下计算机系统的工作过程,为下一步学习多任务多进程协调工作做好了准备。
相关文章推荐
- 存储程序计算机的工作原理简介
- 从C简单程序的汇编代码入手,以理解计算机工作原理。
- linux_编译执行程序,分析计算机的工作原理
- 通过汇编一个简单的C程序,分析汇编代码理解计算机工作原理
- (ORACLE 10g)"未在本地计算机注册“OraOLEDB.Oracle.1”提供程序"问题解决
- 深入理解计算机系统(CSAPP)课程实验bomb程序炸弹实验日志(phase_6)
- (48) 剖析ArrayDeque / 计算机程序的思维逻辑
- 安装visio 2010:您的计算机上的Office 2003安装已损坏,安装程序无法继续。请删除或修复office 2003产品并重新运行安装程序
- 无法启动此程序,因为计算机中丢失VCRUNTIME140.dll 尝试重新安装此程序以解决此问题
- Mysql 下载与安装问题一:无法启动此程序,因为计算机丢失MSVCR120.dll
- 应用程序无法正常启动0xc000007b;无法启动此程序因为计算机中丢失D3DCOMPILER_43.dll
- 【转载】计算机程序的思维逻辑 (82) - 理解ThreadLocal
- 无法启动此程序,计算机丢失MSVCP110D.dll 解决方案
- Win7右击计算机管理打不开,提示找不到文件或没有关联的程序
- Oracle FAQ: 未在本地计算机上注册"OraOLEDB.Oracle"提供程序 (The 'OraOLEDB.Oracle' provider is not registered on the local machine) solution
- adobe 系列安装出现“安装程序检测到计算机重新启动操作可能处于挂起状态”---解决方法
- 科技、电子信息、计算机、程序
- 安装SQLSERVER2000时出现以前的某个程序安装已在安装计算机上创建挂起的文件操作
- sql-"以前的某个程序安装已在安装计算机上创建挂起的文件操作"
- 未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序解决办法