姓名:殷晓婷 学号:SA*****195
一、实验内容:
1.请使用Example的c代码分别生成.cpp,.s,.o和ELF可执行文件,并加载运行,分析.s汇编代码在CPU上的执行过程;
2.通过实验解释单任务计算机是怎样工作的,并在此基础上讨论分析多任务计算机是怎样工作的。
二、实验过程
1)分析.s汇编代码在CPU上的执行过程,Example的c代码(命名为test.c)如图1所示:
图1
gcc编译过程可划分为以下四个阶段:1.预处理阶段,生成文件*.cpp;2.编译成汇编代码,生成文件*.s;3.汇编成目标代码,生成文件*.o;4.链接成可执行文件
1.预处理
gcc -E -o test.cpp test.c
2.编译成汇编代码
gcc -x cpp-output -S -o test.s test.cpp
3.汇编成目标代码
gcc -x assembler -c test.s -o test.o
4.链接成可执行文件
gcc -o test test.o
图2
test.s汇编代码如图3所示:
图3
在CPU上的执行过程分析如下:
执行main函数,保存当前栈基地址(pushl %ebp),将esp寄存器的值赋给ebp寄存器(movel %esp,%ebp),即栈基指针与栈顶指针指向同一栈地址,再将栈顶指针向下移(sub $4,%esp),将8压栈(movl $8,(%esp)),调用函数f(),堆栈变化如下图所示:
ebp1(esp)—> |ebp| ebp1—> |ebp|
esp —> | 8 |
调用函数f(),保存eip寄存器的值,将f的地址赋给eip寄存器,执行f函数,保存当前栈基址(pushl %ebp),将esp寄存器的值赋给ebp寄存器(movl %esp,%ebp),再将栈顶指针向下移(sub $4,%esp),将%ebp+8栈地址中的值赋给eax寄存器(movl 8(%ebp),%eax),再将eax中的值保存到栈中(movl %eax,(%esp)),调用函数g(),堆栈变化如下图所示:
ebp1—>.|ebp| |ebp|
| 8 | | 8 |
esp —> |[eip]| |[eip]|
ebp2—>|ebp1|
esp—> | 8 |
调用函数g(),保存eip寄存器的值,将f的地址赋给eip寄存器,执行g函数,保存当前栈基址(pushl %ebp),将esp寄存器的值赋给ebp寄存器(movel %esp,%ebp),将%ebp+8栈地址中的值赋给eax寄存器(movl 8(%ebp),%eax),eax寄存器加3(addl $3,%eax),弹出值赋给ebp(popl %ebp),返回(pop %eip),堆栈变化如下图所示:
|ebp| |ebp|
| 8 | | 8 |
|[eip]| |[eip]|
|ebp1| ebp2—> |ebp1|
| 8 | esp —> | 8 |
|[eip]|
ebp3(eip)—>|ebp2|
返回到f函数,继续执行,将ebp的值赋给esp,弹出值赋给ebp(leave),返回(pop %eip),堆栈变化如下图所示:
ebp1—> |ebp|
esp —> | 8 |
返回到main函数,继续执行,eax寄存器加1(addl $1,%eax),leave,ret,最终eax寄存器中的值为13。
2)单任务和多任务计算机的工作原理
单任务:当任务的程序代码放入内存时,CPU一条语句一条语句的执行,执行函数时,如遇到调用函数,则通过栈先把当前环境保存,再执行调用函数,新函数对应一个逻辑上的新栈。依次类推,直到程序执行完。任务完成。
多任务:多任务计算机将多个任务分时执行,通过CPU时间片轮转,分给每个任务特定的时间。执行任务1时,和单任务计算机的工作工程一样。当执行任务1的时间片到了时,保存当前环境,然后CPU转而执行任务2。这样循环,直到任务全被处理完。