正文

汇编实现八皇后2007-04-02 08:15:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/freeeerf/24537.html

分享到:

;程序功能:用深度优先搜索法解决八皇后问题并打印结果.;列数行数分别用1-8标记.所以八皇后的位置申请了9个 ;调试感慨:汇编调试实在麻烦,不像C中在任何地方加个printf就可以知道;哪错了.跳来跳去的,不知哪里死循环了,实在不好调试. .model small,stdcall ;由于皇后位置都是一位数,所以加上30H后作字符打印出. printResult macro local again,print,first push si ;不能改变它的值.  mov ah,02h ;输出状态不变. mov cx,2 ;对称的结果,所以打两个结果.again:  mov si,1 print: mov dl,queen[si] cmp cx,2 je first mov bl,9 sub bl,dl mov dl,blfirst: add dl,30h int 21h inc si cmp si,9 ;到第9个就是说打完了. jnz print mov dl,' ' ;输出两个空格,为好看. int 21h int 21h loop again  pop si endm .data ;改来改去,何必那么小气呢?用9个多方便,就一个字节,不必这么小气! queen db 9 dup(0) used db 9 dup(0)  Nresult dw 0 ;结果的个数.  prompt db "The positions are:",0ah,0dh,'$' over db 0ah,0dh,"The number of the result is $".code ;函数功能:把存在ax寄存器里的二进制数用十进制打印出来.printaxd proc near mov bx,10000d ;二个字节的数最大就3万多. mov ch,0 ;还没出现第一个要打印的数(最高位的非0不需要打印) mov cl,5 ;最多有五位,所以一共除五次. mov si,ax ;哈哈,寄存器太聪明了.go: mov ax,si mov dx,0 ;既然是除法,就要保证高位的绝对值最小. div bx dec cl ;除一次就减一次. mov di,ax ;除完就把商移走,位置让出来给bx/10 mov si,dx ;保证余数.  ;实现bx/10. mov ax,bx mov bx,10 ;记住乘除法运算不能用立即数. mov dx,0 ; 实际上dl的最大值也就是9小于10,但为了保险和习惯,还是用这一句. div bx mov bx,ax mov ax,di  cmp cl,0 ;如果到最后一位了,无论是0还是不为0,都要打印了. jz next or ch,al jz gonext: mov ch,1 ;有打印的了 mov dl,al add dl,30h mov ah,02h int 21h cmp cl,0 jnz go  ret ; This line cann't be forgotten.printaxd endp main proc far mov ax,@data mov ds,ax mov es,ax  mov dx,offset prompt mov ah,09h int 21h  mov si,1 ;当然是从第一列开始.go: inc queen[si] ;当前列向下走一步.  ;测试是否走出8*8的格子了 cmp queen[si],9 jnz stay  ;刚好踏出格子,就把当前列置0,把上一列所在行置空,然后继续go. mov queen[si],0 dec si ;取消所占的行. mov al,queen[si] ;不知何以不能用movzx di,queen[si] cbw mov di,ax mov used[di],0 ;是否完成搜索. cmp si,1 jnz go ;调试记语:为什么为5时不退出呢?改成4后结果居然对了.最后一个疑问了! ;对!原来如此!退出是要在queen[1]为5时,当4变成5时,这个增加的过程 ;在go的第一句,也就是说此时还为4. ;于是退出条件就是当此时第一列为4而又要向前址走一步时根据对称性 ;就要退出了. cmp queen[si],4 ;利用对称性,如果第一列算到5行,就不用算了. je exit jmp go stay:  ;留在方格内,那么就剩下是否满足不在同一行同一斜行的问题了. mov al,queen[si] ;不知何以不能用movzx di,queen[si] cbw mov di,ax cmp used[di],1 ;如果为1就说明当前列的当前行已使用. je go  ;循环检查是否有在同一斜行的皇后. mov di,si dec di ; bx指向与当前列比较的列.check: cmp di,0 je checkover mov dx,si ;dx装着当前列与检测列的差.,差最大不过7,所以也可以说是装在dl中. sub dx,di mov al,queen[si]  ;al放两列的行之差. sub al,queen[di] cmp al,dl ;相等或相反就是在同一斜行. je go neg al ;求负数. cmp al,dl je go dec di jmp checkcheckover: ;好,现在可以留下来了. cmp si,8 jz result ;如果不是最后一列. mov al,queen[si] ;不知何以不能用movzx di,queen[si] cbw mov di,ax mov used[di],1 ;留下来这一行就占住了. inc si jmp go result: ;好,一个结果出来了,根据对称,实际出来两个结果. add Nresult,2 printResult mov queen[si],0 dec si  ;这四行初为设计上的漏洞,想了老半天. mov al,queen[si] ;不知何以不能用movzx di,queen[si] cbw mov di,ax mov used[di],0  jmp go exit: mov dx,offset over mov ah,09h int 21h mov ax,Nresult call printaxd mov ah,01h ; to pause int 21h  mov ah,4ch int 21h main endpend main

阅读(3889) | 评论(1)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册