Instructions
Objective
Write a program in ARMv8 assembly language to create a contrived version of the “Mastermind” game.
Requirements and Specifications
Write an assembly language assignment where game is a contrived version of Mastermind: the computer hides a NxM color code chosen fromC colors. The user tries to crack the hidden code by taking several steps. The first step is for the user to make a guess. The computer responds by providing feedback hints. The game ends when the user:
- cracks the game,
- reaches a maximum number of trials R without cracking the hidden code, or
- choses to quit the game. The game will also end if the timer is exhausted before cracking the code.
Screenshots of output
Source Code
define(argvr,x19)
define(N,x20)
define(M,x21)
define(C,x22)
define(R,x23)
define(remaining,x24)
define(duration,x25)
define(playerName,x26)
define(guess,x27)
define(try,x28)
define(code,x19)
define(S, d8)
.equ lasttime, 0
.equ win, 8
.equ mode, 12
.equ trhead, 16
.equ transFilename, 24
.equ buffer, 56
.text
helloMsg: .string "Hello %s!\n"
testGameMsg: .string "Running Mastermind in test `mode'\n"
playGameMsg: .string "Running Mastermind in play `mode'\n"
hiddenMsg: .string "Hidden `code' is: "
startMsg: .string "\nStart cracking...\n"
usageMsg: .string "Usage:\n %s name `N' `M' `C' `R' `mode' [`duration']\n"
invArgsMsg: .string "Invalid command line argument.\n"
colorFmt: .string "%c "
hiddenFmt: .string "- "
hintHeader: .string "B W `R' `S' T\n"
hintBW: .string "%-2d %-2d "
hintRST: .string "%-2d %.2f %d:%02d\n"
newline: .string "\n"
badInputMsg: .string "Invalid input. Please `try' again\n"
wonMsg: .string "Cracked!\n"
lostMsg: .string "You lost!\n"
scoreMsg: .string "Final score: %.2f\n"
showTopMsg: .string "Show bottom/top scores (B/T/`N')? "
askAgainMsg: .string "Play again (Y/`N')? "
logFilename: .string "scores.log"
logWMode: .string "a"
logRMode: .string "r"
logFmt: .string "%-20s %-12.2f %d:%02d\n"
logInf: .string "%-20s %-12.2f %-12.2f\n"
intFmt: .string "%d"
promptN: .string "Number of scores to print?: "
topScoresMsg: .string "\nTop %d Scores:\n"
botScoresMsg: .string "\nBottom %d Scores:\n"
scoresHeader: .string "Name Score Time (s)\n"
transFileFmt: .string "%s-%d.txt"
transWMode: .string "wt"
infinity: .dword 0x7FF0000000000000
.balign 4
.global main
.type main, %function
main:
stp fp, lr, [sp, -16]! // save registers in stack
mov fp, sp
sub sp, sp, 256 // allocate space for variables
mov argvr, x1 // save argv pointer in register
mov duration, 0 // clear duration
cmp x0, 7 // if n arguments < 7
blt badArguments // exit with error
cmp x0, 8 // compare number of arguments with 8
blt grabInputs // if < 8, read inputs
ldr x0, [argvr, 56] // load time string from arguments
bl atoi // convert to integer
mov duration,x0 // save in time register
grabInputs:
ldr playerName, [argvr, 8] // load player name pointer in register
ldr x0, [argvr, 16] // load N string from arguments
bl atoi // convert to integer
uxtw x0, w0 // extend to x0
mov N, x0 // save in N register
ldr x0, [argvr, 24] // load M string from arguments
bl atoi // convert to integer
uxtw x0, w0 // extend to x0
mov M, x0 // save in M register
ldr x0, [argvr, 32] // load C string from arguments
bl atoi // convert to integer
uxtw x0, w0 // extend to x0
mov C, x0 // save in M register
ldr x0, [argvr, 40] // load R string from arguments
bl atoi // convert to integer
uxtw x0, w0 // extend to x0
mov R, x0 // save in R register
ldr x0, [argvr, 48] // load mode string from arguments
bl atoi // convert to integer
str w0, [sp, mode] // save in mode variable
cmp C,5 // check if C >= 5
blt invalidArguments // if not, print error
cmp R,1 // check if R >= 1
blt invalidArguments // if not, print error
cmp M,C // check if M<=C
bgt invalidArguments // if not, print error
ldr w0, [sp, mode] // load mode
cmp w0, 0 // check if mode is 0
blt invalidArguments // if <0, print error
cmp w0, 1 // check if mode is 1
bgt invalidArguments // if >1, print error
mov x0,0
bl time // Set the time seed for the random number generator
bl srand // Call the srand function to initialize seed
cmp duration, 0 // if no duration was given
bne continue // if duration is set, continue
mov x0, 5 // multiply N by 5
mul duration, N, x0 // set duration = N*5
continue:
mul x0, N, M // multiply n*m
bl malloc // allocate space for code
mov code, x0 // save in code
mul x0, N, M // multiply n*m
bl malloc // allocate space for guess
mov guess, x0 // save in guess
gameStart:
str xzr, [sp, trhead] // initialize history list to zero
mov x0, code // save in code
mov x1, N // use N
mov x2, M // use M
mov x3, C // use colors
mov x4, guess // use guess
bl initializeGame // generate initial game
ldr x0, =helloMsg // load hello message address
mov x1, playerName // load player name address
bl printf // print the hello message
ldr w0, [sp, mode] // load mode
cmp w0, 0 // check if mode is play
beq startPlay // if play, start
ldr x0, =testGameMsg // else, print it's a test game
bl printf
ldr x0, =hiddenMsg // print hidden message
bl printf
mov x0, code // load code
mov x1, N // use N
mov x2, M // use M
bl printCode // print initial code
ldr x0, =newline // print newline
bl printf
startPlay:
bl showScores // ask if scores should be shown
ldr x0, =startMsg // load address of start message
bl printf // print start message
mov x0, 60 // 60 seconds per minute
mul remaining, duration, x0 // remaining = duration*60
mov try, 1 // current try
ucvtf S, xzr // clear score
str wzr, [sp, win] // not winning yet
mov x0, code // load code
mov x1, N // use N
mov x2, M // use M
add x3, sp, trhead
bl printHidden // print hidden hint
gameLoop:
mov x0, guess // save in guess
mov x1, N // use N
mov x2, M // use M
mov x3, C // use C
bl readInput // read guess from user
cmp w0, -1 // if exit
beq dropGame // drop the game
cmp w0, 0 // if error
bne checkGuess // if no error, check guess
ldr x0, =badInputMsg // load address of error message
bl printf // print error message
b gameLoop // read again
checkGuess:
mov x0, guess // load guess
mov x1, N // use N
mov x2, M // use M
add x3, sp, trhead
bl printGuess // print guess
mov x0, guess // pass guess
mov x1, code // pass code
mov x2, N // pass N
mov x3, M // pass M
add x4, sp, trhead
bl displayHints // display the hints
mul x2, N, M
cmp x0, x2 // see if guess it's exact
bne addScore // if not, add score
mov w2, 1
str w2, [sp, win] // else, set win to 1
addScore:
ucvtf d0, x0 // convert B to float
ucvtf d1, x1 // convert W to float
ucvtf d2, try // convert R to float
fmov d3, 2.0 // divide by 2
fdiv d1, d1, d3 // W/2
fadd d0, d0, d1 // B+W/2
fdiv d0, d0, d2 // (B+W/2)/R
fadd S, S, d0 // add to score
mov x0, 100 // load 100.0
ucvtf d1, x0
fmul S, S, d1 // round to 100
frinta S, S
fdiv S, S, d1
mov x0, xzr
bl time // get current time
uxtw x0, w0
cmp try, 1 // check if it's the first try
beq skip // if so, don't update remaining time
ldr x1, [sp, lasttime] // load last time
sub x1, x0, x1 // time difference
sub remaining, remaining, x1 // get new remaining time
skip:
str x0, [sp, lasttime] // save time as last time
cmp remaining, 0 // check if remaining is above zero
bgt getMinSec // if so, get min :sec
mov remaining, 0 // else, clear remaining time
getMinSec:
mov x0, 60 // 60 seconds per minute
udiv x3, remaining, x0 // remaining/60
msub x4, x3, x0, remaining // calculate remainder
mov x2, try // load R
fmov d0, S // load current score
add x0, sp, buffer
ldr x1, =hintRST // load format to print R, S and T
bl sprintf // print R, S and T
add x0, sp, buffer
add x1, sp, trhead
bl saveString // print R, S, T
ldr w0, [sp, win] // load win status
cmp w0, 1 // if win
beq gameCracked // end game
cmp remaining, 0 // if no time
beq gameLost // end game
add try, try, 1 // increment number of tries
cmp try, R // compare with maximum tries
ble gameLoop // repeat game loop if <= max tries
gameLost:
ldr x0, =lostMsg // print lost message
bl printf
fmov d0, S // get current score
mov x0, try // get try
mov x1, remaining // get remaining time
bl calculateScore // get last score
fneg d8, d0 // convert to negative
b printScore
gameCracked:
ldr x0, =wonMsg // print won message
bl printf
fmov d0, S // get current score
mov x0, try // get try
mov x1, remaining // get remaining time
bl calculateScore // get last score
fmov d8, d0 // save score
printScore:
ldr x0, =scoreMsg // print score message
fmov d0, d8
bl printf
mov x0, playerName // load player name
fmov d0, d8 // load score
ucvtf d1, remaining // convert remaining to float
bl logScore
mov x0, xzr
bl time // get current time
mov w3, w0
add x0, sp, transFilename
ldr x1, =transFileFmt // mov x2, playerName
bl sprintf
add x0, sp, transFilename
add x1, sp, trhead
bl transcriptGame // save the transcript
add x0, sp, trhead
bl freeTranscript // free the transcript
bl showScores // show scores
ldr x0, =askAgainMsg // ask if new game should be started
bl printf
bl readChar // read input
cmp w0, 'Y' // if new game
beq gameStart // restart
cmp w0, 'y' // if new game
beq gameStart // restart
b endGame // end game
dropGame:
mov x0, playerName // load player name
ldr x1, =infinity
ldr d1, [x1] // load time +inf
fmov d0, d1 // load score -inf
fneg d0, d0
bl logScore
endGame:
mov x0, code // free allocated space for code
mov x1, guess // free allocated space for guess
bl exitGame // exit game
badArguments:
ldr x0, =usageMsg // print usage message
ldr x1, [argvr] // load first argument (program name)
bl printf
b terminate // terminate program
invalidArguments:
ldr x0, =invArgsMsg // print error message
bl printf
terminate:
mov sp, fp // restore stack pointer
ldp fp, lr, [sp], 16 // restore registers from stack
ret // return to os
// Initialize the game
// void initializeGame (*code, N, M, C, *guess)
.type initializeGame, %function
initializeGame:
stp fp, lr, [sp, -16]! // save registers in stack
stp x19, x20, [sp, -16]! // save registers in stack
stp x21, x22, [sp, -16]! // save registers in stack
stp x23, x24, [sp, -16]! // save registers in stack
mov x19, x0 // save code pointer
mov x22, x4 // save guess pointer
sub x20, x3, 1 // save C - 1
mul w21, w1, w2 // get number of characters= n*m
mov w23, w21
initLoop:
mov w0, 0 // generate number between 0
mov w1, w20 // and C - 1
mov w2, 0 // positive
bl randomNum // generate random number
bl Color // convert to color
strb w0, [x19], 1 // save in color array
subs w21, w21, 1 // decrement number of chars to generate
bne initLoop // repeat while not zero
mov w21, w23 // get number of characters
clrLoop:
mov w0, 32 // save space
strb w0, [x22], 1 // save in color array
subs w21, w21, 1 // decrement number of chars
bne clrLoop // repeat while not zero
ldp x23, x24, [sp], 16 // restore registers from stack
ldp x21, x22, [sp], 16 // restore registers from stack
ldp x19, x20, [sp], 16 // restore registers from stack
ldp fp, lr, [sp], 16 // restore registers from stack
ret // return to calling function
// Generate a random number between n and m, the number is negative if neg is 1
// int randomNum(n, m, neg)
.type randomNum, %function
randomNum:
stp fp, lr, [sp, -16]! // save registers in stack
stp x19, x20, [sp, -16]! // save registers in stack
stp x21, x22, [sp, -16]! // save registers in stack
mov x19, x0 // save n
mov x20, x1 // save m
mov x21, x2 // save neg
bl rand // generate a random number
sub w1, w20, w19 // calculate m-n
add w1, w1, 1 // calculate m-n+1
udiv w2, w0, w1 // divide random number / (m-n+1)
msub w3, w2, w1, w0 // calculate remainder
add w0, w3, w19 // add n to get number between n and m (including n and m)
cmp x21, 0 // check if need a negative
beq rndReturn // if not negative, return
neg w0, w0 // else, negate
rndReturn:
ldp x21, x22, [sp], 16 // restore registers from stack
ldp x19, x20, [sp], 16 // restore registers from stack
ldp fp, lr, [sp], 16 // restore registers from stack
ret // return to calling function
// Convert number to letter color
// char Color(n)
.type Color, %function
Color:
add w0, w0, 65 // convert 0... to 'A'...
ret // return to calling function
// Print code
// void printCode(*code, n, m)
.type printCode, %function
printCode:
stp fp, lr, [sp, -16]! // save registers in stack
stp x19, x20, [sp, -16]! // save registers in stack
mov x19, x0 // save code pointer
mul w20, w1, w2 // get number of characters= n*m
prLoop:
ldrb w1, [x19], 1 // load char from color array
ldr x0, =colorFmt // print color
bl printf
subs w20, w20, 1 // decrement number of chars to print
bne prLoop // repeat while not zero
ldp x19, x20, [sp], 16 // restore registers from stack
ldp fp, lr, [sp], 16 // restore registers from stack
ret // return to calling function
// Print guess
// void printGuess(*code, n, m, transcript)
.type printGuess, %function
printGuess:
stp fp, lr, [sp, -16]! // save registers in stack
stp x19, x20, [sp, -16]! // save registers in stack
stp x21, x22, [sp, -16]! // save registers in stack
mov fp, sp
sub sp, sp, 256 // allocate buffer
mov x19, x0 // save code pointer
mov x21, x3 // save transcript
mov x22, sp
mul w20, w1, w2 // get number of characters= n*m
prgLoop:
ldrb w1, [x19], 1 // load char from color array
//ldr x0, =colorFmt // print color
//bl printf
strb w1, [x22], 1
mov w1, 32
strb w1, [x22], 1
subs w20, w20, 1 // decrement number of chars to print
bne prgLoop // repeat while not zero
strb wzr, [x22], 1
mov x0, sp
mov x1, x21
bl saveString // save in transcript
mov sp, fp
ldp x21, x22, [sp], 16 // restore registers from stack
ldp x19, x20, [sp], 16 // restore registers from stack
ldp fp, lr, [sp], 16 // restore registers from stack
ret // return to calling function
// Print hidden code
// void printHidden(*code, n, m, *transcript)
.type printHidden, %function
printHidden:
stp fp, lr, [sp, -16]! // save registers in stack
stp x19, x20, [sp, -16]! // save registers in stack
stp x21, x22, [sp, -16]! // save registers in stack
mov fp, sp
sub sp, sp, 256 // allocate buffer
strb wzr, [sp]
mov x19, x0 // save code pointer
mov x21, x3 // save transcript
mul w20, w1, w2 // get number of characters= n*m
phLoop:
mov x0, sp
ldr x1, =hiddenFmt // print hidden char
bl strcat
subs w20, w20, 1 // decrement number of chars to print
bne phLoop // repeat while not zero
mov x0, sp
ldr x1, =hintHeader // print hint header
bl strcat
mov x0, sp
mov x1, x21
bl saveString // save in transcript
mov sp, fp
ldp x21, x22, [sp], 16 // restore registers from stack
ldp x19, x20, [sp], 16 // restore registers from stack
ldp fp, lr, [sp], 16 // restore registers from stack
ret // return to calling function
// Read the input from the user, returns 1 if no errors, -1 if user wants to exit
// bool readInput(*input, N, M, C)
.type readInput, %function
readInput:
stp fp, lr, [sp, -16]! // save registers in stack
stp x19, x20, [sp, -16]! // save registers in stack
stp x21, x22, [sp, -16]! // save registers in stack
mov x19, x0 // save input array pointer
mul w20, w1, w2 // get number of characters= n*m
add w21, w3, 64 // last color char
mov x22, 1 // no errors
rdLoop:
bl getchar // read character
cmp w0, 10 // if enter
beq readEnd
cmp w0, '$' // if exit
beq exitChar
cmp w0, 32 // if space
beq rdLoop // read again
cmp w0, 'A' // if not a letter
blt badChar //
cmp w0, w21 // if not a letter
bgt badChar //
cmp w20, 0 // if we input all chars
beq badChar
strb w0, [x19], 1 // save in array
sub w20, w20, 1 // decrement number of chars to save
b rdLoop // read again
exitChar:
mov x22, -1
b rdLoop // repeat
badChar:
cmp x22, -1 // if exit
beq rdLoop // ignore error
mov x22, 0 // input error
b rdLoop // repeat
readEnd:
cmp x22, -1 // if exit
beq readRet // ignore errors
cmp w20, 0 // else, check if all chars were given
beq readRet // if so, return
mov x22, 0 // else, error
readRet:
mov x0, x22 // return error status
ldp x21, x22, [sp], 16 // restore registers from stack
ldp x19, x20, [sp], 16 // restore registers from stack
ldp fp, lr, [sp], 16 // restore registers from stack
ret // return to calling function
// display hints and returns B,W
// int displayHints(guess, code, n, m, transcript)
.type displayHints, %function
displayHints:
stp fp, lr, [sp, -16]! // save registers in stack
stp x19, x20, [sp, -16]! // save registers in stack
stp x21, x22, [sp, -16]! // save registers in stack
stp x23, x24, [sp, -16]! // save registers in stack
mov fp, sp
mov x19, 0 // no exact matches
mov x20, 0 // no approx matches
mov x23, x4 // save transcript
mul x4, x2, x3 // get number of characters= n*m
sub sp, sp, x4 // allocate first array
mov x21, sp // point to stack
sub sp, sp, x4 // allocate second array
mov x22, sp // point to stack
mov x5, 0 // index = 0
comp1:
ldrb w6, [x0, x5] // load guess character
ldrb w7, [x1, x5] // load code character
cmp w6, w7 // compare chars
bne notEq
add x19, x19, 1 // increment exact matches
mov w6, 1
strb w6, [x21, x5] // save guess character used
strb w6, [x22, x5] // save code character used
b nxtComp1
notEq:
strb wzr, [x21, x5] // save guess character not used
strb wzr, [x22, x5] // save code character not used
nxtComp1:
add x5, x5, 1 // increment index
cmp x5, x4 // if not end
blt comp1 // keep comparing
mov x5, 0 // index guess = 0
comp2:
ldrb w6, [x21, x5] // check if guess character was used
cmp w6, 0 // if used,
bne nxtComp2 // try next
ldrb w6, [x0, x5] // load guess character
mov x7, 0 // index code = 0
comp3:
ldrb w9, [x22, x7] // check if code character was used
cmp w9, 0 // if used,
bne nxtComp3 // try next
ldrb w9, [x1, x7] // load code character
cmp w6, w9 // compare chars
bne nxtComp3 // if not equal, try next code char
add x20, x20, 1 // increment approx matches
mov w6, 1
strb w6, [x21, x5] // save guess character used
strb w6, [x22, x7] // save code character used
b nxtComp2
nxtComp3:
add x7, x7, 1 // increment index
cmp x7, x4 // if not end
bne comp3 // keep comparing
nxtComp2:
add x5, x5, 1 // increment index
cmp x5, x4 // if not end
bne comp2 // keep comparing
endit:
add sp, sp, x4, lsl 1 // remove allocated space in stack
sub sp, sp, 16
mov x0, sp
ldr x1, =hintBW // load hint b w format
mov w2, w19 // load exact matches
mov w3, w20 // load approximate matches
bl sprintf // print result
mov x0, sp
mov x1, x23
bl saveString // save hints
add sp, sp, 16
mov x0, x19 // return exact matches
mov x1, x20 // return approximate matches
ldp x23, x24, [sp], 16 // restore registers from stack
ldp x21, x22, [sp], 16 // restore registers from stack
ldp x19, x20, [sp], 16 // restore registers from stack
ldp fp, lr, [sp], 16 // restore registers from stack
ret // return to calling function
// Calculate overall score
// double calculateScore(S, R, T)
.type calculateScore, %function
calculateScore:
ucvtf d1, x0 // convert tries to float
fdiv d0, d0, d1 // S/R
mov x2, 1000 // multiply remaining time T * 1000
mul x1, x1, x2
ucvtf d2, x1 // convert remaining seconds to float
fmul d0, d0, d2 // (S/R)*T*1000
mov x0, 100 // load 100
ucvtf d1, x0 // counvert to float
fmul d0, d0, d1 // round to 100
frinta d0, d0
fdiv d0, d0, d1
ret // return to calling function
// Exit the game
// void exitGame(*code, *game)
.type exitGame, %function
exitGame:
stp fp, lr, [sp, -16]! // save registers in stack
stp x19, x20, [sp, -16]! // save registers in stack
mov x19, x1
bl free // free allocated space for code
mov x0, x19 // free allocated space for guess
bl free
ldp x19, x20, [sp], 16 // restore registers from stack
ldp fp, lr, [sp], 16 // restore registers from stack
mov x0, xzr // exit (0)
bl exit
// Log the score
// void logScore(name, score, T)
.type logScore, %function
logScore:
stp fp, lr, [sp, -16]! // save registers in stack
stp x19, x20, [sp, -16]! // save registers in stack
stp d8, d9, [sp, -16]! // save registers in stack
sub sp, sp, 32
mov x19, x0 // save name pointer
fmov d8, d0 // save score
fmov d9, d1 // save T
ldr x0, =logFilename // open file
ldr x1, =logWMode // mode to append
bl fopen
mov x20, x0 // save file pointer
mov x0, sp // clear buffer
mov x1, xzr
mov x2, 16
bl memset
mov x0, sp
mov x1, x19 // copy name
mov x2, 16
bl strncpy
mov x0, sp // save name
mov x1, 1
mov x2, 16
mov x3, x20
bl fwrite
stp d8, d9, [sp, -16]! // save registers in stack
mov x0, sp // save score
mov x1, 1
mov x2, 8
mov x3, x20
bl fwrite
add x0, sp, 8 // save time
mov x1, 1
mov x2, 8
mov x3, x20
bl fwrite
ldp d8, d9, [sp], 16 // restore registers from stack
mov x0, x20 // close file
bl fclose
add sp, sp, 32
ldp d8, d9, [sp], 16 // restore registers from stack
ldp x19, x20, [sp], 16 // restore registers from stack
ldp fp, lr, [sp], 16 // restore registers from stack
ret
// Load score file and returns array and array size
// scores* loadScores()
.type loadScores, %function
loadScores:
stp fp, lr, [sp, -16]! // save registers in stack
stp x19, x20, [sp, -16]! // save registers in stack
stp x21, x22, [sp, -16]! // save registers in stack
ldr x0, =logFilename // open file
ldr x1, =logRMode // mode to read
bl fopen
mov x19, x0 // save file pointer
mov x1, 0 // move to end of file
mov x2, 2
bl fseek
mov x0, x19 // get file size
bl ftell
uxtw x0, w0
mov x20, x0 // save size
mov x0, x20
bl malloc // allocate space for whole file
mov x21, x0
mov x0, x19 // move to start of file
mov x1, xzr
mov x2, xzr
bl fseek
mov x0, x21 // load all scores
mov x1, 1
mov x2, x20
mov x3, x19
bl fread
mov x0, x19 // close the file
bl fclose
mov x0, x21 // return array
lsr x1, x20, 5 // return number of scores
ldp x21, x22, [sp], 16 // restore registers from stack
ldp x19, x20, [sp], 16 // restore registers from stack
ldp fp, lr, [sp], 16 // restore registers from stack
ret
// Display the top n scores on score file
.type displayTop, %function
displayTop:
stp fp, lr, [sp, -16]! // save registers in stack
stp x19, x20, [sp, -16]! // save registers in stack
stp x21, x22, [sp, -16]! // save registers in stack
mov x19, x0 // save n
ldr x0, =topScoresMsg // print top scores message
mov x1, x19
bl printf
ldr x0, =scoresHeader // print header
bl printf
bl loadScores // load all scores
mov x20, x0 // save array
mov x21, x1 // save size
mov x22, x0
mov x0, x20
mov x1, x21
mov x2, 1 // sort inverted (top at bottom)
bl sortScores // sort scores
printTop:
ldr d0, [x20, 24] // load time
bl isinf // check if it's infinite
cmp w0, 0 // if not infinite
beq prScore // print score
ldr x0, =logInf
mov x1, x20 // print name
ldr d0, [x20, 16] // load score
ldr d1, [x20, 24] // load time
bl printf // print entry
b nextTop
prScore:
ldr d0, [x20, 24] // load time
fcvtas x1, d0 // convert to integer
mov x0, 60 // 60 seconds per minute
udiv x2, x1, x0 // t/60
msub x3, x2, x0, x1 // calculate remainder
ldr x0, =logFmt
mov x1, x20 // print name
ldr d0, [x20, 16] // load score
bl printf // print entry
nextTop:
add x20, x20, 32 // advance to next entry
subs x19, x19, 1 // decrement n
beq endTop
subs x21, x21, 1 // decrement size
bne printTop
endTop:
mov x0, x22 // free array
bl free
ldp x21, x22, [sp], 16 // restore registers from stack
ldp x19, x20, [sp], 16 // restore registers from stack
ldp fp, lr, [sp], 16 // restore registers from stack
ret
// Display the bottom n scores on score file
.type displayBottom, %function
displayBottom:
stp fp, lr, [sp, -16]! // save registers in stack
stp x19, x20, [sp, -16]! // save registers in stack
stp x21, x22, [sp, -16]! // save registers in stack
mov x19, x0 // save n
ldr x0, =botScoresMsg
mov x1, x19
bl printf
ldr x0, =scoresHeader // print header
bl printf
bl loadScores // load all scores
mov x20, x0 // save array
mov x21, x1 // save size
mov x22, x0
mov x0, x20
mov x1, x21
mov x2, 0 // sort normally (smallest at bottom)
bl sortScores // sort scores
printBot:
ldr d0, [x20, 24] // load time
bl isinf // check if it's infinite
cmp w0, 0 // if infinite
bne nextBot // go to next value
ldr d0, [x20, 24] // load time
fcvtas x1, d0 // convert to integer
mov x0, 60 // 60 seconds per minute
udiv x2, x1, x0 // t/60
msub x3, x2, x0, x1 // calculate remainder
ldr x0, =logFmt
mov x1, x20 // print name
ldr d0, [x20, 16] // load score
bl printf // print entry
subs x19, x19, 1 // decrement n
beq endBot
nextBot:
add x20, x20, 32 // advance to next entry
subs x21, x21, 1 // decrement size
bne printBot
endBot:
mov x0, x22 // free array
bl free
ldp x21, x22, [sp], 16 // restore registers from stack
ldp x19, x20, [sp], 16 // restore registers from stack
ldp fp, lr, [sp], 16 // restore registers from stack
ret
// Sort the score array in the given direction
// void sortScores(*scores, N, direction)
.type sortScores, %function
sortScores:
stp fp, lr, [sp, -16]! // save registers in stack
sub x1, x1, 1 // decrement to N-1
mov x7, 0 // i = 0
for1:
cmp x7, x1 // for (i = 0; i < N - 1; i++)
beq endfor1
add x5, x0, x7, lsl 5 // array entry i
ldr d0, [x5, 16] // load array[i].score
mov x3, x7 // min = i
add x4, x7, 1 // j = i + 1;
for2:
cmp x4, x1 // for (j = i + 1; j <= N - 1; j++)
bgt endfor2
add x6, x0, x4, lsl 5 // array entry j
ldr d1, [x6, 16] // load array[j].score
cmp x2, 0 // if normal direction
bne invert
fcmp d1, d0 // if (score j < score min)
bge nextj
fmov d0, d1 // set score as new minimum
mov x3, x4 // save j as min
b nextj
invert:
fcmp d1, d0 // if (score j > score min)
ble nextj
fmov d0, d1 // set score as new maximum
mov x3, x4 // save j as max
nextj:
add x4, x4, 1 // j++
b for2 // repeat for
endfor2:
add x5, x0, x7, lsl 5 // array entry i
add x6, x0, x3, lsl 5 // array entry min
ldr x3, [x5] // load array[i].name
ldr x4, [x6] // load array[min].name
str x4, [x5] // swap
str x3, [x6]
ldr x3, [x5, 8] // load array[i].name
ldr x4, [x6, 8] // load array[min].name
str x4, [x5, 8] // swap
str x3, [x6, 8]
ldr x3, [x5, 16] // load array[i].score
ldr x4, [x6, 16] // load array[min].score
str x4, [x5, 16] // swap
str x3, [x6, 16]
ldr x3, [x5, 24] // load array[i].time
ldr x4, [x6, 24] // load array[min].time
str x4, [x5, 24] // swap
str x3, [x6, 24]
add x7, x7, 1 // i++
b for1 // repeat for
endfor1:
ldp fp, lr, [sp], 16 // restore registers from stack
ret
// Read N from user
.type readN, %function
readN:
stp fp, lr, [sp, -16]! // save registers in stack
sub sp, sp, 16 // allocate space in stack
ldr x0, =promptN // prompt for n
bl printf
ldr x0, =intFmt // read an integer
mov x1, sp
bl scanf
lN:
bl getchar // read until enter is pressed
cmp w0, 10
bne lN
ldr w0, [sp] // get read value
uxtw x0, w0 // extend to x0
add sp, sp, 16 // remove allocated space
ldp fp, lr, [sp], 16 // restore registers from stack
ret // return to caller
// Reads a character from input
// char readChar()
.type readChar, %function
readChar:
stp fp, lr, [sp, -16]! // save registers in stack
stp x19, x20, [sp, -16]! // save registers in stack
bl getchar // read input
mov w19, w0 // save char
l0:
cmp w0, 10 // if enter, end input
beq rdChrEnd
bl getchar // read until enter is pressed
b l0
rdChrEnd:
mov w0, w19 // return read char
uxtb x0, w0 // extend to x0
ldp x19, x20, [sp], 16 // restore registers from stack
ldp fp, lr, [sp], 16 // restore registers from stack
ret
// Show the scores depending on user input
// void showScores()
.type showScores, %function
showScores:
stp fp, lr, [sp, -16]! // save registers in stack
ldr x0, =showTopMsg // ask if top/bottom should be printed
bl printf
bl readChar // read input
cmp w0, 'B' // if bottom
beq showBottom // print bottom
cmp w0, 'b' // if bottom
beq showBottom // print bottom
cmp w0, 'T' // if top
beq showTop // print top
cmp w0, 't' // if top
beq showTop // print top
b showEnd // else, end
showBottom:
bl readN // read N value
bl displayBottom // displayBotton(n)
b showEnd
showTop:
bl readN // read N value
bl displayTop // displayTop(n)
showEnd:
ldp fp, lr, [sp], 16 // restore registers from stack
ret
// Save transcript file
// void transcriptGame(*filename, *transcript)
.type transcriptGame, %function
transcriptGame:
stp fp, lr, [sp, -16]! // save registers in stack
stp x19, x20, [sp, -16]! // save registers in stack
mov x19, x1 // save transcript pointer
ldr x1, =transWMode // create transcript file
bl fopen
mov x20, x0 // save file pointer
ldr x19, [x19] // load transcript head
saveLoop:
cmp x19, 0 // if end of transcript
beq endTrans // end loop
mov x0, x20 // load file pointer
ldr x1, [x19] // pass string pointer
bl fprintf // print to file
ldr x19, [x19, 8] // load next transcript
b saveLoop
endTrans:
mov x0, x20 // close file
bl fclose
ldp x19, x20, [sp], 16 // restore registers from stack
ldp fp, lr, [sp], 16 // restore registers from stack
ret
// Free transcript
// void freeTranscript(*transcript)
.type freeTranscript, %function
freeTranscript:
stp fp, lr, [sp, -16]! // save registers in stack
stp x19, x20, [sp, -16]! // save registers in stack
ldr x20, [x0] // load transcript head
freeLoop:
cmp x20, 0 // if end of transcript
beq endFree // end loop
ldr x0, [x20] // pass string pointer
bl free // free string
ldr x19, [x20, 8] // load next transcript
mov x0, x20 // pass node pointer
bl free // free node
mov x20, x19 // use next node for iteration
b freeLoop
endFree:
ldp x19, x20, [sp], 16 // restore registers from stack
ldp fp, lr, [sp], 16 // restore registers from stack
ret
// Insert string to end of transcript and prints it:
// void saveString(*string, *transcript)
saveString:
stp fp, lr, [sp, -16]! // save registers in stack
stp x19, x20, [sp, -16]! // save registers in stack
stp x21, x22, [sp, -16]! // save registers in stack
mov x19, x0 // save string pointer
mov x20, x1 // save transcript pointer
mov x0, x19 // print string
bl printf
mov x0, 16 // node size
bl malloc // allocate node
mov x21, x0 // save node pointer
mov x0, x19 // pass string
bl strlen // get length
add x0, x0, 1
bl malloc // allocate string
mov x22, x0 // save pointer
mov x0, x22 // copy string
mov x1, x19
bl strcpy
str x22, [x21] // save string pointer in node
str xzr, [x21, 8] // save next as null
ldr x0, [x20] // load transcript head
cmp x0, 0 // if empty list
bne findLast // if not, insert at last
str x21, [x20] // save new node as head
b insertEnd
findLast:
ldr x1, [x0, 8] // load next transcript
cmp x1, 0 // if null
beq saveNode // end loop
mov x0, x1 // go to next
b findLast
saveNode:
str x21, [x0, 8] // save new node as last
insertEnd:
ldp x21, x22, [sp], 16 // restore registers from stack
ldp x19, x20, [sp], 16 // restore registers from stack
ldp fp, lr, [sp], 16 // restore registers from stack
ret
define(code,x19)
Similar Samples
Discover expertly crafted programming assignment solutions at ProgrammingHomeworkHelp.com. Our samples showcase top-quality work, demonstrating our commitment to helping students excel. Browse through various projects and see firsthand the level of precision and excellence you can expect from our services.
Assembly Language
Assembly Language
Assembly Language
Assembly Language
Assembly Language
Assembly Language
Assembly Language
Assembly Language
Assembly Language
Assembly Language
Assembly Language
Assembly Language
Assembly Language
Assembly Language
Assembly Language
Assembly Language
Assembly Language
Assembly Language
Assembly Language
Assembly Language