Home > OS >  Is there a way to convert this C code to ARM Inline Assembly?
Is there a way to convert this C code to ARM Inline Assembly?

Time:07-27

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?

CodePudding user response:

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.

CodePudding user response:

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

  • Related