检查Assbembly MASM中的回文结构

时间:2017-03-16 23:18:48

标签: assembly 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
}

}

1 个答案:

答案 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(裸)

声明它