电子科技大学 软件开发环境 实验报告.docx
- 文档编号:9462422
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:39
- 大小:241.99KB
电子科技大学 软件开发环境 实验报告.docx
《电子科技大学 软件开发环境 实验报告.docx》由会员分享,可在线阅读,更多相关《电子科技大学 软件开发环境 实验报告.docx(39页珍藏版)》请在冰豆网上搜索。
电子科技大学软件开发环境实验报告
电子科技大学
实验报告
学生姓名:
郭小明学号:
一、实验室名称:
主楼A2-412
二、实验项目名称:
软件开发环境试验-----Huffman编码实验
3、实验原理:
分割函数的三项原则
分割函数的三项原则包括:
与其写注释,不如写函数;重复就是罪恶;函数不要超过50行至70行。
关于分割函数三原则的具体含义,请见教材和课堂教学PPT关于电话本的内容。
这里不再赘述。
Huffman编码的基本原理
本实验要求使用Huffman编码算法,实现对文件的压缩和解压。
因此,我们首先介绍huffman的编码算法。
Huffman编码是一种可变长编码方式,是由美国数学家DavidHuffman创立的,是二叉树的一种特殊转化形式。
编码的基本原理是:
将使用次数多的代码转换成长度较短的编码,而使用次数少的代码则可以使用较长的编码,并且保持编码的唯一可解性。
指导书试验原理部分较多,在这里就不做粘贴复制了。
四、实验目的:
本实验总体目的是,通过使用huffman编码算法从而实现文件的压缩和解压,以达到使学生掌握并灵活运用分割函数的三项原则。
5、实验内容:
本实验要求实现一个exe程序。
这个程序按照huffman编码方式,同时包含了压缩功能和解压功能。
用户通过以下命令进行压缩:
C:
\>–cuncompress_filenamecompress_filename
上述命令中,是程序名,-c表示要进行压缩。
uncompress_filename是要压缩的文件名,可以包含路径信息,而compress_filename是压缩之后的文件名,同样可以包含路径信息。
用户可以通过如下命令进行解压:
C:
\>–ucompress_filenameuncompress_filename
上述命令中,-u表示要执行解压命令。
compress_filename是要解压的文件名,可以包含路径信息;uncompress_filename就是解压后所得到的文件,同样可以包含路径信息。
提示:
在实现程序时,需要考虑如何存储huffman树或者编码表或者词频表等等。
本实验要求实现两个版本的程序,一是C语言版本的,二是C++版本的。
对这两个版本的要求如下:
●对于每一个版本的程序,需要在实验报告中给出函数调用关系图、流程处理关系图以及它们的文字说明等内容;
●对于每一个版本的程序,都需要在实验报告中给出源代码。
为了便于查重,代码中注释的比例要占到总行数的20%;
●C++版本的程序,需要给出类关系图。
实验报告的评分标准,包括以下几个方面:
●实验报告是否规范
●实验报告内容是否详实
●实验报告中是否包含了函数调用图、流程图、类图以及它们的文字说明
●实验报告中的代码注释是否达到要求
●程序是否正确无误
●程序是否严格按照分函数的原则编写
●C++版本的程序类关系的耦合度如何
●程序实现是否考虑了大文件情况
六、实验器材(设备、元器件):
PC机,vs2008软件平台。
七、实验数据及结果分析:
代码见附件。
huffmanForC
文件中函数列表如下:
.........
...........
#sum_bit##count#
*/
voidfreToFile(intcode[],HCode*HC)
..............................
jmp整个多分支流程语句后的指令地址
}
elseif()
cmp操作数1操作数2
jxx地址(如果不符合if条件就跳转到下一个if条件处再进行比较)
{
................................
jmp整个多分支流程语句后的指令地址
}
elseif()
cmp操作数1操作数2
jxx地址(如果不符合if条件就跳转到下一个if条件处再进行比较)
{
................................
jmp整个多分支流程语句后的指令地址
}
elseif()
cmp操作数1操作数2
jxx地址(如果不符合if条件就跳转到else条件处再进行比较)
{
.................................
}
else
jmp整个多分支流程语句后的指令地址
{
..................................
}
循环的反汇编
通过实验指导书当中给出的代码清单9的反汇编结果和分析,给出for循环反汇编代码的规律如下:
for(inti=0;i<10;i++)
{
定义i变量,并进行初始化指令代码
jmpxxx跳转到A处执行
B:
执行计数变量递增操作
1.将变量imov到eax处
2.eax里内容递增1
3.再将eax里面内容mov到i的变量里
A:
cmp操作数1操作数2与循环结束条件做比较指令代码
jxxxxx如果仍旧满足条件,向下执行;否则跳转到C处向下执行
循环体指令代码
.....................
.....................
jmpxxx跳转到B处执行
}
C:
代码清单10
while循环的代码示例:
int_tmain(intargc,_TCHAR*argv[])
{
inti=0;
intj=0;
while(i<10)
{
j++;
i++;
}
return0;
}
代码清单10的反汇编结果:
inti=0;
0025138Emovdwordptr[ebp-8],0
intj=0;
00251395movdwordptr[ebp-14h],0
while(i<10)
0025139Ccmpdwordptr[ebp-8],0Ah
002513A0jge002513B6
{
j++;
002513A2moveax,dwordptr[ebp-14h]
002513A5addeax,1
002513A8movdwordptr[ebp-14h],eax
i++;
002513ABmoveax,dwordptr[ebp-8]
002513AEaddeax,1
002513B1movdwordptr[ebp-8],eax
}
002513B4jmp0025139C
return0;
002513B6xoreax,eax
在代码清单10当中,在地址0025138E处movdwordptr[ebp-8],0将[ebp-8]设置为0,即将i设置为0;同理在地址00251395处movdwordptr[ebp-14h],0将[ebp-14]设置为0,即将j设置为0;
在地址0025139C处cmpdwordptr[ebp-8],0Ah,将i的值与10做比较,在地址002513A0处
jge002513B6如果i小于10,则继续向下执行,若i>=10则跳转到002513B6处执行(即返回语句),若继续向下执行,则002513A2002513A5002513A8三地址处的指令对j进行加一操作,002513AB
002513AE002513B1对i进行加一操作;在002513B4jmp0025139C跳转回cmp的指令处继续执行。
通过代码清单10的反汇编结果,while语句的反汇编代码规律
while()
A:
cmp操作数1操作数2while循环结束条件做比较
jxxB若不符合条件则,跳转到B处继续执行,若符合,则顺序执行循环体
{循环体指令
....................................
....................................
....................................
}
jmpA跳转到A处继续执行
B:
....................................
代码清单11
int_tmain(intargc,_TCHAR*argv[])
{
intj=0;
inti=0;
do
{
j++;
i++;
}
while(i<10);
return0;
}
代码清单11的反汇编结果:
intj=0;
0019138Emovdwordptr[ebp-8],0
inti=0;
00191395movdwordptr[ebp-14h],0
do
{
j++;
0019139Cmoveax,dwordptr[ebp-8]
0019139Faddeax,1
001913A2movdwordptr[ebp-8],eax
i++;
001913A5moveax,dwordptr[ebp-14h]
001913A8addeax,1
001913ABmovdwordptr[ebp-14h],eax
}
while(i<10);
001913AEcmpdwordptr[ebp-14h],0Ah
001913B2jl0019139C
return0;
001913B4xoreax,eax
}
在代码清单11当中,在地址0019138E处将[ebp-8]设置为0,即将j设置为0,在地址00191395处,将00191395设置为0,即将i设置为0.在地址0019139C0019139F001913A2三个地址处执行j增1的操作,在001913A5001913A8001913AB三个地址处执行i增1的操作。
在地址001913AE处执行循环条件比较指令
cmpdwordptr[ebp-14h],0Ah
在接下来的001913B2jl0019139C这条指令当中,如果操作数1即i小于操作数2即10,就跳转到0019139C地址处继续执行,否则向下继续执行。
do-while循环的反汇编代码规律:
do
{循环体指令代码
A:
..........................................
..........................................
..........................................
..........................................
}while();
cmp操作数1操作数2do------while循环条件判断语句
jxxA如果符合条件的话,就跳转到A处的循环体部分开始执行,否则继续向下执行
电子科技大学
实验报告
学生姓名:
郭小明学号:
一、实验室名称:
主楼A2-412
二、实验项目名称:
软件开发环境实验三:
函数调用栈帧布局
三、实验原理:
编译器对函数调用的支持,通常情况下都会使用栈。
例如使用栈传递传参,保存函数返回地址。
另外,局部变量也通常位于栈上。
VisualStudio2008为了防止栈上局部数组溢出,又采取了特殊的保护措施。
本实验就需要通过观察栈帧布局,来了解这些保护措施。
本实验的环境是VisualStudio2008。
四、实验目的:
本实验总体目的是,通过使用VisualStudio2008查看函数调用时参数、局部变量等在栈上的分布情况,以达到掌握函数调用时栈帧布局的目的。
六、实验器材(设备、元器件):
PC机,VS2008软件平台。
7、实验步骤:
在源文件中,编写如下代码。
在源文件中,编写如下代码。
voidf()
{
}
intmain()
{
f();
return0;
}
得到反汇编代码如下:
voidf()
{
008D13A0pushebp
008D13A1movebp,esp
008D13A3subesp,0C0h
008D13A9pushebx
008D13AApushesi
008D13ABpushedi
008D13ACleaedi,[ebp-0c0h]
008D13B2movecx,30h
008D13B7moveax,0CCCCCCCCh
008D13BCrepstosdwordptres:
[edi]
}
008D13BEpopedi
008D13BFpopesi
008D13C0popebx
008D13C1movesp,ebp
008D13C3popebp
008D13C4ret
在实验报告中,需要给出代码清单2中反汇编代码的解释。
其中stos指令的含义是:
将eax的值放在[edi]中,之后在这里将edi的值加4。
repstos的含义就是循环执行stos,直到ecx为0,每次循环ecx都会减1。
根据代码清单2,以及内存映像(调式->窗口->内存)可画出栈帧的布局,即图2。
图2无局部变量时的布局
从图2可以知道,即使没有任何局部变量,栈上仍然有0xc0个字节的0xcc存在。
这个是为了检测是否有溢出而写的。
代码清单2的解释:
在008D13A0地址处将ebp的值压入堆栈,并在008D13A1地址处将现在栈顶esp的值赋给ebp,然后再008D13A3处将esp的值减去0C0h,此时栈又向下面生长了0C0h个单位。
然后在008D13A9008D13AA008D13AB三个地址处依次将ebx,esi,edi三个值压入堆栈。
008D13ACleaedi,[ebp-0C0h],在008D13AC地址处,将ebp-0C0h这个地址值赋给edi。
008D13B2movecx,30h
将ecx的值赋为30h,在008D13B7moveax,0CCCCCCCCh,处将eax的值赋值为0CCCCCCCCh,
然后执行stos指令,将eax的值放在[edi]中,之后在这里将edi的值加4。
repstos的含义就是循环执行stos,直到ecx为0,每次循环ecx都会减1。
然后edi,esi,ebx依次出栈,再之后将原来保存在ebp中的esp的值重新赋给esp,在将ebp出栈,就还原了现场。
在源文件中,编写如下代码:
#include""
voidf()
{
inti=0;
}
int_tmain(intargc,_TCHAR*argv[])
{
f();
return0;
}
并且经过反汇编获得如下代码清单4:
voidf()
{
002513A0pushebp
002513A1movebp,esp
002513A3subesp,0CCh
002513A9pushebx
002513AApushesi
002513ABpushedi
002513ACleaedi,[ebp-0CCh]
002513B2movecx,33h
002513B7moveax,0CCCCCCCCh
002513BCrepstosdwordptres:
[edi]
inti=0;
002513BEmovdwordptr[i],0
}
002513C5popedi
002513C6popesi
002513C7popebx
002513C8movesp,ebp
002513CApopebp
002513CBret
在实验报告中,需要给出代码清单4中反汇编代码的解释。
根据代码清单4,以及内存映像(调式->窗口->内存)可画出栈帧的布局,即图3。
图3只有一个整型局部变量时的布局
从图3可知,当增加一个inti时,栈帧大小增加了12字节,即0x0c。
这包括i本身的4字节,然后是i上方的4字节0xcccccccc和i下方的4字节0xcccccccc。
代码清单4的解释:
代码清单4的实现步骤总体类似于代码清单2,也是首先将ebp压栈,然后将esp保存进ebp,有所变化的就是这次是将esp的值减去0CCh,比上一次无局部变量的时候多了0Ch,然后仍旧是压ebx,esi,edi的值入栈,之后仍旧是将002B13ACleaedi,[ebp-0CCh]ebp-0CCh地址值赋给edi,之后将033h赋值给ecx,之后执行stos指令,仍旧是将ebp与ebx之间的堆栈字节通通赋值为0xcc。
在之后将i的值赋值为0,然后同样是出栈和恢复地址。
在实验报告中,需要分别给出只有一个char类型局部变量、只有一个short类型局部变量,以及只有一个double类型局部变量时栈帧的布局。
即代码清单5、代码清单6、代码清单7中f函数所对应的栈帧布局。
下面是chari=0;的反汇编代码清单5:
(注意右键显示符号名)
voidf()
{
00AE13A0pushebp
00AE13A1movebp,esp
00AE13A3subesp,0CCh
00AE13A9pushebx
00AE13AApushesi
00AE13ABpushedi
00AE13ACleaedi,[ebp-0CCh]
00AE13B2movecx,33h
00AE13B7moveax,0CCCCCCCCh
00AE13BCrepstosdwordptres:
[edi]
chari=0;
00AE13BEmovbyteptr[i],0
}
00AE13C2popedi
00AE13C3popesi
00AE13C4popebx
00AE13C5movesp,ebp
00AE13C7popebp
00AE13C8ret
返回地址
前帧ebp的值
0xcccccccccc
i
0xcccccccccccccc
0xcccccccc
原ebx的值
原esi的值
原edi的值
下面是shorti=0;的反汇编代码清单6:
voidf()
{
012313A0pushebp
012313A1movebp,esp
012313A3subesp,0CCh
012313A9pushebx
012313AApushesi
012313ABpushedi
012313ACleaedi,[ebp+FFFFFF34h]
012313B2movecx,33h
012313B7moveax,0CCCCCCCCh
012313BCrepstosdwordptres:
[edi]
shorti=0;
012313BExoreax,eax
012313C0movwordptr[ebp-10h],ax
}
012313C4popedi
012313C5popesi
012313C6popebx
012313C7movesp,ebp
012313C9popebp
012313CAret
返回地址
前帧ebp的值
0xcccccccc
0xcccccccc
i
0xcccc
0xcccccccc
原ebx的值
原esi的值
原edi的值
下面是doublei=0;的反汇编代码清单7:
voidf()
{
013C13A0pushebp
013C13A1movebp,esp
013C13A3subesp,0CCh
013C13A9pushebx
013C13AApushesi
013C13ABpushedi
013C13ACleaedi,[ebp+FFFFFF34h]
013C13B2movecx,33h
013C13B7moveax,0CCCCCCCCh
013C13BCrepstosdwordptres:
[edi]
doublei=0;
013C13BEfldz
013C13C0fstpqwordptr[ebp-1Ch]
}
013C13C3popedi
013C13C4popesi
013C13C5popebx
013C13C6movesp,ebp
013C13C8popebp
013C13C9ret
返回地址
前帧ebp的值
0xcccccccccc
i
0xcccccccc
原ebx的值
原esi的值
原edi的值
在源文件中,编写代码清单8:
voidf()
{
chari=0;
intj=0;
}
int_tmain(intargc,_TCHAR*argv[])
{
f();
return0;
}
并进行反汇编得到代码清单9:
voidf()
{
00D813A0pushebp
00D813A1movebp,esp
00D813A3subesp,0D8h
00D813A9pushebx
00D813AApushesi
00D813ABpushedi
00D813ACleaedi,[ebp+FFFFFF28h]
00D813B2movecx,36h
00D813B7moveax,0CCCCCCCCh
00D813BCrepstosdwordptres:
[edi]
chari=0;
00D813BEmovbyteptr[ebp-5],0
intj=0;
00D813C2movdwordptr[ebp-14h],0
}
00D813C9popedi
00D813CApopesi
00D813CBpopebx
00D813CCmovesp,ebp
00D813CEpopebp
00D813CFret
在实验报告中,需要给出代码清单9中反汇编代码的解释。
根据代码清单9,以及内存映像(调式->窗口->内存)可画出栈帧的布局,即图4。
图4代码清单9对应的栈帧布局
从图4可以看出,当增加一个局部变量时,这个局部变量的上方和下方都会填充若干
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 电子科技大学 软件开发环境 实验报告 软件 开发 环境 实验 报告