## Instructions

**Objective**

## Requirements and Specifications

**Screenshots of output**

**Source Code**

.arch armv7

.cpu cortex-a53

.data

piles: .space 180 @ space to save the size of at most 45 piles

startMsg: .asciz "Initial pile configuration: "

nextMsg: .asciz "Next pile configuration: "

.text

.global main

main:

push {fp,lr} @ save used registers

mov r0,#0 @ set arg to zero

bl time @ call time(0)

bl srand @ call srand(time(0)) to initialize random seed

ldr r0, =piles @ pass pile address to function

bl genPiles @ generate card piles

ldr r0, =startMsg @ print initial message

bl printf

ldr r0, =piles @ pass pile address to function

bl printPiles @ print initial piles

b checkLast @ check if we generated the last config or loop

mainLoop:

ldr r0, =piles @ pass pile address to function

bl newPile @ generate new card pile

ldr r0, =nextMsg @ print next message

bl printf

ldr r0, =piles @ pass pile address to function

bl printPiles @ print piles

checkLast:

ldr r0, =piles @ pass pile address to function

bl isLastConfig @ check if it's last configuration

cmp r0, #0 @ if not

beq mainLoop @ try again

mov r0, #0 @ return 0

pop {fp,lr} @ restore used registers

bx lr

@ Generate piles using 45 cards

@ On entry:

@ R0 = pile address

genPiles:

push {r4-r5,fp,lr} @ save used registers

mov r4, r0 @ save address in r4

mov r5, #45 @ initially we have 45 cards

genLoop:

bl rand @ generate a random number

udiv r1, r0, r5 @ divide random number by number of cards

mul r3, r1, r5 @ multiply result by number of cards

sub r0, r0, r3 @ subtract random number - multiplication to get remainder

add r0, r0, #1 @ increment to get number between 1 and number of cards

str r0, [r4], #4 @ save random number in pile, advance to next one

sub r5, r5, r0 @ remove random number from number of cards

cmp r5,#0 @ if there are still cards

bne genLoop @ generate more

str r5, [r4] @ save a zero to indicate end of piles

pop {r4-r5,fp,lr} @ restore used registers

bx lr @ return to caller

@ Print the current pile configuration

@ On entry:

@ R0 = pile address

.data

numFmt: .asciz "%-3d"

nline: .asciz "\n"

.text

printPiles:

push {r4,fp,lr} @ save used registers

mov r4, r0 @ save address in r4

printLoop:

ldr r1, [r4], #4 @ load number from pile and advance to next one

cmp r1, #0 @ if this is the last pile

beq endPrint @ end printing

ldr r0, =numFmt @ print number

bl printf

b printLoop @ repeat loop

endPrint:

ldr r0, =nline @ print newline

bl printf

pop {r4,fp,lr} @ restore used registers

bx lr @ return to caller

@ Generate new pile

@ On entry:

@ R0 = pile address

newPile:

push {fp,lr} @ save used registers

mov r1, #0 @ new pile size is zero

newLoop:

ldr r2, [r0] @ load number from pile

cmp r2, #0 @ if this is the last pile

beq endNew @ end creating pile

add r1, r1, #1 @ increment new pile size

sub r2, r2, #1 @ decrement current pile size

str r2, [r0] @ save updated size

cmp r2, #0 @ see if pile has disappeared

bne skip @ if not, skip

bl compactPiles @ else, compact piles, removing this zero

b newLoop @ loop reusing this position

skip:

add r0, r0, #4 @ advance to next pile

b newLoop @ repeat loop

endNew:

str r1, [r0], #4 @ save new pile at the last position and advance

str r2, [r0] @ save zero to indicate end of piles

pop {fp,lr} @ restore used registers

bx lr @ return to caller

@ Compact piles by moving all piles down to the initial position, thus removing

@ the initial one

@ On entry:

@ R0 = pile address to remove

compactPiles:

push {r4-r5,fp,lr} @ save used registers

mov r4, r0 @ save address in r4

compactLoop:

ldr r5, [r4, #4] @ load next number from pile

str r5, [r4] @ save in current position

cmp r5, #0 @ if this is the last pile

beq endCompact @ end compacting pile

add r4, r4, #4 @ advance to next pile

b compactLoop @ repeat loop

endCompact:

pop {r4-r5,fp,lr} @ restore used registers

bx lr @ return to caller

@ Check if last configuration was reached

@ On entry:

@ R0 = pile address

@ Returns:

@ R0 = 1 if it's last, 0 if not

isLastConfig:

push {fp,lr} @ save used registers

mov r1, #0 @ save mask in zero

lastLoop:

ldr r2, [r0] @ load number from pile

cmp r2, #0 @ if this is the last pile

beq checkMask @ end checking pile

cmp r2, #9 @ check if number is valid

bgt notLast @ if > 9, this is not the last config

mov r3, #1 @ else, load 1

lsl r3, r3, r2 @ move to bit position n (1-9)

orr r1, r1, r3 @ add to mask

add r0, r0, #4 @ advance to next pile

b lastLoop @ repeat loop

checkMask:

ldr r0, =0x3FE @ load mask with bit positions 1-9 set to 1

cmp r1, r0 @ if the positions 1-9 are filled

bne notLast @ if not, is not the last

mov r0, #1 @ else, it's the last

b endCheck @ end

notLast:

mov r0, #0 @ not last

endCheck:

pop {fp,lr} @ restore used registers

bx lr @ return to caller