4-rings or 4-squares puzzle/X86 Assembly

From Rosetta Code

X86 Assembly

Works with: NASM
Works with: Linux

64 bit

; Based on C version http://rosettacode.org/wiki/4-rings_or_4-squares_puzzle#C

%define TRUE 1
%define FALSE 0

global main,foursquares,acd,ge,bf,print_output
extern printf

segment .data

a dq 0
b dq 0
c dq 0
d dq 0
e dq 0
f dq 0
g dq 0

lo dq 0
hi dq 0
unique dq 0
show dq 0
solutions dq 0

output_fmt db `%ld %ld %ld %ld %ld %ld %ld\n`,0

segment .text

main:                            
    push rbp                     
    mov rbp,rsp                 

    mov rdi,1
    mov rsi,7
    mov rdx,TRUE
    mov rcx,TRUE
    call foursquares

    mov rdi,3
    mov rsi,9
    mov rdx,TRUE
    mov rcx,TRUE
    call foursquares

    mov rdi,0
    mov rsi,9
    mov rdx,FALSE
    mov rcx,FALSE
    call foursquares

    xor rax,rax                  
    leave                       
    ret   
    
segment .data

newlinefmt db `\n`,0
uniquefmt db `\n%ld unique solutions in %ld to %ld\n`,0
nonuniquefmt db `\n%ld non-unique solutions in %ld to %ld\n`,0

segment .text

foursquares:                             
    push rbp                     
    mov rbp,rsp
    
    mov qword [lo],rdi
    mov qword [hi],rsi
    mov qword [unique],rdx
    mov qword [show],rcx
    mov qword [solutions],0
    
    lea rdi,[newlinefmt]
    xor rax,rax
    call printf
    
    call acd
    
    mov rax,qword [unique]
    mov rbx,TRUE
    cmp rax,rbx
    je .isunique
    
    lea rdi,[nonuniquefmt]
    mov rsi,qword [solutions]
    mov rdx,qword [lo]
    mov rcx,qword [hi]
    xor rax,rax
    call printf
    jmp .done
    
.isunique:
    lea rdi,[uniquefmt]
    mov rsi,qword [solutions]
    mov rdx,qword [lo]
    mov rcx,qword [hi]
    xor rax,rax
    call printf
    
.done:
    xor rax,rax                  
    leave                        
    ret  
    
segment .text

acd:                             
    push rbp                     
    mov rbp,rsp
    
    mov rax,qword [lo] ; c = lo
    mov qword [c],rax 

.nextouterfor:
    mov rax,qword [c]  ; c <= hi
    mov rcx,qword [hi] 
    cmp rax,rcx
    jg .doneouterfor
    
    mov rax,qword [lo] ; d = lo
    mov qword [d],rax 
    
.nextinnerfor:
    mov rax,qword [d]  ; d <= hi
    mov rcx,qword [hi] 
    cmp rax,rcx
    jg .doneinnerfor
    
    mov rax,qword [unique]
    mov rcx,FALSE
    cmp rax,rcx
    je .inif
    
    mov rax,qword [c]
    mov rcx,qword [d]
    cmp rax,rcx
    jne .inif
    jmp .iffails
    
.inif: 
    mov rax,qword [c]
    mov rcx,qword [d]
    add rax,rcx
    mov qword [a],rax
    
; ((a >= lo) && 
;  (a <= hi) &&
;  ((!unique) || 
;   ((c != 0) && 
;    (d != 0)
;   )
;  )
; )
    mov rax,qword [a]  ;(a >= lo)
    mov rcx,qword [lo]
    cmp rax,rcx
    jl .iffails
    
    mov rax,qword [a]  ;(a <= hi)
    mov rcx,qword [hi]
    cmp rax,rcx
    jg .iffails
    
    mov rax,qword [unique] ;(!unique)
    mov rcx,FALSE
    cmp rax,rcx
    je .ifsucceeds

    mov rax,qword [c]  ;(c != 0)
    mov rcx,0
    cmp rax,rcx
    je .iffails
    
    mov rax,qword [d]  ;(d != 0)
    mov rcx,0
    cmp rax,rcx
    je .iffails

.ifsucceeds:

    call ge
    
.iffails:
    mov rax,qword [d] ; d++
    inc rax
    mov qword [d],rax
    jmp .nextinnerfor

.doneinnerfor:
    mov rax,qword [c] ; c++
    inc rax
    mov qword [c],rax
    jmp .nextouterfor
   
.doneouterfor:
    xor rax,rax                  
    leave                        
    ret    
    
ge:                              
    push rbp                     
    mov rbp,rsp
    
    mov rax,qword [lo] ; e = lo
    mov qword [e],rax 

.nextfor:
    mov rax,qword [e]  ; e <= hi
    mov rcx,qword [hi] 
    cmp rax,rcx
    jg .donefor
    
    mov rax,qword [unique]
    mov rcx,FALSE
    cmp rax,rcx
    je .inif
 
; ((e != a) && (e != c) && (e != d))

    mov rax,qword [e]
    
    mov rcx,qword [a] ; (e != a)
    cmp rax,rcx
    je .skipif
    
    mov rcx,qword [c] ; (e != c)
    cmp rax,rcx
    je .skipif
    
    mov rcx,qword [d] ; (e != d)
    cmp rax,rcx
    je .skipif
    
