I have written the below assembly code to convert a string from lower case to uppercase, It's not completely working because i'm not able to access the address of a string that i'm converting. this code is not working why?
#include<stdio.h>
int convert(char *str)
{
char *ptr;
__asm__ __volatile__ ( "movl (%1),%%ebx;"
"subl $1,%%ebx;"
"movl %%ebx,%0;"
"REPEAT: addl $1,%%ebx;"
"testl %%ebx,%%ebx;"
"je END;"
"movzbl 0(%%ebx),%%ecx;"
"cmpl $97, %%ecx;"
"jb END;"
"cmpl $122,%%ecx;"
"ja END;"
"subb $32,0(%%ebx);"
"jmp REPEAT;"
"END: movl %%ebx,(%0);"
:"=r" (ptr)
:"r" (str)
);
printf("converted string =%s\n", str);
}
int main()
{
int i;
char str[] = "convert";
i = convert(str);
return 0;
}
Here is my solution slightly different than above, Thanks FUZxxi for pointing it out. I should say that retrieving assembly helps in a great extent, it can be hard to understand but it gives you the actual problem. I have written enough comments if somebody wants to understand what i'm trying to achieve.
/* code to convert from lower case to upper case */
int convert(char *str)
{
__asm__ __volatile__ ( "movl %1,%%ebx;" // Get the address of str
"subl $1,%%ebx;"
"REPEAT: addl $1,%%ebx;"
"movl 0(%%ebx),%%edx" // Move the contents to edx
"movzbl %%dl,%%ecx;" // moving last character to ecx
"testl %%ecx,%%ecx;" // compare if it's null
"je END;"
"cmpl $97, %%ecx;"
"jb END;"
"cmpl $122,%%ecx;"
"ja END;"
"subb $32,(%%ebx);" // if its lower case, subtract 32
"jmp REPEAT;"
"END:;"
: // No output specified
:"r" (str) //input
:"ecx","edx" //clobbers
);
printf("converted string =%s\n", str);
}
Above code should work if you compile using "gcc -m32" option, if you are compiling for amd64. I encountered a problem doing that
"fatal error: sys/cdefs.h: No such file or directory "
solution : Install this package: libc6-dev-i386