大数阶乘与快速排序算法汇编教材.docx
《大数阶乘与快速排序算法汇编教材.docx》由会员分享,可在线阅读,更多相关《大数阶乘与快速排序算法汇编教材.docx(11页珍藏版)》请在冰豆网上搜索。
![大数阶乘与快速排序算法汇编教材.docx](https://file1.bdocx.com/fileroot1/2023-1/31/8aa3d62c-8141-4540-93e0-e515e55ff40c/8aa3d62c-8141-4540-93e0-e515e55ff40c1.gif)
大数阶乘与快速排序算法汇编教材
微机原理
课程设计说明书
设计题目:
大数阶乘与排序
专业
班级
学生
指导教师
2014年春季学期
一.课设目的与要求
1.课设目的:
检验和提高学生在汇编语言程序设计,微机原理与接口应用方面分析问题与解决问题的能力
2.题目要求:
1).要求实现用汇编语言编写设计一个求解大数的阶乘精确值的程序;采用字节型数组存放阶乘结果的每个数字位,采用逐位相乘,再对每一位规格化来实现;输出结成结果的位数及尾零的个数。
2).用汇编语言编写设计快速排序与希尔排序程序,注意合理使用堆栈,以避免堆栈溢出,进一步动态显示排序过程。
二.基本原理
1.大数阶乘原理设计:
我们在处理一个大于一定范围的数的阶乘时,无论使用什么类型去保存运算结果都必然会发生溢出,这势必会导致运算结果出错。
使用数组来模拟数字,这样无论结果数字有多大,只要数组的长度够长就能表示出来,用这个办法可以进行大数据的运算。
2.排序原理设计:
快速排序原理:
首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序。
三.架构设计
核心思想就是把计算结果每一位上的数字保存到一个数组成员中,例如:
把112保存至数组中,保存结果应该是
result[0]2
result[1]1
result[2]1
把整个数组看成一个数字,这个数字和一个数相乘的时候,需要每一位都和这个乘数进行相乘运算还需要把前一为的进位加上。
运算方法和小学数学是一样的,乘积的个位是当前位上应该表示的数字,10位以上的需要进位。
因为乘数不可能大于10000,所以乘数和一个小于10的书相乘的时候不会大于100000,再加上前一位的进位用一个int型数据来保持这个结果就没有问题。
写法如下:
int结果=result[x]*乘数+进位;
每一位的计算结果有了,把这个结果的个位数拿出来放到这个数组元素上:
result[x]=结果%10;
接下来的工作就是计算出进位:
进位=结果/10;
这样一位一位的把整个数组计算一遍,最后可能还有进位,用同样的方法,把进位的数值拆成单个数字,放到相应的数组元素中。
最后输出一下结果,从最高位吧数字打印一遍就OK了。
一趟快速排序的算法是:
1)设置两个变量i、j,排序开始的时候:
i=0,j=N-1;
2)以第一个数组元素作为关键数据,赋值给key,即key=A[0];
3)从j开始向前搜索,即由后开始向前搜索(j--),找到第一个小于key的值A[j],将A[j]赋给A[i];
4)从i开始向后搜索,即由前开始向后搜索(i++),找到第一个大于key的A[i],将A[i]赋给A[j];
5)重复第3、4步,直到i=j;(3,4步中,没找到符合条件的值,即3中A[j]不小于key,4中A[i]不大于key的时候改变j、i的值,使得j=j-1,i=i+1,直至找到为止。
找到符合条件的值,进行交换的时候i,j指针位置不变。
另外,i==j这一过程一定正好是i+或j-完成的时候,此时令循环结束)。
希尔排序原理:
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。
所有距离为d1的倍数的记录放在同一个组中。
先在各组内进行直接插入排序;然后,取第二个增量d24.方案实现与测试
大数阶乘源代码:
includeio32.inc
.data
infoMsgbyte'请输入你要求的阶乘',13,10,0
errorMsgbyte'你输入的数小于0',13,10,0
accountbyte'阶乘的位数为:
',13,10,0
zeroaccountbyte'尾零的个数为:
',13,10,0
inputnumdword0
bufferNumdword100000dup(0),0
tempdword0
arrayNumdword1
carrydword0
.code
start:
moveax,1
movbufferNum[0],eax
moveax,offsetinfoMsg
calldispmsg
callreadsid
movinputnum,eax
cmpeax,0
jlDONE;输入的数小于0;输入的数不小于0
movebx,2
OUTER:
cmpebx,inputnum
jgFINISH;完成计算外层循环用ebx
movecx,1
moveax,0
movcarry,eax
FLAG1:
cmpecx,arrayNum
jgOUTIN;大于1跳出内循环内层循环用ecx
moveax,ebx
mulbufferNum[ecx*4-4]
addeax,carry
adcedx,0;还要加进位标志,也就是说加了上一步的进位
pushebx
movebx,0ah
divebx
popebx
movbufferNum[ecx*4-4],edx
movcarry,eax
incecx
jmpFLAG1
OUTIN:
cmpcarry,0
jzFLAG2
moveax,1
addarrayNum,eax;所用到的数组的个数
movedx,0
moveax,carry
pushebx
movebx,0ah
divebx
popebx
pushedx
moveax,arrayNum
pushebx
movebx,04h
mulebx
popebx
subeax,4
popedx
movbufferNum[eax],edx;保存余数到数组
movedx,0
moveax,carry
pushebx
movebx,0ah
divebx
popebx
movcarry,eax
jmpOUTIN;循环保存余数直到进位只剩个位
FLAG2:
incebx
jmpOUTER
FINISH:
;输出结果
movecx,arrayNum
FLAG3:
cmpecx,0
jleOVER
moveax,bufferNum[ecx*4-4]
calldispsid
moveax,0
dececx
jmpFLAG3
DONE:
cmpedi,0
jeOVER
moveax,offseterrorMsg
calldispmsg
OVER:
calldispcrlf
MOVeax,offsetaccount
calldispmsg
MOVeax,arrayNum
calldispuid
calldispcrlf
movecx,1
movedi,0
zero:
moveax,bufferNum[ecx*4-4]
cmpeax,0
jneF0
incedi
incecx
cmpecx,arrayNum
jgeF0
jmpzero
F0:
MOVeax,offsetzeroaccount
calldispmsg
moveax,edi
calldispuid
calldispcrlf
exit0
endstart
快速排序源代码:
includeio32.inc
includelibmsvcrt.lib;这里是引入类库相当于#include了
printfPROTOC:
PTRDWORD,:
VARARG;声明一下我们要用的函数头
MAXSIZE=1000
.data
countdword0
arrBytesDWORDMAXSIZEdup(0)
szFormatBYTE"%d",09h,0
szFormat1BYTE0ah,0;换行
in_msgbyte'请输入排序数据(-1结束)',10,13,0
out_msgbyte'快速(降序)排序结果如下:
',10,13,0
noticebyte'.........testing........',10,13,0
.code
dumparrayPROCarray:
PTRDWORD,arrsize:
DWORD
moveax,offsetnotice
calldispmsg
movEBX,offsetarrBytes
movECX,arrsize
xorESI,ESI
Tag1:
pushecx
INVOKEprintf,OFFSETszFormat,DWORDPTR[EBX+ESI]
popecx
addESI,4
LOOPTag1
INVOKEprintf,OFFSETszFormat1
RET
dumparrayENDP
readInArrayprocpCount:
DWORD
xorebx,ebx
again:
moveax,offsetin_msg
calldispmsg
xoreax,eax
callreadsid
cmpeax,0
jlDONE
movarrBytes[4*ebx],eax
incebx
jmpagain
DONE:
movcount,ebx
ret
readInArrayendp
qsortPROCarray:
PTRDWORD,lowitem:
DWORD,highitem:
DWORD
LOCALpivot:
DWORD;定义局部变量
MOVEBX,array
MOVEDX,lowitem
MOVESI,lowitem
MOVEDI,highitem
CMPESI,EDI
JGETagEnd
MOVEAX,DWORDPTR[EBX+EDX*4]
MOVpivot,EAX
MOVEAX,EDI
SUBEAX,ESI
MOVECX,EAX
INCEDX
Tag1:
MOVEAX,pivot
CMPEAX,DWORDPTR[EBX+EDX*4]
JLTag2
JMPTag3
Tag2:
MOVEAX,DWORDPTR[EBX+EDX*4]
XCHGEAX,DWORDPTR[EBX+ESI*4+4]
MOVDWORDPTR[EBX+EDX*4],EAX
MOVEAX,DWORDPTR[EBX+ESI*4]
XCHGEAX,DWORDPTR[EBX+ESI*4+4]
MOVDWORDPTR[EBX+ESI*4],EAX
INCESI
Tag3:
INCEDX
LOOPTag1
DECESI
PUSHESI
INVOKEqsort,array,lowitem,ESI
POPESI
INCESI
INCESI
INVOKEqsort,array,ESI,highitem
TagEnd:
RET
qsortENDP
main:
invokereadInArray,addrcount
xoreax,eax
INVOKEdumparray,ADDRarrBytes,count
MOVEAX,count
DECEAX
INVOKEqsort,ADDRarrBytes,0,EAX
moveax,offsetout_msg
calldispmsg
INVOKEdumparray,ADDRarrBytes,count
RET
endmain
大数阶乘测试结果截图:
快速排序测试结果截图:
5.分析总结
经过了一周的努力,我们终于完成本次课设任务。
看似普普通通的题目真正动起手来还真心无从下手,困难重重。
比如说是大数阶乘,首先由于它和我们传统意义上计算阶乘有着很大的区别,所以接受一个新的理念就是一件难事,然后把其转换为程序代码的操作又是一大难事。
所以以后要多多动手,想的和做的还有很大区别。
总之我们这周收获挺大,复习了算法,熟悉了汇编。
六.参考文献
【1】钱晓捷,《微机原理与接口技术》,西安,机械工业出版社,2008年
【2】胡元义,《数据结构教程》,西安,西安电子科技大学出版社,2010年