2

消化できないものがあります。私はいくつかのアセンブラを学んでいますが、今はアドレス指定の章にいます。逆参照のための括弧の概念は理解していますが、どういうわけかその使用法を見ると、その要点を理解できません。ここでもう少し正確に言うと、私の混乱が始まった場所です。

mov al, [L1]

ここで例として、L1 は何らかのマクロであり、後でマシンコードの実アドレスに置き換えられると思いますよね?

したがって、この命令が行うことは、レジスタを逆参照しal(物理アドレスをほとんど変更できないため)、値を に格納されている値に変更することL1です。

今まではすべて問題ない場合:

mov [L1], al

類推すると、アドレスが保存されている必要があり (したがって、これを行うにはいくつかのポイントがありました)、メモリ内の別の場所に変更しますよね?

間違いがなければ大丈夫だと言っていただければ、そうしてください。そうすれば、私は学習を続けることができます。

最後にもう 1 つ、NASM は0xAA55私のコードの下にたくさんのコードを追加します (このシーケンスはプログラムを正しく終了するはずです?)。

4

3 に答える 3

4

L1通常/おそらくラベルであり、メモリ内の特定のアドレスに関連付けられています。プログラマーは便宜上さまざまなラベルを定義し、そのようなラベルはメモリ内の特定の場所を象徴的に表すために使用されます (L1 はお粗末な名前です。ラベルは通常、場所の根底にある目的を示しています。たとえば、PingCounter、ErrorMessage、Login など)。など)。

1 バイトの静的ストレージのラベルは、C コンパイラがchar L1;グローバル スコープで実装する方法です。


NASM 構文では、 の形式にmov edi, L1アセンブルされます。つまり、ラベル アドレスは、マシン コードでは 32 ビットの即値になります。(アセンブラは最終的な数値を認識しませんが、リンカは認識します。) MASM 構文では、これはロードであり、ラベル アドレスを即値として取得する必要があることに注意してください。mov eax, imm32movmov edi, OFFSET L1

ただしmov al, [L1]、逆参照されるアドレスとしてマシン コードに埋め込まれた 32 ビット アドレスを使用して、別の命令にアセンブルします。この命令は、アドレス L1 から 1 バイトをロードし、それを AL に配置します。

アセンブリ言語では、この間接アドレッシング モードは、特定の命令のソースまたはデスティネーション オペランドを角かっこで囲むことによって示されます。(ただし、両方ではありません。x86 は、命令ごとに最大 1 つの明示的メモリ オペランドのみをサポートします。)

mov al, [L1]

L1 に格納されているアドレスを使用して、メモリ内のある場所を特定し、この場所で 1 バイト (= 8 ビット = AL レジスタのサイズ) を読み取り、それを AL レジスタにロードします。

  mov [L1], al

これを逆にします。つまり、具体的には、L1 に格納されているアドレスを読み取り、このアドレスを使用してメモリ内の特定の場所を見つけ、そこに AL レジスタの内容を格納します。


以下の情報が不完全であり、x86 ファミリの新しいプロセッサに関してやや古くなっていることを理解していれば、8086 アーキテクチャに関するこの入門書は、x86 ファミリのアセンブリ言語を始めるのに非常に役立つでしょう。
この「古代の CPU」(実際にはまだ使用されています) から始める利点は、基本的な概念がすべてそこにあり、新しいレジスタ セット、派手なアドレス指定モード、動作モード、およびその他の概念の邪魔にならないことです。新しい CPU のより大きなサイズ、機能、およびモードは、オプションの組み合わせの爆発を導入するだけであり、それらのすべて (ほとんど?) は便利ですが、基本的に開始には関係ありません。

于 2010-03-02T15:29:26.537 に答える
3

あなたの質問に従うのは難しいですが、私は助けようとします。

アセンブリでは、シンボルはアドレスの単なる名前です。アセンブリ ソースでは、L1 は別の場所で定義されたシンボルであり、アセンブラはメモリへのオフセットとして解決します。

逆参照 ([] 表記を使用) する場合、レジスタ ("mov al, [esi]" のように) またはアドレス ("mov al, [L1]" のように) を逆参照できます。どちらのステートメントも同じことを行います。唯一の違いは、アドレスがどこから来るかです。

Intel CPU のドキュメントをダウンロードし、命令リファレンスをざっと読むことをお勧めします。圧倒されたくない場合は、古い x86 プロセッサ (たとえば、486 またはそれ以前) から読み始めてください。そのドキュメントは必ずしもわかりやすいものではありませんが、手元にあると非常に便利です。

NASM の詳細はわかりません。15 年前に Turbo Assembler でアセンブリを学びましたが、その知識は今日でも役に立ちます :)

また、「x86 アセンブリ チュートリアル」を検索してみることをお勧めします。役立つ関連ドキュメントがたくさん見つかります。

于 2010-03-02T15:38:32.987 に答える
1

最後に、NASM は私のコードの下に 0xAA55 の束を追加します (このシーケンスはプログラムを正しく終了するはずです?)、なぜ何度もあるのですか? ここまで読んでくれてありがとう..

ブートローダーを作成する場合にのみ適用されると確信しています。それが「ブート署名」です。このコードをフロッピーに書き込むとします (生成されたマシン コードも正確に 512 バイトですか?)。このブートローダ コードでコンピュータを起動したい場合、BIOS はフロッピーを見て、それが実際のブートローダかどうかを判断します。そのために、フロッピーの最初のセクターの最後の 2 バイトを調べます。これは、フロッピー0xAA55が起動可能であることを示す必要があります.. -ドライブなど。CD では 4096 バイトのセクターがあるため、CD の場合は少し異なります)

あなたのソース コードでは、最後の行のような$(times.. db 0xAA55ものですか、それともそのようなものですか? ブートローダーを作成するつもりがない場合は、その行を効果的に削除できます。

于 2010-03-02T17:36:49.377 に答える