-1

私のプログラムはC++で書かれており、x86アセンブリ言語が埋め込まれています。アセンブリ言語でネストされたforループが2つあり、これを実行する必要があります。ただし、プログラムをコンパイルすると、無限ループが発生します。C ++の同等のプログラムは、次のようになります。

#include<iostream>
using namespace std;
int main()
{
    int a[4] = {3,6,4,7};

    for(int k = 0 ; k < 4;k++)
    {
        for(int l = 0 ; l < a[k];l++)
        {
            cout<<'*';
        }
        cout<<endl;
    }

    system("pause");
    return 0;
}

 /*

  *** 
  ******
  ****
  *******
  Press any key to continue . . .
  */

これは同じことですが、アセンブリを混ぜて実行します。

#include<iostream>
using namespace std;
void output(); //function for making an '*'
void makeSpace(); //function for making a space

int main()
{
    int a[4]={3,6,4,7};

    int counter = 0; //counter that will be used for first forloop
    int counter2 = 0; // counter to be used for second forloop

_asm{

    mov ebx,0 // this is to move from element 0,1,2,3,4, through the array
    mov ecx,0 // ecx will get the data from the array, only to be used as a
              // counter in forloop2 though.

     for1:

    cmp counter,4 //begins for firloop

    je starts 
    mov ecx,[a+ebx] // move the 0th element from array to ecx
    add ebx,4// ebx = ebx+4, I'm doing this to advance the array position (int)
    inc counter// increment counter by one

      for2:
    cmp counter2,ecx //begin forloop2, 
    je starts2
    call output
    inc counter2 //increment counter2 by one

    jmp for2 
      starts2:

    call makeSpace
    jmp for1
      starts:
}

    return 0;
}

void output()
{
    cout<<'*';
    }

void makeSpace()
{
    cout<<endl;
}

なぜこれが無限ループになるのですか?

4

2 に答える 2

2

修正する必要があるものが少なくとも2つあります。

  • output()次のレジスタのみを呼び出すと、ゴミ箱に捨てられないことが保証されます。

    • edi、、、、およびesi_ebxebp

    特に、ecx関数がゴミ箱に移動することを許可されているを使用しています。

  • 0にリセットcounter2することはないため、内部ループはCコードと同等ではありません。

于 2012-09-21T17:51:34.243 に答える
0

ここでの答えは、関数Outputとを呼び出す前にレジスタを保持することは決してないということだと思いますMakeSpace。標準の関数ヘッダーは、コードで使用されるレジスタecxまたはレジスタについて何も保証しません。ebxasm

于 2012-09-21T17:52:53.310 に答える