4-rings or 4-squares puzzle

You are encouraged to solve this task according to the task description, using any language you may know.
Task

Replace       a, b, c, d, e, f,   and
  g        with the decimal
digits   LOW   ───►   HIGH

such that the sum of the letters inside of each of the four large squares add up to
the same sum.

            ╔══════════════╗      ╔══════════════╗
            ║              ║      ║              ║
            ║      a       ║      ║      e       ║
            ║              ║      ║              ║
            ║          ┌───╫──────╫───┐      ┌───╫─────────┐
            ║          │   ║      ║   │      │   ║         │
            ║          │ b ║      ║ d │      │ f ║         │
            ║          │   ║      ║   │      │   ║         │
            ║          │   ║      ║   │      │   ║         │
            ╚══════════╪═══╝      ╚═══╪══════╪═══╝         │
                       │       c      │      │      g      │
                       │              │      │             │
                       │              │      │             │
                       └──────────────┘      └─────────────┘

Show all output here.



   Show all solutions for each letter being unique with
        LOW=1     HIGH=7

   Show all solutions for each letter being unique with
        LOW=3     HIGH=9

   Show only the   number   of solutions when each letter can be non-unique
        LOW=0     HIGH=9



Related task

 Solve the no connection puzzle


 
 
/* ARM assembly Raspberry PI  */
/*  program square4.s   */
 
/************************************/
/* Constantes                       */
/************************************/
.equ STDOUT, 1     @ Linux output console
.equ EXIT,   1     @ Linux syscall
.equ WRITE,  4     @ Linux syscall
 
.equ NBBOX,  7
 
/*********************************/
/* Initialized data              */
/*********************************/
.data
sMessDeb:           .ascii "a="
sMessValeur_a:     .fill 11, 1, ' '            @ size => 11
                    .ascii "b="
sMessValeur_b:     .fill 11, 1, ' '            @ size => 11
                    .ascii "c="
sMessValeur_c:     .fill 11, 1, ' '            @ size => 11
                    .ascii "d="
sMessValeur_d:     .fill 11, 1, ' '            @ size => 11
                    .ascii "\n"
                    .ascii "e="
sMessValeur_e:     .fill 11, 1, ' '            @ size => 11
                    .ascii "f="
sMessValeur_f:     .fill 11, 1, ' '            @ size => 11
                    .ascii "g="
sMessValeur_g:     .fill 11, 1, ' '            @ size => 11
 
szCarriageReturn:   .asciz "\n************************\n"
 
sMessNbSolution:   .ascii "Number of solutions :"
sMessCounter:     .fill 11, 1, ' '            @ size => 11
                   .asciz "\n\n\n"
 
/*********************************/
/* UnInitialized data            */
/*********************************/
.bss  
.align 4
iValues_a:                .skip 4 * NBBOX
iValues_b:                .skip 4 * NBBOX - 1
iValues_c:                .skip 4 * NBBOX - 2
iValues_d:                .skip 4 * NBBOX - 3
iValues_e:                .skip 4 * NBBOX - 4
iValues_f:                .skip 4 * NBBOX - 5
iValues_g:                .skip 4 * NBBOX - 6
iCounterSol:              .skip 4
/*********************************/
/*  code section                 */
/*********************************/
.text
.global main 
main:                                             @ entry of program 
    mov r0,#1
    mov r1,#7
    mov r2,#3                                     @ 0 = rien 1 = display 2 = count 3 = les deux
    bl searchPb
    mov r0,#3
    mov r1,#9
    mov r2,#3                                     @ 0 = rien 1 = display 2 = count 3 = les deux
    bl searchPb
    mov r0,#0
    mov r1,#9
    mov r2,#2                                     @ 0 = rien 1 = display 2 = count 3 = les deux
    bl prepSearchNU
 
100:                                              @ standard end of the program 
    mov r0, #0                                    @ return code
    mov r7, #EXIT                                 @ request to exit program
    svc #0                                        @ perform the system call
 
iAdrszCarriageReturn:            .int szCarriageReturn
 
/******************************************************************/
/*     search problèm  value not unique                           */ 
/******************************************************************/
/* r0 contains start digit */
/* r1 contains end digit */
/* r2 contains action (0 display 1 count) */
prepSearchNU:
    push {r3-r12,lr}                              @ save  registers
    mov r5,#0                                     @ counter
    mov r12,r0                                    @ a