.inif: 
    mov rax,qword [d] ; g = d + e
    mov rcx,qword [e]
    add rax,rcx
    mov qword [g],rax

; ((g >= lo) &&
;  (g <= hi) &&
;  ((!unique) || 
;   ((g != a) && 
;    (g != c) &&
;    (g != d) && 
;    (g != e)
;   )
;  )
; )    

    mov rax,qword [g]  ;(g >= lo)
    mov rcx,qword [lo]
    cmp rax,rcx
    jl .skipif
    
    mov rax,qword [g]  ;(g <= hi)
    mov rcx,qword [hi]
    cmp rax,rcx
    jg .skipif
    
    mov rax,qword [unique] ;(!unique)
    mov rcx,FALSE
    cmp rax,rcx
    je .innerifsucceeds

    mov rax,qword [g]  ;(g != a)
    mov rcx,qword [a]
    cmp rax,rcx
    je .skipif

    mov rcx,qword [c]  ;(g != c)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [d]  ;(g != d)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [e]  ;(g != e)
    cmp rax,rcx
    je .skipif

.innerifsucceeds:
    call bf
    
.skipif:
    mov rax,qword [e] ; e++
    inc rax
    mov qword [e],rax
    jmp .nextfor
   
.donefor:
    xor rax,rax                  
    leave                        
    ret   
    
segment .text
    
bf:                              
    push rbp                     
    mov rbp,rsp
    
    mov rax,qword [lo] ; f = lo
    mov qword [f],rax 

.nextfor:
    mov rax,qword [f]  ; f <= hi
    mov rcx,qword [hi] 
    cmp rax,rcx
    jg .donefor
    
    mov rax,qword [unique]
    mov rcx,FALSE
    cmp rax,rcx
    je .inif
 
; ((f != a) && (f != c) && (f != d) && (f != g) && (f != e))

    mov rax,qword [f]
    
    mov rcx,qword [a] ; (f != a)
    cmp rax,rcx
    je .skipif
    
    mov rcx,qword [c] ; (f != c)
    cmp rax,rcx
    je .skipif
    
    mov rcx,qword [d] ; (f != d)
    cmp rax,rcx
    je .skipif
    
    mov rcx,qword [g] ; (f != g)
    cmp rax,rcx
    je .skipif
    
    mov rcx,qword [e] ; (f != e)
    cmp rax,rcx
    je .skipif
    
.inif: 
    mov rax,qword [e] ; b = e + f - c;
    mov rcx,qword [f]
    add rax,rcx
    mov rcx,qword [c]
    sub rax,rcx
    mov qword [b],rax

; ((b >= lo) &&
;  (b <= hi) &&
;  ((!unique) || 
;   ((b != a) && 
;    (b != c) &&
;    (b != d) && 
;    (b != g) && 
;    (b != e) && 
;    (b != f)
;   )
;  )
; ) 

    mov rax,qword [b]  ;(b >= lo)
    mov rcx,qword [lo]
    cmp rax,rcx
    jl .skipif
    
    mov rax,qword [b]  ;(b <= hi)
    mov rcx,qword [hi]
    cmp rax,rcx
    jg .skipif
    
    mov rax,qword [unique] ;(!unique)
    mov rcx,FALSE
    cmp rax,rcx
    je .innerifsucceeds

    mov rax,qword [b]  ;(b != a)
    mov rcx,qword [a]
    cmp rax,rcx
    je .skipif

    mov rcx,qword [c]  ;(b != c)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [d]  ;(b != d)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [g]  ;(b != g)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [e]  ;(b != e)
    cmp rax,rcx
    je .skipif

    mov rcx,qword [f]  ;(b != f)
    cmp rax,rcx
    je .skipif

.innerifsucceeds:
    mov rax,qword [solutions] ; solutions++
    inc rax
    mov qword [solutions],rax
    
    mov rax,qword [show]
    cmp rax,TRUE
    jne .skipif
   
    call print_output
    
.skipif:
    mov rax,qword [f] ; f++
    inc rax
    mov qword [f],rax
    jmp .nextfor
   
.donefor:
    xor rax,rax                  
    leave                        
    ret   
    
print_output:                            
    push rbp                     
    mov rbp,rsp
        

; printf("%d %d %d %d %d %d %d\n",a,b,c,d,e,f,g);
    
    lea rdi,[output_fmt]
    mov rsi,qword [a]
    mov rdx,qword [b]
    mov rcx,qword [c]
    mov r8,qword [d]
    mov r9,qword [e]
    mov rax,qword [g]
    push rax
    mov rax,qword [f]
    push rax
    xor rax,rax
    call printf
    
    xor rax,rax                  
    leave                        
    ret

Output


4 7 1 3 2 6 5
6 4 1 5 2 3 7
3 7 2 1 5 4 6
5 6 2 3 1 7 4
7 3 2 5 1 4 6
4 5 3 1 6 2 7
6 4 5 1 2 7 3
7 2 6 1 3 5 4

8 unique solutions in 1 to 7

7 8 3 4 5 6 9
8 7 3 5 4 6 9
9 6 4 5 3 7 8
9 6 5 4 3 8 7

4 unique solutions in 3 to 9


2860 non-unique solutions in 0 to 9