TDT4258/ex1/palin_finder.s

201 lines
3.5 KiB
ArmAsm

// Convention:
// R0 / R1 is method input. Should not be clobbered unless specified otherwise
// R2 - R5 + R8 - R10 is general purpose.
// R6 is the result
// Please note that this will clobber the R6 register.
// To make cpulator ignore this, turn off "Function clobbered caller-saved register" in settings.
.global _start
.section .data // RW Memory
// This is the input you are supposed to check for a palindrome
// You can modify the string during development, however you
// are not allowed to change the label 'input'!
input: .asciz "level"
// input: .asciz "8448"
// input: .asciz "KayAk"
// input: .asciz "step on no pets"
// input: .asciz "Never odd or even"
.align
.text // RO Memory
notAPalindrome: .asciz "Not a palindrome"
palindromeDetected: .asciz "Palindrome detected"
.align
// ------
LED_BASE = 0xff200000
UART_BASE = 0xff201000
// ------
// Returns a pointer to the end of the string
findStringEnd:
MOV R6, R0
MOV R0, R0
fse_loop:
LDRB R5, [R6]
CMP R5, #0x0
BXEQ LR
ADD R6, R6, #1
B fse_loop
// Checks whether the character is valid. Returns 0 or 1
isValidCharacter:
CMP R0, #'A'
BLT ivc_subrange2
CMP R0, #'Z'
BLE ivc_validChar
ivc_subrange2:
CMP R0, #'a'
BLT ivc_subrange3
CMP R0, #'z'
BLE ivc_validChar
ivc_subrange3:
CMP R0, #'0'
BLT ivc_invalidChar
CMP R0, #'9'
BLE ivc_validChar
ivc_invalidChar:
MOV R6, #0
BX LR
ivc_validChar:
MOV R6, #1
BX LR
// Makes the letter lowercase if possible
lowercaseCharacter:
MOV R6, R0
CMP R6, #'A'
BXLT LR
CMP R6, #'Z'
BXGT LR
ADD R6, #0x20
BX LR
isPalindrome:
// R0 is string start
// R1 is string length
PUSH {R0, R1}
// R2 is string pointer moving from start
// R3 is string pointer moving from end
MOV R2, R0
MOV R3, R1
// R8 stores valid lowercased start character for later comparison
// R9 stores valid lowercased end character for later comparison
ip_loop:
CMP R2, R3
BGT ip_returnTrue
// Loop until start char is valid,
// lowercase the letter, and save result in R8
LDRB R0, [R2]
BL isValidCharacter
CMP R6, #1
ADDNE R2, R2, #1
BNE ip_loop
BL lowercaseCharacter
MOV R8, R6
// Same for end char, save in R9
LDRB R0, [R3]
BL isValidCharacter
CMP R6, #1
SUBNE R3, R3, #1
BNE ip_loop
BL lowercaseCharacter
MOV R9, R6
// Compare, potentially return false
CMP R8, R9
BNE ip_returnFalse
// Move both pointers and loop
ADD R2, R2, #1
SUB R3, R3, #1
B ip_loop
ip_returnFalse:
POP {R0, R1}
MOV R6, #0
B evaluatePalindromeResult
ip_returnTrue:
POP {R0, R1}
MOV R6, #1
B evaluatePalindromeResult
_start:
BL resetLEDs
LDR R0, =input
BL findStringEnd
MOV R1, R6
// Palindromes can not be less that two chars
SUB R2, R1, R0
CMP R2, #2
BLT onNotPalindrome
B isPalindrome
evaluatePalindromeResult:
CMP R6, #1
BLEQ onPalindrome
BL onNotPalindrome
resetLEDs:
LDR R8, =LED_BASE
MOV R5, #0b0000000000
STR R5, [R8]
BX LR
onPalindrome:
// Light up LEDS
LDR R8, =LED_BASE
MOV R5, #0b0000011111
STR R5, [R8]
// Write to UART
LDR R8, =UART_BASE
LDR R9, =palindromeDetected
op_write_uart_loop:
LDRB R0, [R9]
CMP R0, #0x0
BEQ _end
STR R0, [R8]
ADD R9, R9, #1
B op_write_uart_loop
onNotPalindrome:
// Light up LEDS
LDR R8, =LED_BASE
MOV R5, #0b1111100000
STR R5, [R8]
// Write to UART
LDR R8, =UART_BASE
LDR R9, =notAPalindrome
onp_write_uart_loop:
LDRB R0, [R9]
CMP R0, #0x0
BEQ _end
STR R0, [R8]
ADD R9, R9, #1
B onp_write_uart_loop
_end:
B _end
.end