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.