1:
    mov r11,r0                                    @ b
2:
    mov r10,r0                                    @ c
3:
    mov r9,r0                                     @ d
4:
    add r4,r12,r11                                @ a + b reference
    add r3,r11,r10
    add r3,r9                                     @ b + c + d
    cmp r4,r3
    bne 10f
    mov r8,r0                                     @ e
5:
    mov r7,r0                                     @ f
6:
    add r3,r9,r8
    add r3,r7                                     @ d + e + f
    cmp r3,r4
    bne 9f
    mov r6,r0                                     @ g
7:
    add r3,r7,r6                                  @ f + g
    cmp r3,r4
    bne 8f                                        @ not OK
                                                  @ OK
    add r5,#1                                     @ increment counter
 
8:
    add r6,#1                                     @ increment g
    cmp r6,r1
    ble 7b
9:
    add r7,#1                                     @ increment f
    cmp r7,r1
    ble 6b
    add r8,#1                                     @ increment e
    cmp r8,r1
    ble 5b
10:
    add r9,#1                                     @ increment d
    cmp r9,r1
    ble 4b
    add r10,#1                                    @ increment c
    cmp r10,r1
    ble 3b
    add r11,#1                                    @ increment b
    cmp r11,r1
    ble 2b
    add r12,#1                                    @ increment a
    cmp r12,r1
    ble 1b
 
    @ end
    tst r2,#0b10                                    @ print count ?
    beq 100f
    mov r0,r5                                       @ counter
    ldr r1,iAdrsMessCounter
    bl conversion10
    ldr r0,iAdrsMessNbSolution
    bl affichageMess
 
100:
    pop {r3-r12,lr}                                 @ restaur registers 
    bx lr                                           @return
iAdrsMessCounter:                .int sMessCounter
iAdrsMessNbSolution:             .int sMessNbSolution
 
/******************************************************************/
/*     search problem  unique solution                            */ 
/******************************************************************/
/* r0 contains start digit */
/* r1 contains end digit */
/* r2 contains action (0 display 1 count) */
searchPb:
    push {r0-r12,lr}                                  @ save  registers
    @ init
    ldr r3,iAdriValues_a                              @ area value a
    mov r4,#0
