// 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