-3

This is a C code of Caesar Cipher which takes a given text and an encryption key as its parameters. I have to convert this into ARM Inline Assembler.

void rotN(char *str, int n)
{
  char *p;
  for (p = str; *p != 0; p++)
  {
    int currChar = (int)*p;
    if (currChar >= 97 && currChar <= 122)
    {
      currChar = currChar + n;
      if (currChar > 122)
      {
        currChar = currChar - 26;
      }
      *p = (char)currChar;
    }
    if (currChar >= 65 && currChar <= 90)
    {
      currChar = currChar + n;
      if (currChar > 90)
      {
        currChar = currChar - 26;
      }
      *p = (char)currChar;
    }
  }
}

Over here I've used 65, 90, 97, 122 and 0 as they're ASCII values of 'A', 'Z', 'a', 'z' and '\0'.

void rotN(char *str, int n){
  asm volatile(
    "str     %[str], [%[str]]\n\t"
    "mov     r0, %[n]\n\t"
    "mov     r1, %[str]\n\t"
    "mov     r2, #0\n\t"
    "1:     ldrb    r3, [r1, r2]\n\t"
    "cmp     r3, #0\n\t"
    "beq     2f\n\t"
    "cmp     r3, #97\n\t"
    "blo     2f\n\t"
    "cmp     r3, #122\n\t"
    "bhi     2f\n\t"
    "sub     r3, r3, #26\n\t"
    "b       1b\n\t"
    "2:     add     r3, r3, r0\n\t"
    "cmp     r3, #122\n\t"
    "bhi     2f\n\t"
    "cmp     r3, #97\n\t"
    "blo     2f\n\t"
    "sub     r3, r3, #26\n\t"
    "b       1b\n\t"
    "2:\n\t"
    "strb    r3, [r1, r2]\n\t"
    :
    : [str] "r" (str), [n] "r" (n)
    : "r0", "r1", "r2", "r3"
  );
}

The code above is what I've done so far, but doesn't seem to work. What am i doing wrong?

George
  • 1
  • So your actual question is in the title or in the question body? They are quite different. – Eugene Sh. Jul 26 '22 at 20:16
  • 2
    To answer the question in your title: yes, there is. They wouldn't have given you this exercise if it wasn't possible. As for the question body, do not say "it doesn't work." That's not a problem description. Instead, state what you expect the code to do and what it does instead. Also, make sure to ask a *specific question* instead of just dumping your code. – fuz Jul 26 '22 at 20:24
  • 1
    As for characters, there's no need to manually look up ASCII codes in the code chart. You can write things like `#'A'` just fine. – fuz Jul 26 '22 at 20:25
  • `CPSR` is missing in your clobber list. And you shouldn't use registers directly if possible which is in this case. - declare some local variables and use them instead. – Jake 'Alquimista' LEE Jul 27 '22 at 03:11
  • 1
    What you need isn't an answer but a complete course on (inline) assembly. Even if your code worked, it would be much slower than the C version. – Jake 'Alquimista' LEE Jul 27 '22 at 03:18

2 Answers2

0

Well, you could use the appropriate gcc cross compiler to generate the assembly code. I'm not sure if this satisfies your requirements though.

Save the code into let's say rot.c and run the following, replacing gcc with the appropriate cross compiler version for your ARM device:

gcc rot.c -S -O0

The above command also turns off optimizations (-O0) which may be helpful.

A rot.s will be generated that has the entire assembly for the file. You won't need the whole file, but it may help you figure out where you went wrong in your manual porting effort.

Jake Miller
  • 108
  • 8
  • This does not answer OPs question and should really be a comment. – fuz Jul 27 '22 at 17:52
  • @fuz My answer seems to answer the title. OP asked how to convert C code to assembler. In addition, I'm trying to get my rep up so I CAN submit comments. Unfortunately I must resort to answers at this point. So help me out by giving an upvote :-D – Jake Miller Jul 27 '22 at 22:37
  • 1
    This is not an admissible reason for making a comment into an answer, but I've now reviewed your contribution and upvoted them as appropriate to help you out of this catch 22. – fuz Jul 27 '22 at 23:19
  • @fuz Thanks! Can you point me to comments vs answers discussions so I can git gooder? – Jake Miller Jul 27 '22 at 23:56
  • 1
    It's simple: answers are for answers only. If you just want to give advice that does not directly answer the question, write a comment. – fuz Jul 28 '22 at 00:36
0
.syntax unified
.arch armv5
.global rotN
.text

// void rotN(char *str, int n);

pStr        .req    r0
delta       .req    r1
currChar    .req    r2
temp        .req    r3
dummy       .req    r12

.balign 64
.func
rotN:
    ldrb    currChar, [pStr], #1

.balign 16
1:
    cmp     currChar, #0
    add     temp, currChar, delta
    bxeq    lr

    cmp     currChar, #97
    rsbshs  dummy, currChar, #122
    blo     5f

    cmp     temp, #122
    subhi   temp, temp, #26
    ldrb    currChar, [pStr], #1
    strb    temp, [pStr, #-2]
    b       1b

.balign 16
5:
    cmp     currChar, #65
    rsbshs  dummy, currChar, #90
    ldrb    currChar, [pStr], #1
    blo     1b

    cmp     temp, #90
    subhi   temp, temp, #26
    strb    temp, [pStr, #-2]
    b       1b

.endfunc
.end

Above is a pure assembly version utilizing the standard instruction set.
Consider it a textbook example which is roughly 10% faster at best than the C version. (Is it worth it???)
Please do not ask further questions about details. Just follow it instruction by instruction until you fully understand the whole code - This is the best way to learn.

If it were a professional assignment, and the CPU is armv6 or higher, I'd use enhanced DSP/SIMD instructions and make it around twice as fast, but that's a different story.

Jake 'Alquimista' LEE
  • 6,197
  • 2
  • 17
  • 25