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它可以,但它必须假设内联程序集没有设置自己的开场白。