0

I have this code:

    AREA palindrome, CODE, READONLY

SWI_Exit EQU 0x11

      ENTRY

start

      LDR   r0,=string

      MOV   r1,r0

loop  LDRB  r2,[r1],#1

      CMP   r2,#0

      BNE   loop

      SUB   r1,r1,#2

      BL    pal

stop  SWI   SWI_Exit

 

pal   MOV   r10,#0x0

again LDRB  r3,[r0]

      LDRB  r4,[r1]

      CMP   r3,r4

      BNE   notpal

 

      CMP   r0,r1

      BEQ   waspal

      ADD   r2,r0,#1

      CMP   r2,r1

      BEQ   waspal

      ADD   r0,r0,#1

      SUB   r1,r1,#1

      B     again

 

waspal      MOV   r0,#0x1

notpal      MOV   r0, #0x2

 

string      DCB   "abcba",0

      END

But right now it only checks if it is a palindrome for strings that do not have any punctuation. I would like it so that when I enter a string with or without punctuation and spaces it stores 1 in r0 and 2 if it is not.

So right now when I enter:

"abcba"

I get that it is a palindrome, but when I have

"abc ba"

It is counted as not a palindrome.

Also I have this bug where it does not store any value in register 0 when finishing the loop. But if I change it so that I store the result in two different registers (one in r0 and one in r10) then it works.

Stuart Fong
  • 603
  • 1
  • 13
  • 21

1 Answers1

2

You can vastly simplify your loop-end condition. do{ ...; r0++, r1--; }while(r0<r1); You don't have to care about whether they pass each other or meet exactly, just cmp / blo (branch if unsigned "lower").

Then you can add skipping non-alphabetic characters to both pointer increments. (You don't seem to even be trying to do that, so of course it finds that "abc ba" isn't a palindrome. It's not when you consider all 6 bytes.)

Also, you're missing bx lr in your return paths. Single-step with a debugger to see execution fall through both mov r0, #value instructions.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • Do you mind if you can post an answer with the corrected code? I'd really appreciate it. I'm not really familiar with do while loops. – Stuart Fong Oct 30 '20 at 05:36
  • @StuartFong: I wasn't planning to do your homework for you. There isn't even an attempt to skip punctuation. I only posted this as an answer because it was getting too long for a comment. Also, you haven't defined exactly what "punctuation" is. Do you want to skip every non-alphabetic character, so you keep both lower and upper-case letters? I assume only ASCII, not UTF-8 or something... It should be as simple as replacing pointer-increment with scanning until you find the next alphabetic character in that direction (or hit the start or end of the string, so that's a corner case...) – Peter Cordes Oct 30 '20 at 05:56
  • Fair enough. What I mean by punctuation is capitals, spaces, and any non alphabet character. When you say it's as simple as "simple as replacing pointer-increment with scanning until you find the next alphabetic character in that direction" would there be a way to check the character is punctuation because I am using ASCII characters, and the range between them is 41-5A for capitals and 61-7A for lower case. Is there an operation that just checks whether the character is in that range? – Stuart Fong Oct 30 '20 at 16:54
  • @StuartFong: yes, there are existing Stack Overflow Q&As about checking to see if a byte is an alphabetic character. e.g. [How can I check if a character is a letter in assembly?](https://stackoverflow.com/a/31824566) is an x86 version or an optimized range check (checks for upper or lower with a single sequence of OR / SUB / CMP+branch.) Or a simplistic range-check that just does `c >= 'a' && c <= 'z'` the naive way, with two branches, in ARM asm: [ARM Assembly - Change input file to only include capital letters and spaces, write to output](https://stackoverflow.com/q/31632020) – Peter Cordes Oct 30 '20 at 21:31