此函数接受输入字符串并检查它是否为回文序列。然而,由于内存错误,它会中断。我已经盯着它看了几个小时,但无法弄清楚问题。有许多不必要的推动,但我害怕玩它并打破更多。非常感谢任何帮助。
__declspec(naked)
int isPalindrome(char *input_string, int left_index, int right_index)
{
// C code to be converted to x86 assembly
/*
// Input Validation
if (NULL == input_string || left_index < 0 || right_index < 0){
return -1;
}
// Recursion termination condition
if (left_index >= right_index)
return 1;
if (input_string[left_index] == input_string[right_index]){
return isPalindrome(input_string, left_index + 1, right_index - 1);
}
return -1;
*/
__asm{
mov eax, 0
// BEGIN YOUR CODE HERE
push ebp
push edi
mov ebp, esp;
mov ebx, input_string
mov esi, [ebp+12]
mov edi, [ebp+16]
//push edi;
push esi;
push ebx;
// mov some_register, [esp + 8]
mov ebx, input_string
// mov esi, left_index // esi
// mov esi, [esp + 8]
mov edi, right_index // edi
cmp esi, 0;
jl FALSE;
cmp edi, 0
jl FALSE
cmp ebx, 0x00
je FALSE
cmp esi, edi
jge TRUE
mov cl, byte ptr[ebx + esi]
mov dl, byte ptr[ebx + edi]
cmp cl, dl
je RECURSIVE
jmp FALSE
RECURSIVE:
inc esi
dec edi
push eax
push ecx
push edx
push esi
push edi
call isPalindrome
//sub ebp, 8
pop edx
pop ecx
pop edx
jmp END
FALSE:
mov eax, -1
jmp END
TRUE:
mov eax, 1
jmp END
END:
pop ebx;
pop esi;
pop edi;
mov esp, ebp;
pop ebp;
// END YOUR CODE HERE
ret
}
}
答案 0 :(得分:1)
这里有一些问题。 首先,我必须说我不认为这个问题是递归解决方案的一个很好的选择,因为为它提供一个大字符串可能导致(我敢说)堆栈溢出,而递归只是无关紧要。
以尝试查看字符串的方式查看你的proc,我看到的第一个问题是你的序言/结语:
push ebp
push edi
mov ebp, esp
与:
不匹配pop edi
mov esp, ebp
pop ebp
您将以ebp =原始edi结束,然后尝试返回原始的ebp地址(崩溃)。显然,'pop edi'应该在'mov esp,ebp'之后,或者更有可能你想在'mov ebp,esp'后推'edi'
由于在这些中包含edi对我来说非常不标准,我认为你已添加它以试图支持你的复发,并建议这没有帮助。
对于proc,你可以从:
开始mov ebx, input_string
mov esi, [ebp+12]
mov edi, [ebp+16]
此时您的堆栈看起来像:
[esp+00] edi value
[esp+04] original ebp value
[esp+08] return address
[esp+12] *input_string
[esp+16] left_index
[esp+20] right_index
(显然你已经设置了ebp = esp)
假设您正在尝试将两个索引值转换为esi和edi,这些不是它们的位置,因为在ebp中存储esp之前添加了“push edi”。
之后不久你就有了:
mov ebx, input_string
mov edi, right_index
并且还有一个注释掉'mov esi,left_index'
如果您的编译器支持按名称跟踪过程参数,那么最好使用它们而不是[ebp + xx],这通常会遵循这些引用,但是您可能会手动编码如果是这种情况,则为前置/退出代码。你有没有在这里剪切和粘贴反汇编输出?如果是这样,那么你不应该包括:
; prelude
push ebp
mov ebp, esp
; exit
mov esp, ebp
pop ebp
; ( or possibly 'leave' which does the same thing )
ASM以'mov eax,0'开头,这似乎暗示您的默认返回值为0,但ASM似乎试图返回1表示true或-1表示false。在32位汇编中,-1 = 0xFFFFFFFF,在标准布尔测试中等于'TRUE'。
我认为这段代码应该返回'0'而不是'-1'表示false。也许'-1'被用作NULL指针等的错误代码。
所有这一切,我认为这就是你要找的东西:
push edi
push esi
push ebx
push edx
mov ebx, input_string
mov esi, left_index
mov edi, right_index
// - ERROR -
mov eax, -1
cmp ebx,0
jbe pEND
cmp esi,0
jb pEND
cmp edi,0
jb pEND
// - FALSE -
mov eax, 0
cmp esi, edi
jge pTRUE
mov dl, byte ptr[ebx + edi]
cmp dl, byte ptr[ebx + esi]
jne pEND
// RECURSIVE
inc esi
dec edi
push edi
push esi
push ebx
call isPalindrome
jmp pEND
pTRUE:
mov eax, 1
pEND:
pop edx
pop ebx
pop esi
pop edi
ret
并使用__stdcall而不是__declspec(裸)
声明它