A palindrome implementation and testing application for A.U.TH. Microprocessors and peripherals Lab.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

122 lines
4.0 KiB

  1. /*!
  2. * @file
  3. * main.c
  4. * @brief
  5. * A palindrome implementation and testing application
  6. * for A.U.TH. Microprocessors and peripherals Lab.
  7. *
  8. * Created on: May 1, 2020
  9. * Author: Christos Choutouridis AEM: 8997
  10. * email : <cchoutou@ece.auth.gr>
  11. */
  12. #include <stdint.h>
  13. /*!
  14. * The RAM address to use for palindrome result.
  15. * @note:
  16. * Select a RAM location above `__initial_sp`. See your startup_xx.s for details.
  17. * Keil's RAM layout is:
  18. *
  19. * RAM: |<-Heap_Size-><-Stack_Size->|<- WASTED RAM SPACE ->|
  20. * ^ ^ ^
  21. * | | |
  22. * Start:0x20000000 __initial_sp End of RAM
  23. *
  24. */
  25. #define RESULT 0x20001000
  26. /*!
  27. * String length calculation.
  28. * @arg src{R0} Pointer to string
  29. * @return {R0} String length, -1 if src is NULL
  30. */
  31. __asm uint32_t strLength (const char* src) {
  32. // R0: length, return value
  33. // R1: src
  34. // R2: v = *src
  35. MOV R1, R0 // Get variable
  36. CMP R1, #0 // if (src{R1} == NULL)
  37. MOVEQ R0, #-1 // return -1;
  38. BXEQ LR
  39. MOV R0, #0 // length{R0} =0;
  40. len_loop // do {
  41. LDRB R2, [R1], #1 // v{R2} = *src++;
  42. CMP R2, #0 // if(v)
  43. ADDNE R0, R0, #1 // ++length{R0};
  44. BNE len_loop // } while (v);
  45. BX LR // return length;
  46. }
  47. /*!
  48. * A string palindrome predicate.
  49. * @note
  50. * We use a simple O(n), no stack algorithm.
  51. * @note
  52. * This function also writes to RAM address @ref RESULT the return value (which is nasty).
  53. * @arg src{R0} Pointer to string
  54. * @return {R0} True if palindrome, false if not or src is NULL pointer
  55. * @note
  56. * We consider an empty string "" to be a palindrome, as we can see it the same way both
  57. * from the front and the back.
  58. */
  59. __asm uint32_t isPalindrome (const char* src) {
  60. // R0: src[]
  61. // R1: i
  62. // R2: j
  63. // R3: v1 = src[i]
  64. // R4: v2 = src[j]
  65. PUSH {R4, LR}
  66. CMP R0, #0 // if (src{R0} == NULL)
  67. BEQ pal_false // return false;
  68. MOV R4, R0 // save R0
  69. BL strLength // j{R2} = strLength(src) - 1
  70. SUB R2, R0, #1
  71. MOV R0, R4 // src{R0}
  72. MOV R1, #0 // i{R1} =0;
  73. pal_loop
  74. CMP R1, R2 // while (i<j) {
  75. BGE pal_true
  76. LDRB R3, [R0, R1] // v1 = *src[i];
  77. LDRB R4, [R0, R2] // v2 = *src[j];
  78. CMP R3, R4 // if (v1 == v2) {
  79. ADDEQ R1, R1, #1 // ++i;
  80. SUBEQ R2, R2, #1 // --j;
  81. BEQ pal_loop // // goto loop;
  82. pal_false // } else
  83. MOV R0, #0 // return *RESULT = 0;
  84. LDR R1, =RESULT
  85. STRB R0, [R1]
  86. POP {R4, PC}
  87. // }
  88. pal_true
  89. MOV R0, #1 // return *RESULT = 1;
  90. LDR R1, =RESULT
  91. STRB R0, [R1]
  92. POP {R4, PC}
  93. }
  94. /*!
  95. * Main routine.
  96. * @note
  97. * This routine plays the role of debuging-mode unit testing.
  98. */
  99. int main(void) {
  100. const char *s1 = "hello world!"; // Not a palindrome
  101. const char *s2 = "aibohphobia"; // Aibophobia def= "Irational fear of palindromes", palindrome.
  102. const char *s3 = ""; // Empty string, palindrome.
  103. const char *s4 = 0; // NULL pointer. Out of scope, not palindrome
  104. uint32_t res1 = isPalindrome (s1); // Test case 1
  105. uint32_t res2 = isPalindrome (s2); // Test case 2
  106. uint32_t res3 = isPalindrome (s3); // Test case 3
  107. uint32_t res4 = isPalindrome (s4); // Test case 4
  108. while (1); // Trap forever
  109. //return 0; //!< comment out return, to suppress "statement is unreachable" warning.
  110. //!^ @note:
  111. //! **Weird** Keil's way for "statement is unreachable", suppresion.
  112. }