计算机组成原理课内实验报告一Word文档下载推荐.docx
《计算机组成原理课内实验报告一Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《计算机组成原理课内实验报告一Word文档下载推荐.docx(12页珍藏版)》请在冰豆网上搜索。
![计算机组成原理课内实验报告一Word文档下载推荐.docx](https://file1.bdocx.com/fileroot1/2022-12/12/e115fc67-349e-4b3d-b20c-93e4f832c05b/e115fc67-349e-4b3d-b20c-93e4f832c05b1.gif)
汇编代码给出的方式是,每一句源程序语句后紧随相应的汇编代码。
第一列的数字表示的是当前汇编指令在内存中的地址,第二列表示的是当前汇编指令的机器码,第三列对应于当前汇编指令。
可以看出,每一句高级语言的实现,都可以分解成一句或多句汇编指令来执行,从汇编指令中我们可以看到寄存器、内存单元的变化,整个过程更透明。
五、实验步骤
●在VisualStudio下建立工程文件
⏹选择Win32ConsoleApplication;
输入工程名称;
⏹选择建立空工程;
⏹添加新源文件
●编写简单的C语言程序;
⏹设置断点;
⏹调试,打开汇编以及与其对应的机器代码;
✓按F5进入Debug模式;
✓按Alt+8进入汇编查看模式;
✓右键选中CodeBytes,查看查看机器代码;
●学习、查看C语言源代码、汇编代码及其相对应的机器代码;
六、设计思路与源代码
三个问题要求的程序都比较简单,不做过多解释。
基本的思路就是首先设计并写出源程序,然后经过设断点,调试,反汇编等步骤获取他相应的汇编程序代码。
并对汇编代码进行分析,同时对程序的执行结果做出判断和评价。
●问题一源代码:
●问题二源代码:
●问题三源代码:
七、实验结果以及相关分析
●问题一:
程序的汇编代码如下所示,各条语句后的解释是对汇编代码的逐条分析:
#include<
stdio.h>
intmax(inta,intb)
{;
以下过程为进入max函数前的准备工作。
000D13D0pushebp
;
把原来ebp的值压入堆栈保护起来。
000D13D1movebp,esp
把栈顶的值放在ebp中保存,此后ebp一般不变,此时ebp就是“当前函数堆栈”的基址,以便访问堆栈中的信息以及从当前函数栈顶返回到栈底。
000D13D3subesp,0C0h
保留变量空间长度。
把esp往下移动一个范围,等于划出一片空间用来存局部变量。
000D13D9pushebx
000D13DApushesi
000D13DBpushedi
把寄存器中原来的值压入堆栈保护起来。
000D13DCleaedi,[ebp-0C0h]
本来是要movedi,ebp-0c0h,但是mov不支持该操作;
所以对ebp-0c0h取内容,而lea把内容的地址,也就是ebp-0c0h加载到edi中。
目的是把保存局部变量的区域(从ebp-0c0h开始的区域)初始化成全;
部0cccccccch。
000D13E2movecx,30h
000D13E7moveax,0CCCCCCCCh
000D13ECrepstosdwordptres:
[edi]
初始化用于该函数的栈空间为0XCCCCCCCCh即从堆栈里所有的值均为0xCCCCCCCC。
if(a>
b)
000D13EEmoveax,dwordptr[a]
把a的值扩展成双字放入eax寄存器。
000D13F1cmpeax,dwordptr[b]
把eax寄存器中的值即a与b比较。
000D13F4jlemax+2Dh(0D13FDh)
如果a比b大则跳到地址为0D13FDh的语句。
returna;
000D13F6moveax,dwordptr[a]
把a的值扩展成双字大小存入eax寄存器。
000D13F9jmpmax+30h(0D1400h)
跳到地址为0D1400h的语句结束执行。
else
000D13FBjmpmax+30h(0D1400h)
returnb;
000D13FDmoveax,dwordptr[b]
把b的值扩展为双字大小存入eax寄存器。
}
000D1400popedi
000D1401popesi
000D1402popebx
000D1403movesp,ebp
000D1405popebp
000D1406ret
以上部分将压入堆栈保存起来的值重新弹出恢复程序执行前的状态。
voidmain()
{
000D1420pushebp
000D1421movebp,esp
000D1423subesp,0C0h
000D1429pushebx
000D142Apushesi
000D142Bpushedi
000D142Cleaedi,[ebp-0C0h]
000D1432movecx,30h
000D1437moveax,0CCCCCCCCh
000D143Crepstosdwordptres:
进入函数调用前的准备工作,同上,不做重复解释。
max(10,20);
000D143Epush14h;
将操作数20压入堆栈
000D1440push0Ah;
将操作数10压入堆栈
000D1442callmax(0D1118h);
调用max函数
000D1447addesp,8;
并将堆栈指针上移8
000D144Axoreax,eax
000D144Cpopedi
000D144Dpopesi
000D144Epopebx
000D144Faddesp,0C0h
000D1455cmpebp,esp
000D1457call__RTC_CheckEsp(0D113Bh)
000D145Cmovesp,ebp
000D145Epopebp
000D145Fret
以上部分将压入堆栈保存起来的值重新弹出恢复程序执行前的状态,并且返回值。
●问题二:
0040102055pushebp
004010218BECmovebp,esp
0040102383EC40subesp,40h
0040102653pushebx
0040102756pushesi
0040102857pushedi
004010298D7DC0leaedi,[ebp-40h]
0040102CB910000000movecx,10h
00401031B8CCCCCCCCmoveax,0CCCCCCCCh
00401036F3ABrepstosdwordptr[edi]
函数调用前的准备工作,同问题一,不做重复解释。
printf("
HelloWorld!
"
);
00401038686C2F4200pushoffsetstring"
(00422f6c)
将”HelloWorld”字符串的偏移地址压入堆栈,且其地址为00422f6c。
0040103DE87EC60000callprintf(0040d6c0)
调用printf函数。
0040104283C404addesp,4
恢复了调用printf前的堆栈状态。
004010455Fpopedi
004010465Epopesi
004010475Bpopebx
0040104883C440addesp,40h
0040104B3BECcmpebp,esp
0040104DE85E000000call__chkesp(004010b0)
004010528BE5movesp,ebp
004010545Dpopebp
00401055C3ret
●问题三:
执行结果如图所示:
该程序的汇编代码如下所示,各条语句后的解释是对汇编代码的逐条分析:
main()
0040101055pushebp
004010118BECmovebp,esp
0040101383EC48subesp,48h
0040101653pushebx
0040101756pushesi
0040101857pushedi
004010198D7DB8leaedi,[ebp-48h]
0040101CB912000000movecx,12h
00401021B8CCCCCCCCmoveax,0CCCCCCCCh
00401026F3ABrepstosdwordptr[edi]
进入函数调用前的准备工作,同问题一,不做重复解释。
inta;
floatb;
a*=a/=(a=7)-(b=4.5);
00401028DB45FCfilddwordptr[ebp-4]
将[ebp-4]单元的整数值压栈,即st(0)。
0040102BC745FC07000000movdwordptr[ebp-4],7
将整数7赋值到[ebp-4]单元。
00401032DB45FCfilddwordptr[ebp-4]
将[ebp-4]单元的整数值压入栈,即st
(1)。
00401035C745F800009040movdwordptr[ebp-8],40900000h
将浮点数4.5赋值到[ebp-8]单元(由于是浮点数,该数是32位形式)
0040103CD865F8fsubdwordptr[ebp-8]
st(0)-[ebp-8]差值,结果放在st(0)。
0040103FDEF9fdivpst
(1),st
st(0)/st(i),并把结果放在st(i),并执行一次出栈操作。
00401041E8C2010000call__ftol(00401208)
浮点转换整数指令,入口参数通过st传入,出口结果在eax,且弹出st
004010468945FCmovdwordptr[ebp-4],eax
004010498B45FCmoveax,dwordptr[ebp-4]
0040104C0FAF45FCimuleax,dwordptr[ebp-4]
a=a*a结果放到eax
004010508945FCmovdwordptr[ebp-4],eax
将结果存入内存单元。
a=%d,b=%f\n"
a,b);
00401053D945F8flddwordptr[ebp-8]
将[ebp-8]单元的值即b入栈
0040105683EC08subesp,8
将栈顶指针向下移动8,栈顶下移到b。
00401059DD1C24fstpqwordptr[esp]
将堆栈栈顶的数据传送到目标操作数中,并弹出栈顶
0040105C8B4DFCmovecx,dwordptr[ebp-4]
0040105F51pushecx
ecx中存储a
00401060681C604200pushoffsetstring"
(0042601c);
打印的参数设定压入堆栈
00401065E836000000callprintf(004010a0)
调用printf函数
0040106A83C410addesp,10h
0040106D5Fpopedi
0040106E5Epopesi
0040106F5Bpopebx
0040107083C448addesp,48h
004010733BECcmpebp,esp
00401075E856010000call__chkesp(004011d0)
0040107A8BE5movesp,ebp
0040107C5Dpopebp
0040107DC3ret
问题分析以及解决:
预期的结果是a=7.84,b=4.5。
在程序初始化时,eax被初始化为0CCCCCCCCh,转化为补码是-343597384,所以计算发生错误,与预期不相符合。
处理方法可以直接用汇编语言重写,也可以在C语言代码中,给a,b预定义的时候对其赋值并分配内存空间。
八、实验小结
由于硬件等许多因素,程序并非完全如预期执行。
硬件软件等许多因素都相互影响相互制约。
通过查看汇编代码,能对底层有一个更清晰的认识。
另外实验过程中接触了不少自己并不是很了解的知识,通过各种途径的查询和询问,解决了问题。
我们很难对各种知识都有一个全面而深刻的理解,然而具备解决问题的能力是很重要的一个方面。