/* ARM assembly Raspberry PI */ /* program game24Solver.s */ /* REMARK 1 : this program use routines in a include file see task Include a file language arm assembly for the routine affichageMess conversion10 see at end of this program the instruction include */ /* for constantes see task include a file in arm assembly */ /************************************/ /* Constantes */ /************************************/ .include "../constantes.inc" .equ STDIN, 0 @ Linux input console .equ READ, 3 @ Linux syscall .equ NBDIGITS, 4 @ digits number .equ TOTAL, 24 .equ BUFFERSIZE, 80 /*********************************/ /* Initialized data */ /*********************************/ .data szMessRules: .ascii "24 Game\n" .ascii "The program will display four randomly-generated \n" .asciz "single-digit numbers and search a solution for a total to 24\n\n" szMessDigits: .asciz "The four digits are @ @ @ @ and the score is 24. \n" szMessOK: .asciz "Solution : \n" szMessNotOK: .asciz "No solution for this problem !! \n" szMessNewGame: .asciz "New game (y/n) ? \n" szCarriageReturn: .asciz "\n" .align 4 iGraine: .int 123456 /*********************************/ /* UnInitialized data */ /*********************************/ .bss .align 4 sZoneConv: .skip 24 sBuffer: .skip BUFFERSIZE iTabDigit: .skip 4 * NBDIGITS @ digits table iTabOperand1: .skip 4 * NBDIGITS @ operand 1 table iTabOperand2: .skip 4 * NBDIGITS @ operand 2 table iTabOperation: .skip 4 * NBDIGITS @ operator table /*********************************/ /* code section */ /*********************************/ .text .global main main: @ entry of program ldr r0,iAdrszMessRules @ display rules bl affichageMess 1: mov r3,#0 ldr r12,iAdriTabDigit ldr r5,iAdrszMessDigits 2: @ loop generate random digits mov r0,#8 bl genereraleas add r0,r0,#1 str r0,[r12,r3,lsl #2] @ store in table ldr r1,iAdrsZoneConv bl conversion10 @ call decimal conversion mov r2,#0 strb r2,[r1,r0] @ reduce size display area with zéro final mov r0,r5 ldr r1,iAdrsZoneConv @ insert conversion in message bl strInsertAtCharInc mov r5,r0 add r3,r3,#1 cmp r3,#NBDIGITS @ end ? blt 2b @ no -> loop mov r0,r5 bl affichageMess mov r0,#0 @ start leval mov r1,r12 @ address digits table bl searchSoluce cmp r0,#-1 @ solution ? bne 3f @ no ldr r0,iAdrszMessOK bl affichageMess bl writeSoluce @ yes -> write solution in buffer ldr r0,iAdrsBuffer @ and display buffer bl affichageMess b 10f 3: @ display message no solution ldr r0,iAdrszMessNotOK bl affichageMess 10: @ display new game ? ldr r0,iAdrszCarriageReturn bl affichageMess ldr r0,iAdrszMessNewGame bl affichageMess bl saisie cmp r0,#'y' beq 1b cmp r0,#'Y' beq 1b 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 iAdrszMessRules: .int szMessRules iAdrszMessDigits: .int szMessDigits iAdrszMessNotOK: .int szMessNotOK iAdrszMessOK: .int szMessOK iAdrszMessNewGame: .int szMessNewGame iAdrsZoneConv: .int sZoneConv iAdriTabDigit: .int iTabDigit /******************************************************************/ /* recherche solution */ /******************************************************************/ /* r0 level */ /* r1 table value address */ /* r0 return -1 if ok */ searchSoluce: push {r1-r12,lr} @ save registers sub sp,#4* NBDIGITS @ reserve size new digits table mov fp,sp @ frame pointer = address stack mov r10,r1 @ save table add r9,r0,#1 @ new level rsb r3,r9,#NBDIGITS @ last element digits table ldr r4,[r1,r3,lsl #2] @ load last element cmp r4,#TOTAL @ equal to total to search ? bne 0f @ no cmp r9,#NBDIGITS @ all digits are used ? bne 0f @ no mov r0,#-1 @ yes -> it is ok -> end b 100f 0: mov r5,#0 @ indice loop 1 1: @ begin loop 1 cmp r5,r3 bge 9f ldr r4,[r10,r5,lsl #2] @ load first operand ldr r8,iAdriTabOperand1 str r4,[r8,r9,lsl #2] @ and store in operand1 table add r6,r5,#1 @ indice loop 2 2: @ begin loop 2 cmp r6,r3 bgt 8f ldr r12,[r10,r6,lsl #2] @ load second operand ldr r8,iAdriTabOperand2 str r12,[r8,r9,lsl #2] @ and store in operand2 table mov r7,#0 @ k mov r8,#0 @ n 3: cmp r7,r5 beq 4f cmp r7,r6 beq 4f ldr r0,[r10,r7,lsl #2] @ copy other digits in new table on stack str r0,[fp,r8,lsl #2] add r8,r8,#1 4: add r7,r7,#1 cmp r7,r3 ble 3b add r7,r4,r12 @ addition test str r7,[fp,r8,lsl #2] @ store result of addition mov r7,#'+' ldr r0,iAdriTabOperation str r7,[r0,r9,lsl #2] @ store operator mov r0,r9 @ pass new level mov r1,fp @ pass new table address on stack bl searchSoluce cmp r0,#0 blt 100f @ soustraction test cmp r4,r12 subgt r7,r4,r12 suble r7,r12,r4 str r7,[fp,r8,lsl #2] mov r7,#'-' ldr r0,iAdriTabOperation str r7,[r0,r9,lsl #2] mov r0,r9 mov r1,fp bl searchSoluce cmp r0,#0 blt 100f mul r7,r4,r12 @ multiplication test str r7,[fp,r8,lsl #2] mov r7,#'*' //vidregtit mult ldr r0,iAdriTabOperation str r7,[r0,r9,lsl #2] mov r0,r9 mov r1,fp bl searchSoluce cmp r0,#0 blt 100f 5: @ division test push {r1-r3} mov r0,r4 mov r1,r12 bl division // mov r7,r9 cmp r3,#0 bne 6f str r2,[fp,r8,lsl #2] mov r7,#'/' ldr r0,iAdriTabOperation str r7,[r0,r9,lsl #2] mov r0,r9 mov r1,fp bl searchSoluce b 7f 6: mov r0,r12 mov r1,r4 bl division cmp r3,#0 bne 7f str r2,[fp,r8,lsl #2] mov r7,#'/' ldr r0,iAdriTabOperation str r7,[r0,r9,lsl #2] mov r0,r9 mov r1,fp bl searchSoluce 7: pop {r1-r3} cmp r0,#0 blt 100f add r6,r6,#1 @ increment indice loop 2 b 2b 8: add r5,r5,#1 @ increment indice loop 1 b 1b 9: 100: add sp,#4* NBDIGITS @ stack alignement pop {r1-r12,lr} bx lr @ return iAdriTabOperand1: .int iTabOperand1 iAdriTabOperand2: .int iTabOperand2 iAdriTabOperation: .int iTabOperation /******************************************************************/ /* write solution */ /******************************************************************/ writeSoluce: push {r1-r12,lr} @ save registers ldr r6,iAdriTabOperand1 ldr r7,iAdriTabOperand2 ldr r8,iAdriTabOperation ldr r10,iAdrsBuffer mov r4,#0 @ buffer indice mov r9,#1 1: ldr r5,[r6,r9,lsl #2] @ operand 1 ldr r11,[r7,r9,lsl #2] @ operand 2 ldr r12,[r8,r9,lsl #2] @ operator cmp r12,#'-' beq 2f cmp r12,#'/' beq 2f b 3f 2: @ if division or soustraction cmp r5,r11 @ reverse operand if operand 1 is < operand 2 movlt r2,r5 movlt r5,r11 movlt r11,r2 3: @ conversion operand 1 = r0 mov r0,r5 mov r1,#10 bl division cmp r2,#0 addne r2,r2,#0x30 strneb r2,[r10,r4] addne r4,r4,#1 add r3,r3,#0x30 strb r3,[r10,r4] add r4,r4,#1 ldr r2,[r7,r9,lsl #2] strb r12,[r10,r4] @ operator add r4,r4,#1 mov r0,r11 @ conversion operand 2 mov r1,#10 bl division cmp r2,#0 addne r2,r2,#0x30 strneb r2,[r10,r4] addne r4,r4,#1 add r3,r3,#0x30 strb r3,[r10,r4] add r4,r4,#1 mov r0,#'=' str r0,[r10,r4] @ conversion sous total add r4,r4,#1 cmp r12,#'+' addeq r0,r5,r11 cmp r12,#'-' subeq r0,r5,r11 cmp r12,#'*' muleq r0,r5,r11 cmp r12,#'/' udiveq r0,r5,r11 mov r1,#10 bl division cmp r2,#0 addne r2,r2,#0x30 strneb r2,[r10,r4] addne r4,r4,#1 add r3,r3,#0x30 strb r3,[r10,r4] add r4,r4,#1 mov r0,#'\n' str r0,[r10,r4] add r4,r4,#1 add r9,#1 cmp r9,#NBDIGITS blt 1b mov r1,#0 strb r1,[r10,r4] @ store 0 final 100: pop {r1-r12,lr} bx lr @ return iAdrsBuffer: .int sBuffer /******************************************************************/ /* string entry */ /******************************************************************/ /* r0 return the first character of human entry */ saisie: push {r1-r7,lr} @ save registers mov r0,#STDIN @ Linux input console ldr r1,iAdrsBuffer @ buffer address mov r2,#BUFFERSIZE @ buffer size mov r7,#READ @ request to read datas svc 0 @ call system ldr r1,iAdrsBuffer @ buffer address ldrb r0,[r1] @ load first character 100: pop {r1-r7,lr} bx lr @ return /***************************************************/ /* Generation random number */ /***************************************************/ /* r0 contains limit */ genereraleas: push {r1-r4,lr} @ save registers ldr r4,iAdriGraine ldr r2,[r4] ldr r3,iNbDep1 mul r2,r3,r2 ldr r3,iNbDep2 add r2,r2,r3 str r2,[r4] @ maj de la graine pour l appel suivant cmp r0,#0 beq 100f add r1,r0,#1 @ divisor mov r0,r2 @ dividende bl division mov r0,r3 @ résult = remainder 100: @ end function pop {r1-r4,lr} @ restaur registers bx lr @ return /*****************************************************/ iAdriGraine: .int iGraine iNbDep1: .int 0x343FD iNbDep2: .int 0x269EC3 /***************************************************/ /* ROUTINES INCLUDE */ /***************************************************/ .include "../affichage.inc"