Instructions
Objective
Write an ARM assignment to check if a magic square is valid in ARM assembly language using KEIL.
Requirements and Specifications

Screenshots of output


Source Code
AREA magicSquares, CODE
EXPORT __main
ALIGN
ENTRY
__main PROC
; the code will initialize R1 and use a test matrix to run the code,
; if R1 is set somewhere else and a matrix is set at 0x20000010,
; then uncomment the following line
; B start
MOV R1, #4 ; matrix size N
; copy test matrix to matrix space at 0x20000010
LDR R2, =tstmat1 ; start address of test matrix 1
;LDR R2, =tstmat2 ; start address of test matrix 2
LDR R3, =0x20000010 ; start address of matrix
MOV R4, R1 ; number of rows
copyrows
MOV R5, R1 ; number of cols
copycols
LDR R0, [R2], #4 ; load value from test matrix
STR R0, [R3], #4 ; store value in matrix
SUBS R5, R5, #1 ; decrement remaining cols
BNE copycols ; repeat while not zero
SUBS R4, R4, #1 ; decrement remaining rows
BNE copyrows ; repeat while not zero
start
; fill rows variable
LDR R2, =0x20000010 ; load address of matrix
LDR R3, =rows ; point to start of rows array
LSL R4, R1, #2 ; size of a row = N*4
MOV R5, #0 ; start in position 0
loopr
STR R2, [R3, R5, LSL #2]; save address in rows
ADD R2, R2, R4 ; advance to next row
ADD R5, R5, #1 ; increment index
CMP R5, R1 ; compare index with N
BLT loopr ; repeat while i < N
; fill cols variable
LDR R2, =0x20000010 ; load address of matrix
LDR R3, =cols ; point to start of cols array
MOV R4, #0 ; start in position 0
loopc
STR R2, [R3, R4, LSL #2]; save address in cols
ADD R2, R2, #4 ; advance to next col
ADD R4, R4, #1 ; increment index
CMP R4, R1 ; compare index with N
BLT loopc ; repeat while i < N
; calculate sum number = N*(N^2 + 1)/2
MUL R2, R1, R1 ; N*N
ADD R3, R2, #1 ; N*N + 1
MUL R3, R3, R1 ; N*(N*N + 1)
LSR R3, R3, #1 ; N*(N*N + 1)/2
MOV R8, #0 ; assume it's not magic at start
; First we test the matrix elements
LDR R4, =rows ; load rows
MOV R5, #0 ; row index
loop1
LDR R6, [R4, R5, LSL #2] ; load row address
MOV R7, #0 ; col index
loop2
LDR R0, [R6, R7, LSL #2] ; load element from row
CMP R0, #1 ; check if >= 1
BLT endTest ; if < 1, it's not a magic square
CMP R0, R2 ; check if <= N^2
BGT endTest ; if > N^2, it's not a magic square
ADD R7, R7, #1 ; increment col index
CMP R7, R1 ; compare index with N
BLT loop2 ; repeat while col < N
ADD R5, R5, #1 ; increment row index
CMP R5, R1 ; compare index with N
BLT loop1 ; repeat while row < N
; We now test the row sums
LDR R4, =rows ; load rows
MOV R5, #0 ; row index
sumrows1
LDR R6, [R4, R5, LSL #2] ; load row address
MOV R7, #0 ; col index
MOV R9, #0 ; start sum in zero
sumcols1
LDR R0, [R6, R7, LSL #2] ; load element from row
ADD R9, R9, R0 ; add element to sum
ADD R7, R7, #1 ; increment col index
CMP R7, R1 ; compare index with N
BLT sumcols1 ; repeat while col < N
CMP R9, R3 ; check if sum = N*(N*N + 1)/2
BNE endTest ; if != N^2, it's not a magic square
ADD R5, R5, #1 ; increment row index
CMP R5, R1 ; compare index with N
BLT sumrows1 ; repeat while row < N
; We now test the column sums
LDR R4, =cols ; load cols
MOV R5, #0 ; col index
sumcols2
LDR R6, [R4, R5, LSL #2] ; load col address
MOV R7, #0 ; row index
MOV R9, #0 ; start sum in zero
sumrows2
MUL R0, R7, R1 ; row * num cols
LSL R0, R0, #2 ; address of element = row * num cols * 4
LDR R0, [R6, R0] ; load element from col
ADD R9, R9, R0 ; add element to sum
ADD R7, R7, #1 ; increment row index
CMP R7, R1 ; compare index with N
BLT sumrows2 ; repeat while row < N
CMP R9, R3 ; check if sum = N*(N*N + 1)/2
BNE endTest ; if != N^2, it's not a magic square
ADD R5, R5, #1 ; increment col index
CMP R5, R1 ; compare index with N
BLT sumcols2 ; repeat while col < N
; We now test the first diagonal sum
LDR R4, =rows ; load rows
MOV R5, #0 ; row index
MOV R6, #0 ; start sum in zero
sumdiag1
LDR R7, [R4, R5, LSL #2] ; load row address
LDR R0, [R7, R5, LSL #2] ; load element from row at index position (row,row)
ADD R6, R6, R0 ; add element to sum
ADD R5, R5, #1 ; increment row index
CMP R5, R1 ; compare index with N
BLT sumdiag1 ; repeat while row < N
CMP R6, R3 ; check if sum = N*(N*N + 1)/2
BNE endTest ; if != N^2, it's not a magic square
; Lastly, we test the second diagonal sum
LDR R4, =rows ; load rows
SUB R5, R1, #1 ; row index = N-1
MOV R6, #0 ; col index = 0
MOV R7, #0 ; start sum in zero
sumdiag2
LDR R9, [R4, R5, LSL #2] ; load row address
LDR R0, [R9, R6, LSL #2] ; load element from row at index position (row,col)
ADD R7, R7, R0 ; add element to sum
SUB R5, R5, #1 ; decrement row index
ADD R6, R6, #1 ; increment col index
CMP R6, R1 ; compare col with N
BLT sumdiag2 ; repeat while col < N
CMP R7, R3 ; check if sum = N*(N*N + 1)/2
BNE endTest ; if != N^2, it's not a magic square
MOV R8, #1 ; if we end all tests, matrix is a magic square
endTest
; here, R8 will have 1 if the matrix is magic and 0 otherwise
done B done
ENDP
ALIGN AREA myData1, DATA, READWRITE
SPACE 16 ; leave 16 bytes (0x10)
matrix SPACE 400 ; start of matrix at 0x20000010, at most 10x10
rows SPACE 40 ; space to save rows (at most 10)
cols SPACE 40 ; space to save columns (at most 10)
AREA myData2, DATA, READONLY
tstmat1 DCD 16, 3, 2, 13 ; magic square matrix
DCD 5, 10, 11, 8
DCD 9, 6, 7, 12
DCD 4, 15, 14, 1
tstmat2 DCD 5, 10, 11, 8 ; swapped 2 first rows, not magic
DCD 16, 3, 2, 13
DCD 9, 6, 7, 12
DCD 4, 15, 14, 1
END