汇编语言斐波那锲数列文档格式.docx
《汇编语言斐波那锲数列文档格式.docx》由会员分享,可在线阅读,更多相关《汇编语言斐波那锲数列文档格式.docx(11页珍藏版)》请在冰豆网上搜索。
Intb=fib(N)
Result=a+b;
由此可知几个重要实现地方:
a)保存现场:
N在一个fib函数里面是局部变量,当系统调用子程序时需要保存这个局部变量,在返回时需要恢复:
SUBTPROCNEAR
PUSHAX
PUSHBX
…….
POPBX
POPAX
SUBTENDP;
采用保存恢复寄存器的形式
b)参数传递:
其中的N在调用fib传参时是作为实参,在被调用函数中还需要被使用,这是参数的传递,这里采用通过数据区传递参数(同全局变量)
c)返回值:
最后的result在高级语言中是通过将result赋给一个临时变量(调用该函数的程序)然后释放result这个局部变量,在本程序中采用寄存器直接传递的方法,所以在Fib函数中将result赋给一个寄存器,然后不保存它,让其传递到上层调用函数中去。
3.课程设计中遇到的问题及解决方案
●遇到的问题
在编写斐波那契函数的过程中主要遇到了问题是保存现场的问题,在高级语言中,对子程序调用时,系统会自动为我们保存当前程序的现场指令地址,局部变量。
而在汇编中除了现场指令地址保存外,其他的工作都必须我们自己完成,所以在对子程序调用时,怎么保存当前的局部变量,怎么传递参数到将要调用的函数中去使用,都是很难理顺思路的地方。
●解决方案
第一:
明确哪些是局部变量,在调用完子程序返回时要恢复的。
第二:
局部变量作为实参,与被调用的子程序中的形参的区别。
第三:
确保有压栈就必须对应出栈,且系统的中断指令地址的保存与我们使用的栈是同一个栈
解决方案在上面已经写过,就没有在复述了
4.程序流程图
5.源程序及注释
DATASSEGMENT
message1db"
inputthenumber"
"
$"
NUM=18h;
修改此处获得第N项斐波那契数列值
Ndw0;
用于传参的N
DATASENDS
CODESSEGMENT
ASSUMECS:
CODES,DS:
DATAS
Mainprocfar
START:
pushds
subax,ax
pushax
movax,DATAS
movds,ax
movbyteptrN,NUM
callFIB;
调用Fib子程序
movdx,ax
;
callOutput_CTLF
callPrintOX;
将十进制转换为十六进制输出
movah,1
int21h;
等待退出屏幕
ret
Mainendp
;
outputCTLF
Output_CTLFprocNear
pushax
pushdx
movah,02h
movdl,0dh
int21h
movdl,0ah
int21h
popdx
popax
Output_CTLFendp
inputvalueindx
PrintOXprocnear
movcl,4
loop1:
pushcx
roldx,cl
movax,dx
popcx
andax,000fh
cmpax,000ah
jlLessThanA
addax,07h
LessThanA:
addax,30h
movdl,al
movah,2
looploop1
PrintOXendp
FIBprocnear;
FIB子函数
pushcx;
cx与bx为局部变量
pushbx
movcx,N;
使用N作为实参传参,cx为形参
cmpcx,1;
相当于if(N=<
1)
jleless_equal_1
deccx;
相当于N-1
movN,cx;
使用N作为实参传参
callFIB;
FIB(N-1)
movbx,ax
addax,bx;
ax中保存FIB(N-1)+FIB(N-2),并且作为返回值
jmpender
less_equal_1:
movax,1;
如果N<
=1result=1
ender:
popbx
FIBendp
CODESENDS
endstart
实验二统计学生成绩
设计10个学生的成绩分别为56、69、84、82、73、88、99、63、100和80分。
试编制程序分别统计低于60分、60-69分、70-79分、80-89分、90-99分及100分的人数,并存放到S5、S6、S7、S8、S9及S10单元中。
定义以x为数组名的含10个单元的一维数组,分别存放10个学生的成绩;
定义变量S5、S6、S7、S8、S9及S10,初始化为0,以存放各成绩阶段的人数,以上均以字为存储单元长度。
建立子程序SEARCH,用以查找学生成绩并进行各成绩阶段的人数统计,并在主程序中调用。
其中,统计应用公式——(成绩)/10-5)*2——根据成绩相s5的相对地址变化量来进行存储。
3.典型程序模块及典型编程技巧分析
子程序SEARCH(统计人数)
SEARCH:
MOVSI,0
NEXT:
MOVAX,x[SI]
MOVBX,10
DIVBL
MOVBL,AL
SUBBX,5
SALBX,1
INCS5[BX]
ADDSI,2
LOOPNEXT
RET
子程序PRINTMen人数
PRINTMen:
MOVAH,02H
INT21H
MOVDL,'
'
RET
编程技巧:
采用子程序方法,使程序更易分析,模块更清晰,利用循环和相对地址变化量来减少程序的冗余度,是其看起来精简和更易分析。
4.课程设计中遇到的问题及解决方法
1、对汇编语言编程的基本结构都不会
解决方法:
看书,多看几个程序,便熟悉了基本结构datasegment,codesegment等。
2、数组的地址分配方式很糊涂,其存储单元的长度与首地址的关系
请教老师同学,在多次练习小习题后,进行画图分析
3、子程序的使用方法
多看程序
4、公式的汇编语言转换
“心急吃不了”热豆腐,将大化小,化繁为易,一步步计算
5.程序流程图,程序清单和程序注释
子程序SEARCH
子程序返回
6.程序清单和注释
DATASEGMENT;
数据段开始
xDW56,69,84,82,73,88,99,63,100,80;
定义数组,以存放学生成绩
S5sDW0;
定义变量s5,表示分数50-59分统计结果
S6DW0;
定义变量s6,表示分数60-69分统计结果
S7DW0;
定义变量s7,表示分数70-79分统计结果
S8DW0;
定义变量s8,表示分数80-89分统计结果
S9DW0;
定义变量s9,表示分数90-99分统计结果
S10DW0;
定义变量s10,表示100分统计结果
DATAENDS;
数据段结束
CODESEGMENT;
代码段开始
MAINPROCFAR;
MAIN函数声明
ASSUMECS:
CODE,DS:
DATA
PUSHDS;
过程开始
SUBAX,AX
MOVAX,DATA
MOVDS,AX;
初始化
BEGIN:
MOVCX,10;
BEGIN函数开始
CALLSEARCH;
调用统计人数子程序
MOVDL,BYTEPTRS5
ADDDL,30H
CALLPRINT;
将分数50-59分统计结果赋值s5并输出
MOVDL,BYTEPTRS6
将分数60-69分统计结果赋值s6并输出
MOVDL,BYTEPTRS7
将分数70-79分统计结果赋值s7并输出
MOVDL,BYTEPTRS8
将分数80-89分统计结果赋值s8并输出
MOVDL,BYTEPTRS9
将分数90-99分统计结果赋值s9并输出
MOVDL,BYTEPTRS10
将分数100分统计结果赋值s10并输出
MAINENDP;
MAIN主程序结束
SEARCHPROCNEAR;
SEARCH子程序开始
MOVSI,0;
初始化地址变化量为0
NEXT:
MOVBX,10;
根据成绩计算相对S5的地址变化量
DIVBL;
计算公式((成绩)/10-5)*2送(BX)
MOVBL,AL;
(BH)保持为0不变
SUBBX,5;
只统计50分以上成绩
SALBX,1;
(BX)*2
INCS5[BX];
S5是S5,S6,S7,S8,S9和S10单元的首地址
LOOPNEXT
SEARCHENDP;
SEARCH子程序结束
PRINTPROCNEAR;
输出统计结果子程序
RET
PRINTENDP;
PRINT子程序结束
CODEENDS;
代码段结束
ENDSTART
收获与体会
汇编语言是一门低级语言,所以在程序设计的过程中我明显的感觉到一个词:
底层!
如,输入输出时要对每一位数值位进行处理,加深了对高级语言中输入输出格式的理解;
子程序调用时需要自己设计分析堆栈的空间的分配情况,让我明白保存现场的意义及实现方式;
使用变量时要仔细分配急度缺乏的寄存器资源,这也是程序优化的核心思想;
甚至是要考虑到变量因为类型的不同储存的方式也不同,以及使用很