Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 回文函数总是为错误报告偏移量#1_C_String_Assembly_X86_Return Value - Fatal编程技术网

C 回文函数总是为错误报告偏移量#1

C 回文函数总是为错误报告偏移量#1,c,string,assembly,x86,return-value,C,String,Assembly,X86,Return Value,我正在编写一个x86汇编函数,用于确定字符串是否为回文(空终止符除外) 如果字符串是回文,则此函数将返回0;如果字符串不是回文,则将返回失败的比较(即字符串左半部分不匹配字符的索引) 虽然它成功地检测到哪些字符串是回文,哪些字符串不是回文,但它总是报告1作为失败回文测试的索引,而不管它实际上在哪里失败 汇编代码: .386 .MODEL FLAT, C .CODE ; Determines whether or not a given string is a palindrome

我正在编写一个x86汇编函数,用于确定字符串是否为回文(空终止符除外)

如果字符串是回文,则此函数将返回0;如果字符串不是回文,则将返回失败的比较(即字符串左半部分不匹配字符的索引)

虽然它成功地检测到哪些字符串是回文,哪些字符串不是回文,但它总是报告
1
作为失败回文测试的索引,而不管它实际上在哪里失败

汇编代码:

.386
.MODEL FLAT, C
.CODE
    ; Determines whether or not a given string is a palindrome
    ; Uses:
    ;   ECX - pointer to start of string (incremented till halfway)
    ;   EDX - pointer to end of string (decremented till halfway)
    ;   AL - dereference character from ECX for comparison
    ;   BL - dereference character from EDX for comparison
    ;   ESI - index where comparison failed in case strings are not palindromes
    ; Arguments:
    ;   [ESP+4] - pointer to string to test
    ;   [ESP+8] - length of string
    ; Returns:
    ; 0 = string is a palindrome
    ; > 0 = string is not a palindrome; return value is the # comparison that failed (e.g. AABAAA would return 3)
    ; C prototype: int __cdecl palin(char *str, int len);
    palin PROC
        push ebx
        push esi
        ; Load ECX with a pointer to the first character in the string
        mov ecx, dword ptr [esp+12]
        ; Copy the pointer into EDX then add the length so EDX points to the end of the string
        mov edx, ecx
        add edx, dword ptr [esp+16]
        xor esi, esi
        loop0:
            ; Begin loop with decrement of EDX to skip the null terminator
            dec edx
            inc esi
            mov al, byte ptr [ecx]
            mov bl, byte ptr [edx]
            cmp al, bl
            ; Comparison fail = strings cannot be palindromes
            jnz not_palindrome
            inc ecx
            ; If start ptr >= end ptr we are done, else keep looping
            cmp ecx, edx 
        jl loop0
        ; Return 0 = success; string is a palindrome
        xor eax, eax
        jmp end_palin
        not_palindrome: 
        ; Return > 0 = fail; string is not a palindrome
            mov eax, esi
        end_palin:  
            pop esi
            pop ebx
            ret
    palin ENDP
END
用于装配功能的C驱动程序:

#include <stdio.h>
#include <string.h>

int __cdecl palin(char *str, int len);

int __cdecl main(int argc, char *argv[])
{
    int ret;
    if(argc<2) 
    {
        printf("Usage: pal word");
        return 0;
    }
    if(ret = (palin(argv[1], strlen(argv[1])) > 0))
    {
        printf("%s is not a palindrome; first comparison that failed was #%d\n",  argv[1], ret);    
    }
    else
    {
        printf("%s is a palindrome\n", argv[1]);
    }
    return 0;
}

最后一行应该返回3而不是1-有人知道这里发生了什么吗?

代码中几乎没有bug。。。您正在寻找的是:

if(ret=(佩林(argv[1],斯特伦(argv[1]))>0))

在好的C/C++编译器中,这应该会发出警告,我想,您在使用什么?您是否使用
-Wall-Wextra
(这些用于
gcc
clang
,对于其他编译器,您应该查看其文档)

它执行的是
ret=(res>0)
,而(res>0)是布尔表达式,所以它是
0
1

你可能想要
if((ret=palin(argv[1],strlen(argv[1])))>0)
,这说明了为什么有时候亲吻并将这些东西分成两行更好


其他错误:

jl loop0
:应该是
jb
ecx
edx
是内存指针,因此不带符号。如果将在0x8000000边界上分配数据,则
jl
首先将失败
cmp

您可以简化退出逻辑:

    ; Return 0 = success; string is a palindrome
        xor esi, esi    ; fake "esi" index = 0, reusing "not palindrome" exit code fully
    not_palindrome: 
    ; Return > 0 = fail; string is not a palindrome
        mov eax, esi
        pop esi
        pop ebx
        ret
最后一个风格挑剔:
jnz not_palindrome
=>我会使用
jne
别名,因为您比较两个字符是否相等,而不是“零”(这是相同的指令,只是不同的别名,我倾向于同时使用这两个,试图使用更合适的来遵循我对功能的“人类”描述)

您还可以执行
cmpal,[edx]
操作,而无需将第二个字符加载到
bl
(再保存一条指令,而不关闭
ebx
,这样您就不需要再
推/弹出ebx
,再保存两条指令)


如果您坚持只为“易读”代码而将第二个字符加载到寄存器中,您仍然可以使用
ah
作为第二个字符,将
ebx
从代码中完全删除。

代码中几乎没有错误。。。您正在寻找的是:

if(ret=(佩林(argv[1],斯特伦(argv[1]))>0))

在好的C/C++编译器中,这应该会发出警告,我想,您在使用什么?您是否使用
-Wall-Wextra
(这些用于
gcc
clang
,对于其他编译器,您应该查看其文档)

它执行的是
ret=(res>0)
,而(res>0)是布尔表达式,所以它是
0
1

你可能想要
if((ret=palin(argv[1],strlen(argv[1])))>0)
,这说明了为什么有时候亲吻并将这些东西分成两行更好


其他错误:

jl loop0
:应该是
jb
ecx
edx
是内存指针,因此不带符号。如果将在0x8000000边界上分配数据,则
jl
首先将失败
cmp

您可以简化退出逻辑:

    ; Return 0 = success; string is a palindrome
        xor esi, esi    ; fake "esi" index = 0, reusing "not palindrome" exit code fully
    not_palindrome: 
    ; Return > 0 = fail; string is not a palindrome
        mov eax, esi
        pop esi
        pop ebx
        ret
最后一个风格挑剔:
jnz not_palindrome
=>我会使用
jne
别名,因为您比较两个字符是否相等,而不是“零”(这是相同的指令,只是不同的别名,我倾向于同时使用这两个,试图使用更合适的来遵循我对功能的“人类”描述)

您还可以执行
cmpal,[edx]
操作,而无需将第二个字符加载到
bl
(再保存一条指令,而不关闭
ebx
,这样您就不需要再
推/弹出ebx
,再保存两条指令)


如果您坚持将第二个字符加载到寄存器中只是为了“易于阅读”代码,您仍然可以使用
ah
作为第二个字符,从代码中完全删除该
ebx

使用调试器逐步检查代码。使用调试器逐步检查代码。描述为人类读者选择适当JCC同义词的另一种方式是说,您应该选择具有正确语义含义的同义词。描述选择适当JCC同义词的另一种方式对于人类读者来说,就是说你应该选择一个具有正确语义的词。