在进入大学之前知道计科院的会学一些编程语言,诸如C语言、C++之类。没想到到了大二居然学了一门叫汇编语言的课程。越学越发现汇编语言真是操蛋,什么寄存器呀,存储器呀乱七八糟的一大堆,搞个基本的a+b都那么麻烦。完全没有C语言那么好用。
然而存在即合理,汇编语言存在至今自然有它的用处。汇编语言最大的特点是直接和底层的硬件相关,能针对不同的硬件编程,且执行效率高。用于无法使用高级语言进行编程的地方,如电饭锅的温控程序。汇编语言还能写操作系统的内核,反汇编别人的程序。当然还有考试要用。
考试过后闲来无事写了个简单的、典型的汇编程序。其中包括基本指令、分支和循环、数组、过程(使用堆栈传递参数)、宏等。包括了大部分的知识点和考点。程序是用来求5个数中最大的数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | ; 输入5个数存入数组,并求出最大数 ; Author: yaozhen http://iyaozhen.com ; Date: 2013.7.23 .386 .MODEL FLAT ExitProcess PROTO NEAR32 stdcall, dwExitCode:DWORD INCLUDE io.h ; header file for input/output cr EQU 0dh ; carriage return character Lf EQU 0ah ; line feed maxNbrs EQU 100 .STACK 4096 ; reserve 4096-byte stack .DATA ; reserve storage for data directions BYTE "You should enter 5 number.",cr,lf,lf,0 prompt BYTE "Number: ",0 number BYTE 20 DUP (?) nbrarray DWORD maxNbrs DUP (?) nbrelts DWORD ? maxnum BYTE cr,lf,"The maxnum is ",0 .CODE ; start of main program code compare PROC NEAR32 push ebp ;保存寄存器 mov ebp,esp ;建立堆栈 mov ebx,[ebp+12] ;从堆栈中取出传入的第一个参数(数组首地址) mov ecx,[ebp+8] ;从堆栈中取出传入的第二个参数(所需比较次数) mov eax,[ebx] ;数组第一个值赋给eax add ebx,4 ;数组指针指向下一个值 compare0: cmp eax,[ebx] ;比较,将大数存入eax jge compare1 jl compare2 compare1: jmp forcmp compare2: mov eax,[ebx] forcmp: add ebx,4 loop compare0 pop ebp ;恢复寄存器ebp ret compare ENDP autoinput MACRO num ;存入n个数到数组的宏 whileinput: mov ecx,num ;循环次数 output prompt input number,20 atod number mov [ebx],eax ;存储到数组中 inc nbrelts ;数组长度 add ebx,4 ;指针指向下一个 loop whileinput ENDM _start: output directions ;提示语句 mov nbrelts,0 ;数组长度 lea ebx,nbrarray ;取出数组首地址 mov ecx,5 ;输入数字的个数 autoinput ecx mov eax,0 lea ebx,nbrarray ;数组首地址 mov ecx,nbrelts ;数组长度 dec ecx ;n个数只要比较n-1次 push ebx ;堆栈传递参数(数组首地址) push ecx ;堆栈传递参数(所需比较次数) call compare ;调用子过程 dtoa number,eax ;输出结果 output maxnum output number input number,20 ;用于程序的暂停 INVOKE ExitProcess, 0 ; exit with return code 0 PUBLIC _start ; make entry point public END ; end of source code |
代码大部分都给出了注释,且运行无错(运行结果见下图)。弄懂这个程序绝对有利于知识点的学习与巩固。
程序中用到了子程序(过程)和宏。两者作用相似但还是有些区别的。过程显得有点画蛇添足而宏更类似于C语言中的函数。关于两者的区别下面有更专业的说明。
宏和子程序都是为了简化源程序的编写,提高程序的可维护性,但是它们二者之间存在着以下本质的区别:
1、在源程序中,通过书写宏名来引用宏,而子程序是通过CALL指令来调用;
2、汇编程序对宏通过宏扩展来加入其定义体,宏引用多少次,就相应扩展多少次,所以,引用宏不会缩短目标程序;而子程序代码在目标程序中只出现一次,调用子程序是执行同一程序段,因此,目标程序也得到相应的简化;
3、宏引用时,参数是通过“实参”替换“形参”的方式来实现传递的,参数形式灵活多样,而子程序调用时,参数是通过寄存器、堆栈或约定存储单元进行传递的;
4、宏引用语句扩展后,目标程序中就不再有宏引用语句,运行时,不会有额外的时间开销,而子程序的调用在目标程序中仍存在,子程序的调用和返回均需要时间。
总之,当程序片段不长,速度是关键因素时,可采用宏来简化源程序,但当程序片段较长,存储空间是关键因素时,可采用子程序的方法来简化源程序和目标程序。(来源:http://www.feiesoft.com/asm/09-1-5.html)
为了更好的学习汇编语言,这里推荐一个在线的学习网站:http://www.feiesoft.com/asm/。还有一本大家都很推荐的书——王爽的《汇编语言》。下载地址:王爽-汇编语言-第2版(高质量,115.26M)