2017-03-16 11 views
-2

この関数は入力ストリングを取り、それがパリンドロームかどうかをチェックします。しかし、メモリエラーのために破損します。私は数時間それを見てきましたが、問題を把握することはできません。多くの不必要なプッシュがありますが、私はそれで遊んで壊れて、さらに壊れてしまいます。助けていただければ幸いです。アセンブリーでのパリンドロームのチェック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 
} 

}

+0

(裸)の代わりに__declspecの__stdcall使用してそれを宣言:

はすべてのことが言われて、私は、これはあなたが探しているものだと思いますabba "、第2コール深度のレジスタにどのような値が表示されますか?私がコードを正しく読んでいれば、すでに2番目の深度マッシュにはほとんどすべての引数値が間違っています(返された後、おそらく上位レベルに戻ることはできません)。デバッガ命令で命令を実行したり、机の上にペーパー+ペンを置いたり、レジスタの値に関するメモを書き留めたり、データの期待や定義と比較したりする必要はありません。 – Ped7g

+0

はい、問題は、関数が古い引数で呼び出され、左と右のインデックスが再帰呼び出しで更新されないということです。 –

+0

これは単に真実ではありません。最初に関数を入力すると、 'left_index'はアドレス 'esp + 8'にあり、これは0x0150になります。 2回目の再帰レベルでは 'left_index'も' esp + 8'に戻りますが、評価しても '0x0150'を指していないので、古い引数はありません。あなたは間違った議論をするかもしれませんが、 "古い"はまだメモリの '0x0150'に座っています。だから、 'esp'値に注意を払い始め、スタックの内容を見るためのメモリウィンドウを開きます。 (ちょっとスタックに特化したビューを持っているので、多くのデバッガでは最新のものになっています) – Ped7g

答えて

0

ここではいくつかの問題があります。 第1に、私はこの問題が再帰的な解決策の良い候補ではないと言わなければなりません。大きな文字列を与えるとスタックオーバーフローが発生し、再帰は単調ではありません。

あなたのprocの文字列を見しようとしているのと同じ方法を見てみると、私が見る最初の問題は、あなたのプリアンブル/エピローグである:

pop edi 
mov esp, ebp 
pop ebp 

push ebp 
push edi 
mov ebp, esp 

は一致しません

あなたはebp =あなたの元のediで終わるでしょう、そして元のebpアドレス(クラッシュ)に戻ろうとしてください。明らかに、「ポップエディ」は「mov esp、ebp」の後にあるべきですか、「mov ebp、esp」の後に「push edi」が必要なのでしょうか?

これらの中にediを含めると、非標準的な、私はあなたのrecurrsionをサポートするためにそれを追加したと仮定し、これは有用ではないことをお勧めします。 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に2つのインデックス値を取得しようとしていますが、espをebpに格納する前に '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は、デフォルトの戻り値が0であることを示唆しているように思われる「のMOV EAX、0」で始まる、しかし、ASMは、のために1を返すようにしようとしているように見えますtrueの場合はfalse、falseの場合は-1 32ビットアセンブリでは、-1 = 0xFFFFFFFFで、標準ブールテストでは「TRUE」になります。

このコードは、falseの場合は '-1'ではなく '0'を返しているはずです。おそらく '-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 

、あなたはそれを文字列を与えればそう

関連する問題