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.
 
 
 

120 lines
3.8 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 R0: Pointer to string
  54. * @return R0: True if predicate
  55. * False if not
  56. */
  57. __asm uint32_t isPalindrome (const char* src) {
  58. // R0: src[]
  59. // R1: i
  60. // R2: j
  61. // R3: v1 = src[i]
  62. // R4: v2 = src[j]
  63. PUSH {R4, LR}
  64. CMP R0, #0 // if (src{R0} == NULL)
  65. BEQ pal_false // return false;
  66. MOV R4, R0 // save R0
  67. BL strLength // j{R2} = strLength(src) - 1
  68. SUB R2, R0, #1
  69. MOV R0, R4 // src{R0}
  70. MOV R1, #0 // i{R1} =0;
  71. pal_loop
  72. CMP R1, R2 // while (i<j) {
  73. BGE pal_true
  74. LDRB R3, [R0, R1] // v1 = *src[i];
  75. LDRB R4, [R0, R2] // v2 = *src[j];
  76. CMP R3, R4 // if (v1 == v2) {
  77. ADDEQ R1, R1, #1 // ++i;
  78. SUBEQ R2, R2, #1 // --j;
  79. BEQ pal_loop // // goto loop;
  80. pal_false // } else
  81. MOV R0, #0 // return *RESULT = 0;
  82. LDR R1, =RESULT
  83. STRB R0, [R1]
  84. POP {R4, PC}
  85. // }
  86. pal_true
  87. MOV R0, #1 // return *RESULT = 1;
  88. LDR R1, =RESULT
  89. STRB R0, [R1]
  90. POP {R4, PC}
  91. }
  92. /*!
  93. * Main routine.
  94. * @note
  95. * This routine plays the role of debuging-mode unit testing.
  96. */
  97. int main(void) {
  98. const char *s1 = "hello world!"; // Not a palindrome
  99. const char *s2 = "aibohphobia"; // Aibophobia def= "Irational fear of palindromes", palindrome.
  100. const char *s3 = ""; // Empty string, palindrome.
  101. const char *s4 = 0; // NULL pointer. Out of scope, not palindrome
  102. uint32_t res1 = isPalindrome (s1); // Test case 1
  103. uint32_t res2 = isPalindrome (s2); // Test case 2
  104. uint32_t res3 = isPalindrome (s3); // Test case 3
  105. uint32_t res4 = isPalindrome (s4); // Test case 4
  106. while (1); // Trap forever
  107. //return 0; //!< comment out return, to suppress "statement is unreachable" warning.
  108. //!^ @note:
  109. //! **Weird** Keil's way for "statement is unreachable", suppresion.
  110. }