在 Assbembly MASM 中检查回文
Checking for Palindrome in Assbembly MASM
此函数接受一个输入字符串并检查它是否为回文。但是由于内存错误,它中断了。我已经盯着它看了几个小时,但无法找出问题所在。有很多不必要的推动,但我害怕玩它并打破更多。非常感谢任何帮助。
__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
}
}
这里有一些问题。
首先,我必须说,我认为这个问题不是递归解决方案的理想候选者,因为为其提供大字符串可能会导致(我敢说)堆栈溢出,而递归只是不必要的。
以与尝试查看字符串相同的方式查看您的过程,我看到的第一个问题是您的 preamble/epilogue:
push ebp
push edi
mov ebp, esp
不匹配:
pop edi
mov esp, ebp
pop ebp
你最终会得到 ebp = 你原来的 edi,然后尝试 return 到原来的 ebp 地址(崩溃)。显然 'pop edi' 应该在 'mov esp, ebp' 之后,或者您更可能希望 'push edi' 在 'mov ebp, esp'
之后
我认为其中包含 edi 非常不标准,因此我假设您添加它是为了支持您的递归,并建议这没有帮助。
对于过程,您从:
开始
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 中,但它们不在原来的位置,因为您在将 esp 存储在 ebp 中之前添加了 'push edi'。
不久之后你有:
mov ebx, input_string
mov edi, right_index
还有一个被注释掉的'mov esi, left_index'
如果您的编译器支持按名称跟踪过程参数,那么您最好使用它们而不是 [ebp+xx],后者通常会遵守此类引用,但您似乎很奇怪如果是这种情况,请编写您的 prelude/exit 代码。您是否在此处剪切和粘贴了反汇编程序的输出?如果是这样,那么您不应该包括:
; prelude
push ebp
mov ebp, esp
; exit
mov esp, ebp
pop ebp
; ( or possibly 'leave' which does the same thing )
ASM 以 'mov eax, 0' 开头,这似乎表明您的默认 return 值为 0,但是 ASM 似乎试图将 return 1 表示为 true 或 -1为假。在 32 位汇编中 -1 = 0xFFFFFFFF 在标准布尔测试中等同于 'TRUE'.
我认为此代码应该 returning '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(naked)
声明它
此函数接受一个输入字符串并检查它是否为回文。但是由于内存错误,它中断了。我已经盯着它看了几个小时,但无法找出问题所在。有很多不必要的推动,但我害怕玩它并打破更多。非常感谢任何帮助。
__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
}
}
这里有一些问题。 首先,我必须说,我认为这个问题不是递归解决方案的理想候选者,因为为其提供大字符串可能会导致(我敢说)堆栈溢出,而递归只是不必要的。
以与尝试查看字符串相同的方式查看您的过程,我看到的第一个问题是您的 preamble/epilogue:
push ebp
push edi
mov ebp, esp
不匹配:
pop edi
mov esp, ebp
pop ebp
你最终会得到 ebp = 你原来的 edi,然后尝试 return 到原来的 ebp 地址(崩溃)。显然 'pop edi' 应该在 'mov esp, ebp' 之后,或者您更可能希望 'push edi' 在 'mov ebp, esp'
之后我认为其中包含 edi 非常不标准,因此我假设您添加它是为了支持您的递归,并建议这没有帮助。
对于过程,您从:
开始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 中,但它们不在原来的位置,因为您在将 esp 存储在 ebp 中之前添加了 'push edi'。
不久之后你有:
mov ebx, input_string
mov edi, right_index
还有一个被注释掉的'mov esi, left_index'
如果您的编译器支持按名称跟踪过程参数,那么您最好使用它们而不是 [ebp+xx],后者通常会遵守此类引用,但您似乎很奇怪如果是这种情况,请编写您的 prelude/exit 代码。您是否在此处剪切和粘贴了反汇编程序的输出?如果是这样,那么您不应该包括:
; prelude
push ebp
mov ebp, esp
; exit
mov esp, ebp
pop ebp
; ( or possibly 'leave' which does the same thing )
ASM 以 'mov eax, 0' 开头,这似乎表明您的默认 return 值为 0,但是 ASM 似乎试图将 return 1 表示为 true 或 -1为假。在 32 位汇编中 -1 = 0xFFFFFFFF 在标准布尔测试中等同于 'TRUE'.
我认为此代码应该 returning '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(naked)
声明它