1:                                                    @ loop init value a
    str r0,[r3,r4,lsl #2]
    add r4,#1
    add r0,#1
    cmp r0,r1
    ble 1b
 
    mov r5,#0                                         @ solution counter
    mov r12,#-1
2:
    add r12,#1                                        @ increment indice a
    cmp r12,#NBBOX-1
    bgt 90f
    ldr r0,iAdriValues_a                              @ area value a
    ldr r1,iAdriValues_b                              @ area value b
    mov r2,r12                                        @ indice  a
    mov r3,#NBBOX                                     @ number of origin values 
    bl prepValues
    mov r11,#-1
3:
    add r11,#1                                        @ increment indice b
    cmp r11,#NBBOX - 2
    bgt 2b
    ldr r0,iAdriValues_b                              @ area value b
    ldr r1,iAdriValues_c                              @ area value c
    mov r2,r11                                        @ indice b
    mov r3,#NBBOX -1                                  @ number of origin values
    bl prepValues
    mov r10,#-1
4:
    add r10,#1
    cmp r10,#NBBOX - 3
    bgt 3b
    ldr r0,iAdriValues_c
    ldr r1,iAdriValues_d
    mov r2,r10
    mov r3,#NBBOX - 2
    bl prepValues
    mov r9,#-1
5:
    add r9,#1
    cmp r9,#NBBOX - 4
    bgt 4b
    @ control 2 firsts squares
    ldr r0,iAdriValues_a
    ldr r0,[r0,r12,lsl #2]
    ldr r1,iAdriValues_b
    ldr r1,[r1,r11,lsl #2]
    add r4,r0,r1                               @ a + b   value first square
    ldr r0,iAdriValues_c
    ldr r0,[r0,r10,lsl #2]
    add r7,r1,r0                               @ b + c
    ldr r1,iAdriValues_d
    ldr r1,[r1,r9,lsl #2]
    add r7,r1                                  @ b + c + d
    cmp r7,r4                                  @ equal first square ?
    bne 5b
    ldr r0,iAdriValues_d
    ldr r1,iAdriValues_e
    mov r2,r9
    mov r3,#NBBOX - 3
    bl prepValues
    mov r8,#-1
6:
    add r8,#1
    cmp r8,#NBBOX - 5
    bgt 5b
    ldr r0,iAdriValues_e
    ldr r1,iAdriValues_f
    mov r2,r8
    mov r3,#NBBOX - 4
    bl prepValues
    mov r7,#-1
7:
    add r7,#1
    cmp r7,#NBBOX - 6
    bgt 6b
    ldr r0,iAdriValues_d
    ldr r0,[r0,r9,lsl #2]
    ldr r1,iAdriValues_e
    ldr r1,[r1,r8,lsl #2]
    add r3,r0,r1                                @ d + e
    ldr r1,iAdriValues_f
    ldr r1,[r1,r7,lsl #2]
    add r3,r1                                   @ de + e + f
    cmp r3,r4                                   @ equal first square ?
    bne 7b
    ldr r0,iAdriValues_f
    ldr r1,iAdriValues_g
    mov r2,r7
    mov r3,#NBBOX - 5
    bl prepValues
    mov r6,#-1
8:
    add r6,#1
    cmp r6,#NBBOX - 7
    bgt 7b
    ldr r0,iAdriValues_f
    ldr r0,[r0,r7,lsl #2]
    ldr r1,iAdriValues_g
    ldr r1,[r1,r6,lsl #2]
    add r3,r0,r1                               @ f +g 
    cmp r4,r3                                  @ equal first square ?
    bne 8b
    add r5,#1                                  @ increment counter
    ldr r0,[sp,#8]                             @ load action for two parameter in stack
    tst r0,#0b1
    beq 9f                                     @ display solution ?
    ldr r0,iAdriValues_a
    ldr r0,[r0,r12,lsl #2]
    ldr r1,iAdrsMessValeur_a
    bl conversion10
    ldr r0,iAdriValues_b
    ldr r0,[r0,r11,lsl #2]
    ldr r1,iAdrsMessValeur_b
    bl conversion10
    ldr r0,iAdriValues_c
    ldr r0,[r0,r10,lsl #2]
    ldr r1,iAdrsMessValeur_c
    bl conversion10
    ldr r0,iAdriValues_d
    ldr r0,[r0,r9,lsl #2]
    ldr r1,iAdrsMessValeur_d
    bl conversion10
    ldr r0,iAdriValues_e
    ldr r0,[r0,r8,lsl #2]
    ldr r1,iAdrsMessValeur_e
    bl conversion10
    ldr r0,iAdriValues_f
    ldr r0,[r0,r7,lsl #2]
    ldr r1,iAdrsMessValeur_f
    bl conversion10
    ldr r0,iAdriValues_g
    ldr r0,[r0,r6,lsl #2]
    ldr r1,iAdrsMessValeur_g
    bl conversion10
    ldr r0,iAdrsMessDeb
    bl affichageMess
9:
    b 8b    @ suite 
 
90:
    ldr r0,[sp,#8]                                @ load action for two parameter in stack
    tst r0,#0b10
    beq 100f                                      @ display counter ?
    mov r0,r5
    ldr r1,iAdrsMessCounter
    bl conversion10
    ldr r0,iAdrsMessNbSolution
    bl affichageMess
100:
    pop {r0-r12,lr}                               @ restaur registers 
    bx lr                                         @return
iAdriValues_a:                   .int iValues_a
iAdriValues_b:                   .int iValues_b
iAdriValues_c:                   .int iValues_c
iAdriValues_d:                   .int iValues_d
iAdriValues_e:                   .int iValues_e
iAdriValues_f:                   .int iValues_f
iAdriValues_g:                   .int iValues_g
 
iAdrsMessValeur_a:               .int sMessValeur_a
iAdrsMessValeur_b:               .int sMessValeur_b
iAdrsMessValeur_c:               .int sMessValeur_c
iAdrsMessValeur_d:               .int sMessValeur_d
iAdrsMessValeur_e:               .int sMessValeur_e
iAdrsMessValeur_f:               .int sMessValeur_f
iAdrsMessValeur_g:               .int sMessValeur_g
iAdrsMessDeb:                    .int sMessDeb
iAdriCounterSol:                 .int iCounterSol
/******************************************************************/
/*     copy value area  and substract value of indice             */ 
/******************************************************************/
/* r0 contains the address of values origin */
/* r1 contains the address of values destination */
/* r2 contains value indice to substract     */
/* r3 contains origin values number          */
prepValues:
    push {r1-r6,lr}                                @ save  registres
    mov r4,#0                                      @ indice origin value
    mov r5,#0                                      @ indice destination value
1:
    cmp r4,r2                                      @ substract indice ?
    beq 2f                                         @ yes -> jump
    ldr r6,[r0,r4,lsl #2]                          @ no -> copy value
    str r6,[r1,r5,lsl #2]
    add r5,#1                                      @ increment destination indice
2:
   add r4,#1                                       @ increment origin indice
   cmp r4,r3                                       @ end ?
   blt 1b
100:
    pop {r1-r6,lr}                                 @ restaur registres 
    bx lr                                          @return
/******************************************************************/
/*     display text with size calculation                         */ 
/******************************************************************/
/* r0 contains the address of the message */
affichageMess:
    push {r0,r1,r2,r7,lr}                          @ save  registres
    mov r2,#0                                      @ counter length 
1:                                                 @ loop length calculation 
    ldrb r1,[r0,r2]                                @ read octet start position + index 
    cmp r1,#0                                      @ if 0 its over 
    addne r2,r2,#1                                 @ else add 1 in the length 
    bne 1b                                         @ and loop 
                                                   @ so here r2 contains the length of the message 
    mov r1,r0                                      @ address message in r1 
    mov r0,#STDOUT                                 @ code to write to the standard output Linux 
    mov r7, #WRITE                                 @ code call system "write" 
    svc #0                                         @ call systeme 
    pop {r0,r1,r2,r7,lr}                           @ restaur des  2 registres */ 
    bx lr                                          @ return  
/******************************************************************/
/*     Converting a register to a decimal unsigned                */ 
/******************************************************************/
/* r0 contains value and r1 address area   */
/* r0 return size of result (no zero final in area) */
/* area size => 11 bytes          */
.equ LGZONECAL,   10
conversion10:
    push {r1-r4,lr}                                 @ save registers 
    mov r3,r1
    mov r2,#LGZONECAL
1:                                                  @ start loop
    bl divisionpar10U                               @ unsigned  r0 <- dividende. quotient ->r0 reste -> r1
    add r1,#48                                      @ digit
    strb r1,[r3,r2]                                 @ store digit on area
    cmp r0,#0                                       @ stop if quotient = 0 
    subne r2,#1                                     @ else previous position
    bne 1b                                          @ and loop
                                                    @ and move digit from left of area
    mov r4,#0
2:
    ldrb r1,[r3,r2]
    strb r1,[r3,r4]
    add r2,#1
    add r4,#1
    cmp r2,#LGZONECAL
    ble 2b
                                                      @ and move spaces in end on area
    mov r0,r4                                         @ result length 
    mov r1,#' '                                       @ space
3:
    strb r1,[r3,r4]                                   @ store space in area
    add r4,#1                                         @ next position
    cmp r4,#LGZONECAL
    ble 3b                                            @ loop if r4 <= area size
 
100:
    pop {r1-r4,lr}                                    @ restaur registres 
    bx lr                                             @return
 
/***************************************************/
/*   division par 10   unsigned                    */
/***************************************************/
/* r0 dividende   */
/* r0 quotient    */
/* r1 remainder   */
divisionpar10U:
    push {r2,r3,r4, lr}
    mov r4,r0                                          @ save value
    ldr r3,iMagicNumber                                @ r3 <- magic_number    raspberry 1 2
    umull r1, r2, r3, r0                               @ r1<- Lower32Bits(r1*r0) r2<- Upper32Bits(r1*r0) 
    mov r0, r2, LSR #3                                 @ r2 <- r2 >> shift 3
    add r2,r0,r0, lsl #2                               @ r2 <- r0 * 5 
    sub r1,r4,r2, lsl #1                               @ r1 <- r4 - (r2 * 2)  = r4 - (r0 * 10)
    pop {r2,r3,r4,lr}
    bx lr                                              @ leave function 
iMagicNumber:  	.int 0xCCCCCCCD
 
 