学习汇编了,老师用了几个课时的时间讲完,说下节课讲微机了。
咋惊,决定用一周力攻。今天发了近一天时间搞定一个程序,稍有满足感,也有点感触。决定记录下来。
该程序是用递归求N!。
书里原程序:
STACK SEGMENT STACK
DW 64 DUP(?)
STACK ENDS
CODE SEGMENT
ASSUME CS:CODE
START: MOV AX,3010H
PUSH AX
MOV SI,3000H
MOV AX,[SI]
PUSH AX
CALL branch
INT 03H
branch: PUSH BP
MOV BP,SP
PUSH BX
PUSH AX
MOV BX,[BP+06H]
MOV AX,[BP+04H]
CMP AX,0000H
JZ A1
PUSH BX
DEC AX
PUSH AX
CALL branch
MOV BX,[BP+06H]
MOV AX,[BX]
PUSH BX
MOV BX,[BP+04H]
MUL BX
POP BX
JMP A2
A1: MOV AX,0001H
A2: MOV [BX],AX
POP AX
POP BX
POP BP
RET 0004H
CODE ENDS
END START
刚开始,对子程序调用还不是很了解。咋一看,第一感觉是程序是否有问题。以C的思想想:“递归调用到啥时停止?停止后怎么好像并没有求N*(N-1)。。的值呢??
上机在dos中调试一下,结果错误。。。
于是乎,决定自己改程序······(后来发现改后的都不知是什么东西)
隔天早上,找实验老师,老师亦郁闷乎。和老师一起研究了一上午,未果,亦以为程序错误~~
中午又在一本书上看到该程序,程序一样,于是观点稍变~~
下午上课,和一位仁兄探讨一番,课余又请教了下任课老师~~顿时有点明朗。对程序调用,堆栈的变化有了进一步认识~~
之后上了体育课回来,继续研究······又再查了下”RET“的含义,这回明白了,”RET N“是从栈顶弹出IP,执行IP指向的下一指令,并执行SP+N->SP。呵呵,这回知道怎么个递归法咯~~
研究了一个多小时,终于搞定,调试成功~~长抒一口气,稍有满足感~~~
最终结论:程序正确,不过有得改进。由于“ MOV AX,[SI]”只给AL赋值,AH可能由于原先内存内的值而导致错误,导致程序结果错误甚至崩溃~~还有DI没用到,可以删除~~
心得: 学语言还是看程序来得快~~
需要仔细琢磨,也需要交流~~
语法指令需要了解清楚,汇编调用子程序最好把堆栈的变化画出来~~