汇编语言研究试验报告.docx
《汇编语言研究试验报告.docx》由会员分享,可在线阅读,更多相关《汇编语言研究试验报告.docx(18页珍藏版)》请在冰豆网上搜索。
汇编语言研究试验报告
研究实验一
搭建一个精简的C语言开发平台
一、研究目的
1.通过搭建C语言开发平台,认识到汇编语言对于深入理解其他领域知识的重要性。
2.对前面所学习的汇编知识进行融合贯通。
3.对用研究的方法进行学习进行体验
4.培养自己独立研究问题的能力。
二、研究原理
我们要搭建一个精简的C语言开发平台,必须要对C语言开发环境有一个清晰的认识了解。
TC2.0软件里有很多子文件和文件夹,而我们的目的是搭建一个精简的C语言开发平台,顾名思义就是要找出我们编译连接程序必须的文件,其他的文件就可以不要。
我们可以在程序编译连接中,根据出现的错误,一步一步去把我们程序必须的文件夹找出来。
三、研究步骤和过程
1.安装TC2.0在D盘根目录下,文件名为“TC2.0”。
2.在C盘根目录下建立一个文件夹“minic”用来存放我们已知解决问题要有的程序和文件。
在DOC环境c:
\mdminic
下,输入下面的指令:
3.把TC.EXE文件拷贝到minc文件夹里,具体操作如下:
在DOC中,minic目录下输入如下指令:
Copyd:
\tc2.0\tc.exe
4.打开TC2.0输入程序,保存,其文件为“WO.C”同时设置TC2.0的工作路径,如下图
设置后,保存好。
进行编译:
5.
编译成功显示:
生成文件WO.OBJ
6.连接:
出现错误,显示连接错误:
不能打开C0S.OBJ文件
7.查找C0S.OBJ文件,复制到文件夹minic
8.按照步骤6和7的方法,连续找出缺失的必须文件,拷贝到minic文件夹,直到成功生成WO.EXE文件,文件夹里有如下图的文件:
minic完成后
遇到的问题与总结四、1.在把TC2.0中的内容拷贝到minic文件时,自己指令输错了,后来通过多次试验终于成功了,至此发现自己对DOC的很多指令很不熟悉,今后还的加强在这方面的学习。
2.在找C0S.OBJ时把其中的“0”看成是字母‘o',导致一直找不到文件,疑惑了不久,后来去查找TC2.0文件夹,才发现其中的是数字0不是字母o.
通过这个问题感觉自己还不细心,做程序最重要就是要非常细心,不能出一点擦错。
3.WO.EXE文件生成了,自己去验证了下,发现在程序开始加一个“#include<>”就识别不了了。
这个精简的C语言开发平台局限性很大。
4.自己研究了一下,tc里的路径设置,tc保存路径需要生成TCCONFIG.TC文件和TCPICK.TCP文件,这两个文件默认放在C旁的根目录下。
研究实验二
使用寄存器
一、研究目的
1.对前面所学习的汇编知识进行融合贯通。
2.对用研究的方法进行学习进行体验
3.培养自己独立研究问题的能力。
二、研究步骤和思考
1.编写一个程序yan2.c
中。
yan2.exe文件,保存在minic,生成了编译连接yan2.c2.用Debug加载yan2,exe之后,用u命令查看其机器码和汇编代码。
自己想
了下没找到对应的机器码。
.
3.找main函数在代码段中的偏移地址。
在tc中输入,然后编译连接;
在DOS运行他wo.exe,得到main的偏移地址是1fah
自己在别的程序中也打印了main的偏移地址,发现也是1fah。
由此我得出一个结论:
main的偏移地址是固定的。
对于为什么能打印main的偏移地址,我认为main就相当于一个标号,但这个标号在一定条件下是固定的,不能更改,我试了用别的字母代替main,编译出错。
4.用debug查看1fah处得指令
程序一一对应和C语言将函数实现为汇编语言中的子程序C验证:
5.
编写ur2.c,用DEBUG跟踪。
Call020b相当于调用f(void)
子程序返回,返回值放在了AX中为3。
证明了我们的设想是对的。
三、遇到的问题与总结。
1.第一次编写yan2.c时,我以为寄存器大小写一样可以,就把_AX写成了_ax发现编译错误了,证明了我的假设是错误的。
2.在用U查看yan2.exe的代码时,为什么代码不是从main的偏移地址开始的,而开始的那端代码是有什么作用类?
,这里有个疑问,有待研究下面的试验。
.
研究实验三
使用内存空间
研究目的四、语言中如何使用内存空间。
深入理解在C1.对用研究的方法进行学习进行体验.23.培养自己独立研究问题的能力。
研究过程和思考总结五、,编译连接编写程序um1.c1.
DEBUG察看,用'语句实现在屏幕中间显示一个绿色字符‘用一条2.Ca第一次编写了一下程序:
可以显示字符a,但颜色是白色,经分析AH肯定没送进内存空间中,后来经过思考才发现,char是字符型的只占一个字节,后来把程序改为:
显示一个绿色a,正确
3.编写程序:
思考问题,通过一步一步在Debug中察看,发现C语言将全局变量放在内存中,将局部变量放在了栈中,pushbpmovbp,sp含义,为了还原现场。
研究函数的返回值存放位置:
4.
编程:
把变量a,b分别赋值1,2用debug察看,可以发现:
C语言将函数的返回值放在了ax中,在这里返回值为3。
5.编程:
上面程序是向安全空间写入从‘0'到‘a'的8个字符,
第一条指令是宏定义,buffer后面()中的物理代替buffer,malloc(20)是向系统申请20个安全空间,while是循环指令。
六、体会与收获
通过做这个研究实验,我更加深刻地理解了在C语言中如何使用内存空间的。
研究实验四
不用main函数编程
研究目的七、.
1.对前面所学习的汇编知识进行融合贯通。
2.对用研究的方法进行学习进行体验
3.培养自己独立研究问题的能力。
八、研究步骤和思考结果
1.编写一个程序f.c
研究如何进行编译连接:
编译可以成功,连接出错。
显示错误:
这个错误可能与C0S。
obj有关系。
2.用link.exe对生成的obj文件进行连接,生成exe文件,加载,观察程序汇编代码,思考:
Debug用.
;个字节程序代码有f.exe1dh不能正常返回;研究发现f.exe。
函数的偏移地址是0000hfdebug加载m.c3.编程:
编译连接后用开始:
:
结束
思考总结:
m.exe总代码是0ec8h字节,m.exe可以正常返回,
函数指令一样,f函数和main
4.思考与结果:
用Debug对m.exe进行跟踪,找到对main函数进行调用的指令的地址为011a,
:
整个程序的返回是下面第一个ret:
5.研究main函数和c0s.obj的关系。
研究步骤:
1)用link.exe对c:
\minic目录下的c0s.obj进行连接,生成c0s.exe
2)用Debug查看cos.exe的汇编代码和m.exe的汇编代码,找到m.exe中的调用main函数的call指令的偏移地址,从这个偏移地址开始向后查看10条指令,然后用debug加载c0s.exe,从相同的偏移地址开始向后察看10条指令。
对两处得指令进行比较。
的汇编代码:
m.exe
C0s.exe的汇编代码:
结果分析和问题结果:
比较两处指令发现call后面的地址发生了变化,也就是说调用的子程序的偏移地址不一样。
Tc.exe把c0s.obj同用户.obj一起进行连接,生成.exe文件。
对main函数调用的指令和程序返回指令是c0s.obj提供的。
我们用link.exe可以连接c0s.obj来生成exe文件,然后用debug加载,这样就可以查看c0s.obj文件中的程序代码了。
经验证c0s.obj文件里有我们设想的代码。
,替代c0s.obj,然后编译为c0s.asm自己编写一个程序6.
c:
\minic目录下的c0s.obj。
如下:
用masm.exe编译之后生成了文件c0s.obj,然后把其拷c0s.obj。
贝到c:
\minic目录下,覆盖掉原来的7.在c:
\minic目录下,用tc.exe将f.c重新编译,连接,
生成f.exe。
成功地生成查看。
然后用debug了.exe文件。
的代码。
call0012指令就是去执行f.exe上图中
,向安全的f.c的基础上,写一个新的c0s.obj在新的8.
内存空间写入从“a”到“h”的8个字符。
分析,理解f.c。
程序f.c如下:
。
然后进行编译连接,成功生成了f.exe#define是宏定义,意思是把程序中的Buffer全部物理替换为((char*)*(intfar*)0x02000000),((char*)*(intfar*)0x02000000)表示地址为0x02000000处的内存中的内容,
Buffer=0;
;将地址为0x02000000的内存中的内容修改为0.
Buffer[10]=0;
把0赋值给ds:
[0+10],字节操作。
下面while是一个循环语句:
循环条件是:
Buffer[10]不等于8。
语句主体是:
把a到h的8个字符依次放到,[0],[1],…[7]里。
九、收获与感受
做完这个研究试验,我明白了在前几个试验中,如果没有main函数为什么不就不能生成exe文件,是因为TC函数一起连接,现在自己可main需要和c0s.obj中的.
以不用main函数,也可以编写C程序了,还学会了怎么自己编写c0s.obj文件。
研究实验五
函数如何接受不定数量的参数
十、研究目的
1.对前面所学习的汇编知识进行融合贯通。
2.对用研究的方法进行学习进行体验
3.培养自己独立研究问题的能力。
十一、研究步骤和思考结果
1.用c:
\minic下的tc.exe完成下面的试验,写一个程序a.c:
编译连接生成了exe文件,用debug查看,分析a.exe的汇编代码,思考问题:
main函数是如何给showchar传递是如何接受参数的?
showchar参数的?
从上图可以看出:
main函数通过栈给shorchar传递参数。
然后showchar就从栈里去取参数。
2.写一个程序b.c:
编译连接,用DEBUG察看b.exe的代码,
思考问题总结:
showchar函数把n中存的数作为显示字符的个数,当a=8时就结束输出。
在程序中showchar的第一个参数的偏移地址是_BP+4,
Printf函数是通过计数%c和%d的个数,知道参数个数的。
3.实现一个简单的printf函数,只需要支持“%c,%d”即可。
程序如下:
voidshow(char*str,...);
main()
{
show(%c+%d=%c,'d',203,'f');
printf(%c+%d=%c,'d',203,'f');
}
voidshow(char*str,...)
{intxianshi=160*20+6;charyu;intjishu=0;
charch;inti;char*p;
intc;inta=0;intb=0;
while(*str!
=0)
if(*str=='%'){
str++;{
if(*str=='c')
{
*(charfar*)(0xb8000000+xianshi+a+a)=*(int
*)(_BP+6+b+b);
a++;b++;
}
if(*str=='d')
{c=*(int*)(_BP+6+b+b);
if(c==0)
{*(charfar*)(0xb8000000+xianshi+a+a)=0x30;
a++;
}
while(c!
=0)
{
yu=c_x0010_;c=c/10;
*p++=yu;jishu++;
}
for(;jishu>0;jishu--)
{
*(charfar*)(0xb8000000+xianshi+a+a)=*(p-1)+0x30;
a++;*p--;
}b++;
}
}
else
{
*(charfar*)(0xb8000000+xianshi+a+a)=*str;
a++;
}
str++;
}
}
编译连接然后运行显示如下:
第二行是printf()函数的输出,
最后一行是show函数的输出。
收获与感受。
十二、.
这个是实验是,五个实验中用是最久的,虽然明白了些printf函数的算法,但是由于以前没怎么学习C语言,所以在写程序过程中遇到了很多困难,可谓是一波三折啊。
编译过程出了很多错误,最后通过查阅资料,请教他人,终于可以做到零错误了。
我觉得这个研究实验为以后我们学习C语言打下了基础。