我编写了下面的汇编代码,用于将字符串从小写字母转换为大写字母,但由于我无法访问我正在转换的字符串的地址,因此它无法正常工作。这段代码不起作用的原因?
#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;
}
答案 0 :(得分:0)
这是我的解决方案与上述略有不同,感谢FUZxxi指出。我应该说检索程序集在很大程度上有帮助,它可能很难理解但它会给你带来实际问题。如果有人想了解我想要实现的目标,我已经写了足够的评论。
/* 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);
}
如果使用&#34; gcc -m32&#34;进行编译,则上述代码应该有效。选项,如果您正在编译amd64。我遇到了这样的问题&#34;致命错误:sys / cdefs.h:没有这样的文件或目录&#34;
解决方案:安装此软件包:libc6-dev-i386
答案 1 :(得分:0)
接受的答案中的代码似乎有一些问题:
更像这样的事情:
char *convert(char *str)
{
char *res = str;
char temp;
__asm__ __volatile__ (
"dec %[str]\n"
"REPEAT:\n\t"
"inc %[str]\n\t"
"movb (%[str]), %[temp]\n\t" /* Read the next char */
"testb %[temp], %[temp]\n\t"
"jz END\n\t" /* Is the char null */
"cmpb $97, %[temp]\n\t" /* >= 'a'? */
"jb REPEAT\n\t"
"cmpb $122, %[temp]\n\t" /* <= 'z'? */
"ja REPEAT\n\t"
"subb $32, %[temp]\n\t" /* Perform lowercase */
"mov %[temp], (%[str])\n\t" /* Write back to memory */
"jmp REPEAT\n"
"END:\n"
: [str] "+r" (str), [temp] "=r" (temp)
: /* no inputs */
: "memory"
);
/* Note that at this point, str points to the null.
str - res is the length. */
return res;
}
此代码:
\n\t
(而非;
)可使gcc -S
的输出更易于阅读。或者如果你真的想要花哨,可以在'c'中编写代码,并使用gcc -O2 -S
查看输出。