; N-queens problem solving program - machine lang version of NQ11.sno ; Demonstrates use of patmac.inc ; Written by Viktors Berstis ; Note: If you want to time this to compare to snobol5, turn off the : slow debug printing calls per below. ; N = 8 N equ 8 include debug64.inc include patmac.inc .data patvars strng macro nam,mxl align 8 nam dq &nam&len &nam&len dq 0 &nam&lenmax dq mxl &nam&text db mxl DUP(?) endm nullstrng macro a,lim mov rdx,a mov qword ptr [rdx],0 ifnb mov qword ptr [rdx+8],lim endif endm append macro a,b mov rdx,b lea rsi,[rdx+16] ;text mov rcx,[rdx+0] ;len mov rdx,a lea rdi,[rdx+16] ;text mov rbx,[rdx] ;len add rdi,rbx add rbx,rcx ;#### cmp rbx,[rdx+8] ;lenmax ;#### ja error2 ;dont do if it would be too long mov [rdx],rbx jrcxz @F rep movsb @@: endm prtstrng macro a mov rdx,a mov al,'[' call dbgprtc lea rsi,[rdx+16] ;text mov rcx,[rdx+0] ;len call dbgstr mov al,']' call dbgprtc call dbgcrlf endm align 8 SOLUTION dq 0 ; NM1 = N - 1 NM1 dq N-1 ; NP1 = N + 1 NP1 dq N+1 ; NSZ = N * NP1 NSZ dq N*(N+1) ; L = 'Q' DUPL('-',NM1) ' ' L dq Llen Llen dq N+1 Llenmax dq N+1 Ltext db 'Q' db N-1 DUP('-') db ' ' db N*N DUP(?) strng X,(N*(N+1)) strng T,(N*(N+1)) align 8 Iaddr dq I+stkamount Baddr dq Blen+stkamount I dq 0 strng B,(N*(N+1)) align 8 here db (here-I)*N DUP(?) stkamount equ (here-I) db stkamount DUP(?) .code public mainCRTStartup mainCRTStartup: nullstrng Baddr,(N*(N+1)) ; SOLVE() :(END) call SOLVE mov rax,SOLUTION call dbgprtfi call dbgs db ' solutions found',13,10,0 call dbgexit ; DEFINE('SOLVE(B)I') SOLVE PROC mov r12,Baddr ;old value add Iaddr,stkamount add Baddr,stkamount nullstrng Baddr,(N*(N+1)) append Baddr,r12 mov rax,Iaddr mov qword ptr [rax],0 ;set I to zero at this level ; EQ(SIZE(B),NSZ) :S(PRINT) mov rdx,Baddr mov rax,[rdx] cmp rax,NSZ je PRINT ; B = L B nullstrng T append T,L append T,Baddr nullstrng Baddr append Baddr,T ;myLOOP I = LT(I,N) I + 1 :F(RETURN) myLOOP: mov rsi,Iaddr cmp qword ptr [rsi],N jnl myRETURN inc qword ptr [rsi] ; TEST = BREAK('Q') 'Q' (ARBNO(LEN(N ) '-') LEN(N ) 'Q' ;+ | ARBNO(LEN(NP1) '-') LEN(NP1) 'Q' ;+ | ARBNO(LEN(NM1) '-') LEN(NM1) 'Q') ; B TEST :S(NEXT) mov r10,Baddr mov r11,[r10] ;length add r10,16 ;points to text pstart r10,r11,deeper pbreaki 'Q' pstri 'Q' plp parbnos plen N pstri '-' parbnoe plen N pstri 'Q' palt parbnos plen NP1 pstri '-' parbnoe plen NP1 pstri 'Q' palt parbnos plen NM1 pstri '-' parbnoe plen NM1 pstri 'Q' prp pend jmp NEXT ;deeper SOLVE(B) deeper: call SOLVE ;NEXT B LEN(NM1) . X LEN(1) = '-' X :(myLOOP) NEXT: mov r10,Baddr mov r11,[r10] add r10,16 pstart r10,r11,error passns plen NM1 passne Xtext,Xlen,Xlenmax plen 1 mov r9,cursoro pend mov r10,Baddr mov rdi,r10 mov rcx,[r10] add rdi,16 mov rsi,rdi add rsi,r9 sub rcx,r9 mov [r10],rcx rep movsb mov byte ptr Ttext,'-' mov Tlen,1 append T,X append T,Baddr nullstrng Baddr append Baddr,T jmp myLOOP ;PRINT SOLUTION = SOLUTION + 1 ; OUTPUT = 'Solution number ' SOLUTION ' is:' PRINT: inc SOLUTION jmp doprint ; #### comment this out for no print version because debug printing is slow myRETURN: sub Iaddr,stkamount sub Baddr,stkamount ret doprint: call dbgs db 'Solution number ',0 mov rax,SOLUTION call dbgprtfi call dbgs db ' is:',13,10,0 ;PRTLOOP B LEN(NP1) . OUTPUT = :S(PRTLOOP)F(RETURN) mov r10,Baddr mov rdx,[r10] mov rsi,r10 add rsi,16 add rdx,rsi mov rcx,NP1 PRTLOOP: call dbgstr call dbgcrlf add rsi,NP1 cmp rsi,rdx jl PRTLOOP sub Iaddr,stkamount sub Baddr,stkamount ret error: dbgustr 'error' call dbgexit error2: dbgustr 'error2' call dbgexit SOLVE endp END