1

こちらでも同様の質問をしましたが、まだエラーが発生するので、何が間違っているのか教えていただければ幸いです。私はアセンブラーを知っており、8051 アセンブラーでいくつかのプロジェクトを行ってきましたが、同じでなくても、x86 asm に近いことを知っておいてください。

VC++ 2010 Express で試したコード ブロックがあります (CPUID 命令から情報を取得しようとしています)。

int main()
{
char a[17]; //containing array for the CPUID string
a[16] = '\0'; //null termination for the std::cout
void *b=&a[0]; 
int c=0; //predefined value which need to be loaded into eax before cpuid

_asm
{
    mov eax,c;
    cpuid;
    mov [b],eax;
    mov [b+4],ebx;
    mov [b+8],ecx;
    mov [b+12],edx;
}
std::cout<<a;
}`

簡単にまとめると、配列の最初の要素への void ポインターを作成しようとしましたが、間接アドレス指定を使用するよりも、レジスターから値を移動するだけです。しかし、このアプローチでは「b変数の周りのスタックが実行時エラーで壊れています」というメッセージが表示されますが、その理由はわかりません。

助けてください。ありがとう。そして、これは単なる学習目的です.CPUIDの関数があることは知っています....

編集: また、x86 VC++ 2010 インライン アセンブラーで直接アドレッシングを使用するにはどうすればよいですか? つまり、8051 での即時数値ロードの一般的な構文はmov src,#number、VC++ asm ではmov dest,number# 記号なしです。では、メモリ セル アドレス x に直接アクセスすることをコンパイラに伝えるにはどうすればよいでしょうか。

4

2 に答える 2

6

スタックが破損している理由は、 in の値を格納しているためeaxですbebx次に、メモリ位置にの値を格納するb+4などです。インライン アセンブラの構文は、バイト ポインタの場合[b+4]、C++ の式と同等です。&(b+4)b

これは、見bて一歩踏み出すとわかります。を実行するとすぐmov [b],eaxに の値がb変わります。

この問題を解決する 1 つの方法は、 の値をインデックス レジスタにロードbし、インデックス付きアドレス指定を使用することです。

mov edi,[b]
mov [edi],eax
mov [edi+4],ebx
mov [edi+8],ecx
mov [edi+12],edx

bへのポインターを保持する必要はまったくありませんalea(実効アドレスのロード) 命令を使用して、インデックス レジスタを直接ロードできます。

lea edi,a
mov [edi],eax
... etc ...

インライン アセンブラーをいじっている場合は、デバッガーで [レジスタ] ウィンドウを開いて、シングル ステップ実行時に状況がどのように変化するかを確認することをお勧めします。

メモリを直接アドレス指定することもできます:

mov dword ptr a,eax
mov dword ptr a+4,ebx
... etc ...

ただし、このような直接アドレス指定には、前の例のインデックス付きアドレス指定よりも多くのコード バイトが必要でした。

上記のlea(Load Effective Address) 命令と、示した直接アドレス指定により、最後の質問に答えることができると思います。

于 2010-11-06T17:18:48.420 に答える
0

デバッガーで [Registers] ウィンドウを開くというアドバイスは、VC++ 2010 Express では機能しません。

VC++ 2010 Express にレジスタ ウィンドウがないことを知って、私と同じくらい驚くかもしれません。これは特に驚くべきことです。

私が知っている唯一の回避策は、ウォッチ ウィンドウを開き、[名前] フィールドにレジスタ名を入力することです。必要に応じて、EAX EBX ECX EDX ESI EDI EIP ESP EBP EFL および CS DS ES SS FS GS を入力します。

ST1 ST2 ST3 ST4 ST5 ST6 ST7 はウォッチ ウィンドウでも機能します。

ウォッチ ウィンドウで右クリックし、[16 進数表示] をオンにして、[値] を [16 進数] に設定することもできます。

于 2011-07-20T08:59:31.773 に答える