C 回文函数总是为错误报告偏移量#1
我正在编写一个x86汇编函数,用于确定字符串是否为回文(空终止符除外) 如果字符串是回文,则此函数将返回0;如果字符串不是回文,则将返回失败的比较(即字符串左半部分不匹配字符的索引) 虽然它成功地检测到哪些字符串是回文,哪些字符串不是回文,但它总是报告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
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同义词的另一种方式对于人类读者来说,就是说你应该选择一个具有正确语义的词。