1

アセンブリでポインターを使用する方法を理解しようとしています。内部に関するいくつかのチュートリアルを読んで、いくつかの概念を理解したと思います。しかし、試してみると、うまくいきました。以下は、C を ASM に変換する試みです。

const char *s = "foo";
unsigned z = *(unsigned*)s;
if(!(z & 0xFF))
do_something();
if(!(z & 0xFFFF))
 do_b_something();

(これは完全なコードではありませんが、単語チェックであるため、0xFF0000、0xF000000 をそれぞれチェックする 2 つの stmts があります。

ASM:

mov ebp,str
mov eax,ebp

mov eax,[eax]
and eax,0xFF
cmp eax,0
je etc

mov eax,[eax]
and eax,0xFFFF
cmp eax,0
je etc

セグフォルトを返します。

そして試してみてください:

mov eax,dword ptr [eax]

これは gcc コンパイラによって生成され、他のアセンブリ コードで確認できます。

invalid symbol

FASM アセンブラー上。FASM で実際にサポートされていないか、何か不足していますか?

4

3 に答える 3

1

元のコードで何をしようとしているのかはまったく明確ではありません - 正しく見えません。

ただし、これ:

mov eax,[eax]
and eax,0xFF
cmp eax,0
je etc

mov eax,[eax]

うまくいきません。EAX のアドレスに格納されている値で EAX の内容を上書きし、その値を操作してから、分岐後に元のポインターを復元せずに再読み込みしようとしています。

于 2013-02-08T14:09:37.463 に答える
1

これがあなたがやろうとしていることだと思います:

    mov  ebp,str
    mov  eax,ebp

    mov  ebx,[eax]
    test ebx,0xFF
    jz   low_byte_empty

    do_something:
         ; some code here...

low_byte_empty:
    test ebx,0xFFFF
    jz   low_word_empty

    do_b_something:
         ; some code here.

low_word_empty:

説明:

最初に、JasonD が彼の回答で既に言及しているように、ポインタを にロードしeax、次に論理andを実行し、その結果をeaxメモリにアドレス指定するために使用しています (範囲内のメモリ オフセット0x0... 0xFF)。

では、コードの何が問題なのか: メモリ アドレスへのポインターと値の両方を同時に同じレジスターに保持することはできません。[eax]したがって、 からまでの値をロードすることにしました。必要に応じて、ebx他の 32 ビット汎用レジスタ ( ecxedx、) を使用することもできます。esiedi

次に、cmpレジスタが空かどうかを確認するために使用する必要はありませんcmp。これは、減算を実行してフラグを設定するだけであるためです。しかし、ZF(ゼロフラグ)はすでに設定されてandいるので、cmpここでは絶対に必要ありません。次に、ここでcmpは必要なく、結果も必要ないため、フラグを更新するだけで、 を使用することをお勧めしますtesttestとまったく同じ論理 AND をand実行します。唯一の違いはtest、結果を保存せず、フラグを更新するだけです。

于 2013-02-08T15:50:24.693 に答える
0

次のバリアントは、よりシンプルで、小さく、高速で、レジスタを 1 つしか使用しません。

    mov  eax, str
    mov  eax,[eax]

    test al, al
    jz   low_byte_empty

do_something_byte:
     ; some code here...

low_byte_empty:
     test ah, ah
     jz   low_word_empty         

do_something_word:
     ; some code here

low_word_empty:
于 2013-02-09T08:12:09.047 に答える