[英]Accessing address of a string in inline assembly in gcc
我已經編寫了以下匯編代碼,將字符串從小寫轉換為大寫,因為我無法訪問要轉換的字符串的地址,因此無法完全正常工作。 此代碼不起作用,為什么?
#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;
}
這是我的解決方案,與上面略有不同,感謝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);
}
如果使用amd64進行編譯,則以上代碼在使用“ gcc -m32”選項進行編譯時應該可以工作。 我這樣做時遇到問題
“嚴重錯誤:sys / cdefs.h:沒有這樣的文件或目錄”
解決方案:安裝此軟件包:libc6-dev-i386
接受的答案中的代碼似乎有一些問題:
怎么樣呢?
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
查看輸出。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.