[汇编版]冒泡排序、快速排序、堆排序
来源:互联网 发布:办公必备软件 编辑:程序博客网 时间:2024/05/19 02:19
代码下载
刚刚看完<Intel汇编程序语言设计>一书,用汇编写了几个基本的排序算法。编写的汇编函数代码都是是使用stdcall调用规范的,所以C语言工程也可以链接并调用这些函数的,怎么调用以后在再文章说明。另外,我把程序的不同模块放在不同的源文件中,使代码结构更清晰。和C编译器生成的汇编代码不同的是,为了效率最佳,内存操作最少,我在函数中都没有定义局部变量,大量使用寄存器,刚好算法不是太复杂,寄存器够用,坏处是代码可读性比较差了。程序的编译环境是VS2008,关于如何配制编译环境,可以参看我之前的文章<用Visual Studio 2008编写Win32汇编程序>。算法都是些基本的算法,就不多加说明,只是在程序中加了少许注释。我把几个算法都放在一个工程中,下面是工程中的源文件和简单介绍。
Head.inc
BubbleSort.asm
QuickSort.asm
HeapSort.asm
PrintNumber.asm
main.asm
包含文件:Head.inc
包含文件类似于C/C++的头文件,我们可以把引用的库函数,或者是其他源文件中定义的函数的声明放在里面。和C语言一样,包含文件中的函数声明告诉编译器,在这个源文件中我们没有这个函数的实现,但是你可以使用它,在Link时可以在其他.obj文件中找到它的实现。(此外,和C语言一样,如果被调用的函数在源代码中的位置调用者之后,也要在调用者上面的位置声明被调用的函数),下面是源代码:
ExitProcess PROTO,dwExitCode:DWORD;Windows APIGetStdHandle PROTO, nStdHandle:DWORD;Windows APIWriteConsoleA PROTO,hConsoleOutput:DWORD,;Windows APIlpBuffer:PTR DWORD,nNumberOfCharsToWrite:DWORD,lpNumberOfCharsWritten:PTR DWORD,lpReserved:PTR DWORDPrintNumber PROTO,inputNumber:SDWORDBubbleSort PROTO,pArray:PTR SDWORD,len : SDWORDHeapSort PROTO,pArray : PTR SDWORD,len : SDWORDAdjustHeap PROTO,pArray : PTR SDWORD,len : SDWORD,rootIndex : SDWORDQuickSort PROTO,pArray : PTR SDWORD,len : SDWORDQuickSortRecursion PROTO,pArray:PTR SDWORD,headIndex:SDWORD,tailIndex:SDWORD
源文件:BubbleSort.asm
和C语言一样,一个汇编源文件可以不包括入口点函数,而仅包含一些库函数的实现。但你也不能把一个函数定义放里面就完事了,它需要包含完整的格式,包括:TITLE,.386,.MODEL,.stack,.data,.code等部分,当然其中有些字段是可选的,但是必须是一个完整的合法的格式,源文件在末尾以END结尾。和C语言一样,每个源文件都会编译成一个.obj文件,最后所有的.obj文件由Linker生成.exe或者.dll文件。代码如下:
TITLE Bubble Sort.386.MODEL flat,stdcallINCLUDE Head.inc.codeBubbleSort PROC USES eax ebx ecx edx esi edi,pArray:PTR SDWORD,len : SDWORDmov EAX,pArraymov EDX,lensub EDX,2shl EDX,2;EAX=pArray,EDX=LastIndex-1,ESI=i,EDI=jL1:mov ESI,0mov EDI,4L2:mov EBX,[EAX+ESI]mov ECX,[EAX+EDI]cmp EBX,ECXjl L3;exchange two numbersmov [EAX+ESI],ECXmov [EAX+EDI],EBXL3:ADD ESI,4ADD EDI,4CMP ESI,EDXjle L2sub EDX,4cmp EDX,0jge L1retBubbleSort ENDPEND
源文件:QuickSort.asm
TITLE Quick Sort.386.MODEL flat,stdcallINCLUDE Head.inc.codeQuickSort PROC USES eax ,pArray:PTR SDWORD,len : SDWORDmov eax,lendec eaxINVOKE QuickSortRecursion,pArray,0,eaxretQuickSort ENDPQuickSortRecursion PROC USES eax ebx ecx esi edi,pArray : PTR SDWORD,headIndex : SDWORD,tailIndex : SDWORDmov EAX,pArraymov ESI,headIndexmov EDI,tailIndexmov EBX,[EAX+4*ESI];ESI = left pointer, EDI = right pointer, EBX= middle number L1:CMP ESI,EDIjge L4L2:cmp ESI,EDIjge L4cmp EBX,[EAX+4*EDI]jg E1dec EDIjmp L2E1:mov ECX,[EAX+4*EDI]mov [EAX+4*ESI],ECXinc ESIL3:cmp ESI,EDIjge L4cmp EBX,[EAX+4*ESI]jl E2inc ESIjmp L3E2:mov ECX,[EAX+4*ESI]mov [EAX+4*EDI],ECXdec EDIjmp L1L4:mov [EAX+4*ESI],EBXdec ESIinc EDIcmp ESI,headIndexjle L5INVOKE QuickSortRecursion,pArray,headIndex,ESIL5:cmp EDI,tailIndexjge END1INVOKE QuickSortRecursion,pArray,EDI,tailIndexEND1:retQuickSortRecursion ENDPEND
源文件:HeapSort.asm
TITLE Heap Sort.386.MODEL flat,stdcallINCLUDE Head.inc.codeHeapSort PROC USES eax ebx ecx edx esi edi,pArray : PTR SDWORD,len : SDWORD;build heap.;EAX=(len-2)/2mov EAX,lensub EAX,2shr EAX,1L1:INVOKE AdjustHeap,pArray,len,EAXDEC EAXCMP EAX,0jge L1;EAX=pArray, EBX=len, ECX=LastIndexmov EAX,pArraymov EBX,lenmov ECX,EBXdec ECX;begin to sortL2:cmp EBX,2jl END1mov ESI,[EAX+4*ECX]mov EDI,[EAX]mov [EAX+4*ECX],EDImov [EAX],ESIdec EBXdec ECXINVOKE AdjustHeap,pArray,EBX,0jmp L2END1:retHeapSort ENDP;----------------------------;AdjustHeap method used to adjust the binary-tree to a heap,;it assume that the initial condition is two sub-tree of the binary-tree are;heap but the root node is not biggest number.;----------------------------AdjustHeap PROC USES eax ebx ecx edx esi edi,pArray : PTR SDWORD,len : SDWORD,rootIndex : SDWORDmov EDX,rootIndexmov EAX,pArray;ESI = left sub-node index, EDI= right sub-node indexL1:mov ESI,EDXshl ESI,1inc ESIcmp ESI,lenjge END1mov EDI,ESIinc EDIcmp EDI,lenjge Exchangemov EBX,[EAX+4*ESI]mov ECX,[EAX+4*EDI]cmp EBX,ECXjge Exchangemov ESI,EDI;ESI=selected sub-node index(used to exchange with father node),;EDI= father node indexExchange:mov EDI,EDXmov EBX,[EAX+4*ESI]mov ECX,[EAX+4*EDI]cmp EBX,ECXjle END1mov [EAX+4*ESI],ECXmov [EAX+4*EDI],EBXmov EDX,ESI jmp L1END1:retAdjustHeap ENDPEND
源文件:PrintNumber.asm
该源文件用来在控制台打印数字,在WIN32汇编中,I/O操作不再使用中断,而是调用Windows API,这和C/C++,C#等高级语言是一样的。
TITLE Print Number.386.MODEL flat,stdcallINCLUDE Head.inc.codePrintNumber PROC USES eax ecx edx esi edi,inputNumber:SDWORDLOCALIsNegative:DWORD,outputBuffer[13]:BYTE,handle:DWORD,charWritten:DWORD;Decide if inputNumber is a negative number,;if it is, then IsNegative=1,inputNumber=-inputNumbermov IsNegative,0bt inputNumber,31jnc L1mov IsNegative,1neg inputNumber L1: mov EAX,inputNumbermov EDX,0;EDI will be the dividend.mov EDI,10lea ESI,outputBuffer;"line break" is insert at the end of outputBuffermov [ESI+11],BYTE PTR 0Ahmov [ESI+12],BYTE PTR 0Dh;ECX is the current index of outputBuffermov ECX,11;convert inputNumber to chars and store it into outputBuffer. L2: div edi add EDX,'0' dec ECX mov [ESI+ECX],DL mov EDX,0 cmp EAX,0 jnz L2 ;if inputNumber is negative number, insert '-' at front of string cmp IsNegative,0 jz L3 dec ECX mov [ESI+ECX],BYTE PTR '-' ;print the number L3: INVOKE GetStdHandle,-11 mov handle,eax lea EDX,charWritten ;ESI+ECX is the beginning of printed buffer. add ESI,ECX ;len of printed buffer = 13-ECX sub ECX,13 neg ECX INVOKE WriteConsoleA,handle,ESI,ECX,EDX,0 retPrintNumber ENDPEND
源文件:main.asm(入口点)
TITLE It is Main function.386.MODEL flat,stdcallINCLUDE Head.inc.data pArray SDWORD -2147483648,100,2147483647,-100,-100,2147483647len SDWORD ($-pArray)/4.codemain PROC USES eax ecx,INVOKE BubbleSort,ADDR pArray,len;INVOKE HeapSort,ADDR pArray,len;INVOKE QuickSort,ADDR pArray,len;Print Numbersmov EAX,OFFSET pArraymov ECX,lenP1:INVOKE PrintNumber,[EAX]ADD EAX,4LOOP P1INVOKE ExitProcess,0main ENDPEND main
发现我在文中总是说“和C语言一样”,这是我的一点感触。发现和其他高级语言,比如C#那样抽象程度非常高的语言,C语言和汇编真的很接近,C语言只是汇编的朴素的封装而已,C语言大约只是封装了对通用寄存器的操作,2者生成的.obj文件都是可以相互链接的。
- [汇编版]冒泡排序、快速排序、堆排序
- 冒泡排序,快速排序,堆排序比较
- 冒泡排序,快速排序,堆排序比较
- 冒泡排序 快速排序 插入排序 堆排序 选择排序
- 插入排序、选择排序、冒泡排序、快速排序、堆排序
- 排序总结JS版(冒泡排序、简单选择排序、快速插入排序、希尔排序、堆排序、快速排序)
- 拓扑排序, 快速排序, 冒泡排序, 堆排序, 二分查找
- 冒泡排序、归并排序、快速排序、堆排序
- 插入排序、冒泡排序、选择排序、Shell排序、快速排序、归并排序、堆排序
- C# 插入排序 冒泡排序 选择排序 快速排序 堆排序 归并排序 基数排序 希尔排序
- 冒泡排序 快速排序 选择排序 堆排序 直接插入排序 希尔排序 归并排序
- 冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序java实现
- 插入排序、希尔排序、冒泡排序、快速排序、选择排序、堆排序、归并排序
- 冒泡排序,插入排序,快速排序,归并排序,堆排序,选择排序,希尔排序
- 冒泡排序、快速排序、堆排序(Java)
- 快速排序 冒泡排序
- 快速排序、冒泡排序
- 冒泡排序 快速排序
- 为什么IEnumerator接口没有继承IDisposable接口
- C/C++堆栈指引
- ANDROID L——Material Design详解(视图和阴影)
- [Windbg笔记] 调试偶发性Bug
- 为什么要用作文
- [汇编版]冒泡排序、快速排序、堆排序
- 汇编与C互操作
- 两道设计模式的面试题
- How To Create USB Dos Boot Disk
- VB Script 如何使用XSD验证XML文档格式
- 批处理:修改COM端口号
- 瘟神的尾行 -- Rootkit技术发展史 (转载)
- 在程序中设置读、写、执行的硬件断点
- 将托管dll注入到非托管进程中