Search code examples
cgccinline-assemblyuppercaseatt

Accessing address of a string in inline assembly in gcc


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;

  }

Solution

  • 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