C++;将参数传递给内联汇编函数 我在C++中有内联ASM的问题。我试图实现快速strlen,但它不起作用-当我使用\uu declspec(裸)关键字调试器将输入地址显示为0x000000,当我不使用该关键字时,eax指向一些垃圾,函数返回各种值
以下是代码:C++;将参数传递给内联汇编函数 我在C++中有内联ASM的问题。我试图实现快速strlen,但它不起作用-当我使用\uu declspec(裸)关键字调试器将输入地址显示为0x000000,当我不使用该关键字时,eax指向一些垃圾,函数返回各种值,c++,c,assembly,inline-assembly,C++,C,Assembly,Inline Assembly,以下是代码: int fastStrlen(char *input) // I know that function does not calculate strlen { // properly, but I just want to know why it crashes _asm // access violation when I try to write to varia
int fastStrlen(char *input) // I know that function does not calculate strlen
{ // properly, but I just want to know why it crashes
_asm // access violation when I try to write to variable x
{
mov ecx, dword ptr input
xor eax, eax
start:
mov bx, [ecx]
cmp bl, '\0'
je Sxend
inc eax
cmp bh, '\0'
je Sxend
inc eax
add ecx, 2
jmp start
Sxend:
ret
}
}
int _tmain(int argc, _TCHAR* argv[])
{
char* test = "test";
int x = fastStrlen(test);
cout << x;
return 0;
}
int fastStrlen(char*input)//我知道这个函数不计算strlen
{//没错,但我只是想知道它为什么会崩溃
_asm//尝试写入变量x时发生访问冲突
{
mov ecx,dword ptr输入
异或eax,eax
开始:
mov bx,[ecx]
cmp bl,“\0”
杰斯森德
埃克斯公司
cmp bh,“\0”
杰斯森德
埃克斯公司
添加ecx,2
jmp启动
Sxend:
ret
}
}
int _tmain(int argc,_TCHAR*argv[]
{
char*test=“test”;
int x=快速斯特伦(测试);
不能不使用\u declspec(裸体)
因为在这种情况下,编译器不会生成尾声和序言指令,如果您想访问参数fastStrlen
,您需要像编译器期望的那样生成序言。因为您不知道编译器期望什么,所以应该让它生成序言
这意味着您不能只使用ret
返回调用方,因为这意味着您提供了自己的尾声。因为您不知道编译器使用了什么序言,所以您不知道需要实现什么尾声来反转它。相反,将返回值赋给内联assem之前在函数中声明的C变量bly语句,并在正常的C return语句中返回该变量。例如:
int fastStrlen(char *input)
{
int retval;
_asm
{
mov ecx, dword ptr input
...
Sxend:
mov retval,eax
}
return retval;
}
正如您在评论中所指出的,您的代码将无法改进编译器运行库中的strlen实现。它还会读取长度为偶数的字符串末尾,如果字符串末尾的字节未映射到内存中,这将导致内存故障。您希望mov
而不是lea
o、 你不是在返回长度,而是在返回地址。将16位寄存器与'\0'
进行比较也不会达到你想要的效果。顺便说一句,这不会太快,你也不需要asm来完成这项工作。@Jester mov不起作用,是的,我知道我现在返回的val是错误的,但我更改了它,因为我没有尽管错误是由于使用了ESI寄存器,但它是ABI特定的(因此实际上取决于处理器、操作系统和编译器)。您必须使用eax
作为返回值。如果需要,您可以在加载后将其归零。此外,您也不允许销毁ebx
。@Jester soo我必须将-mov eax&&eax更改为返回值并将8字节reg与“\0”进行比较。除非编译器是死机,否则它应该能够引用相关参数不带任何开场白的esp
。@Jester它可以,但它必须假设内联程序集没有设置自己的开场白。