在 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)

声明它