使用汇编语言编程常见错误与技巧(无限期小结中……):
1、定义的变量的位数与所涉及到的寄存器的位数不一致。。。。
2、没有把count1=$-string1 紧跟着放在string1的定义之后,注意$的含义噢!它用来保存当前正在汇编的指令的偏移地址。。。。
3、使用中断指令时,不光要对ah做出修改,还要影响al的值,大家注意咯!!!!
4、要学会将 能影响标志位的语句、判断标志位的语句与跳转语句结合使用。。。
5、学会利用移位语句,要记得它有乘除的效果。。。
6、我居然把start的位置放到了ds、es、cs、ss的初始化语句之后了,结果。。。。。。。。编译链接通过了,运行嘛。。。。。。。。。。。。。。。。。。。。
7、定义的变量是可以直接用inc、dec的。。。。。即对其内容值加一、减一。。。。。注意:虽然变量可以看成符号地址,不过此处只是把它们的数据内容加减一,而非对其地址。。。。。话说当时居然以为不能直接用inc、dec。。。。。。。。哎。。。。。。。。。
8、寄存器、变量、segment等内容未初始化。。。。。。。。。。。一个字:错!!!!!!!!
9、有时候真够弱的,明明是有符号数比较,居然用了ja、jb等。。。。。。。哎。。。。。。。。。。。。。(让错误来得更猛烈些吧!!!!!)
10、使用offset、lea时,别忘了要用16位的寄存器去装偏移地址。
11、使用十六进制数时,若第一个数位值是字母,而且未在其前加0,则会被认为是变量。
12、数据段中定义的第一个字节单元的ea是0,^ ^ ,别误认为是单元的数据噢!
13、寄存器、变量之间传递值时,记得位数要一致噢!
14、话说今天居然定义了 value db 0 ,mov dl,value ,mov ah,02h ,int 21h,结果输出。。。。其实应该是value db '0' ,因为dl中放的应该是所要输出的字符的ASCII码才对!
15、shl 1、shr 1相当于乘以2、除以2,而非是单纯地被看成左移1位、右移1位。
16、在考虑算法时,不要忘了考虑边界情况。
17、如果存储单元大小是字,则不是使用inc si,inc di,而是使用add si,2,add di,2。
18、可以用si指示当前位置,而使用di指示长度变化中的数组的尾部。
19、在编程前,先画个流程图(有时候就连想画正确都很难(过程分支太多,交叉跳转也很多,问题本身也复杂),更别提直接上机编写了),建立一下基本框架,能帮助自己采用正确的循环结构,减少失误。
20、可以使用[BX][BP][SI][DI](十六位寻址:基址寄存器、变址寄存器),但不能使用[DX]、[AX]等。
21、当出现死循环时,运行程序后无法正常终止,可能原因是跳出条件总没有达到。
22、当你要辨别一个数是奇数还是偶数时,不管它是以原码形式表示,还是用补码形式,只要看它最后一位,为1即为奇数,为0即为偶数。
23、一个数的表示形式(原码、补码)不会影响其奇偶性。
24、使用call时要记得把子过程与主过程放在同一个代码段内,同时应该注意end start的位置应在最后。
25、使用push后记得相应地使用pop,还要注意二者应反序,即push ax,push bx,push cx与pop cx,pop bx,pop ax相对应。
26、与第25点相应的,在子过程中的 ret 处之前应放上相应地放上pop语句,而子过程的入口处应相应放上push语句。
27、再谈画流程图,在汇编语言中,细节的东西往往考虑得太多,以致于因为大量的跳转语句、分支的存在而使编写者产生思维混乱。个人认为,可以考虑在每个判断语句后都使用双跳转,尽可能增加跳转标号的数量,而且名字越详细越好,这样可以提高可读性。在分支的发展路线上,可以都采用二元分支,并且应保证各个分支最终都有相应的出口。从宏观上来观察,入口只有一个,出口也是,从入口进来,分支会逐渐增多,当到达一个极点后开始逐渐减少。当然,我们在画图时可以一步一步来,先用概括性的语句来描述,再用伪代码,最后采用真正的代码,逐渐深入,逐渐完善,自上而下,一步一步靠近细节。从大框架到各步骤,再从各步骤的小框架到各语句,框架之中还有框架……
28、1000 0000B == 0000 0000B == 0D
29、回车、换行 与 换行、回车 等效。line feed:换行,回车:carriage return。
30、 在使用中断之前,最好注意一下当前是否有对AX的使用,若有需要,必须先将AX入栈,完成中断后再出栈。
31、若定义了 A DW 6,7,8,则6、7、8的存储地址分别为A+0、 A+2、 A+4。使用mov语句时,应分别用A[0]、A[2]、A[4]。
32、cmp [SI],'S',使用debug时,注意到它显示cmp word ptr [SI],53 了吗?如果之前定义的是array DB 's','d','g',且LEA SI,array,则此处可使用强制类型转换,即cmp byte ptr [SI],'S'.
33、有时候觉得结果太多,输出很不方便,可以直接在debug中使用-d来查看ds中的内容。
34、题目要求的数据要有一百个怎么办?可以这样写:data_array dw 10 DUP(1,2,3,4,5,6,7,8,9,0)
35、当把loop与jmp结合使用,每次从loop的尾部 jmp 到标号lop1前,应记得为cx设初值。
36、array db 1,2,3,4,5 ,lea si,array ,mov ax,[si] ,编译器不会报错,但结果已经错了,应该改为mov al,[si]。
37、如果是远过程,那么代码段的开始应写上:
CODES SEGMENT
main PROC FAR
ASSUME CS:CODES,DS:DATAS,SS:STACKS
START:
;此处输入代码据段代码
PUSH DS
SUB AX,AX
PUSH AX ;远过程结尾用 ret 返回时必须使用这三句语句。
;如果未使用这三条语句,则必须mov ah,4ch,int 21h返回DOS。
MOV AX,DATAS
MOV DS,AX ;数据段寄存器初始化
38、数据段、附加段、堆栈段,只要没用到的,都可以不使用assume,都可以不初始化。这样并不会影响结果。
39、在数据段内定义dat db 30h,41h(元素在同一行时这样写),(不在同一行时,这样写:)
dat db 30h
db 41h
40、在上例中,inc dat,加的是dat[0]. 而[dat+1]指的是dat[1].若用的是dw来定义,则[dat+2]里装的才是41h。
40、start与end start是必需的。
期待更新中。。。。