A palindrome implementation and testing application for A.U.TH. Microprocessors and peripherals Lab.
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 

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. }