web-dev-qa-db-ja.com

YASM / NASM x86アセンブリでのイミティブと大括弧の基本的な使用法

次のように宣言したとします。

section .bss
buffer    resb     1

そして、これらの指示はsection .textに続きます:

mov    al, 5                    ; mov-immediate
mov    [buffer], al             ; store
mov    bl, [buffer]             ; load
mov    cl, buffer               ; mov-immediate?

Blには値5が含まれ、clには変数bufferのメモリアドレスが含まれることを理解しても正しいですか?

私は両者の違いについて混乱しています

  • 即値をレジスターに移動する、
  • レジスタをイミディエイトに移動します(何が入っているか、データまたはアドレス?)
  • 括弧なしでイミディエイトをレジスターに移動する
    • たとえば、mov cl, buffer vs mov cl, [buffer]

更新:回答を読んだ後、私は次の要約が正確だと思います:

  • mov edi, arrayは、0番目の配列インデックスのメモリアドレスをediに入れます。つまり、ラベルのアドレス。
  • mov byte [edi], 3は、VALUE 3を配列の0番目のインデックスに入れます
  • add edi, 3の後、ediには配列の3番目のインデックスのメモリアドレスが含まれるようになりました
  • mov al, [array]は、0番目のインデックスのDATAをalにロードします。
  • mov al, [array+3]は、3番目のインデックスのDATAをalにロードします。
  • x86は2つの明示的なメモリオペランドをエンコードできない のため、およびalは8ビットのみであり、16ビットアドレッシングでも使用できないため、mov [al], [array]は無効です。モード。 メモリ位置の内容の参照。(x86アドレッシングモード)
  • mov array, 3は無効です。「ねえ、arrayが格納されているオフセットが好きではないので、3と呼びます」とは言えません。即値はソースオペランドにしかできません。
  • mov byte [array], 3は、値3を配列の0番目のインデックス(最初のバイト)に入れます。 byte指定子が必要です メモリ、即値オペランドを使用する命令のバイト/ワード/ dワード間のあいまいさを回避するため。それ以外の場合は、アセンブル時のエラー(あいまいなオペランドサイズ)になります。

これらのいずれかが誤りである場合は言及してください。 (編集者注:構文エラー/あいまいさを修正したため、有効なものは実際にare有効なNASM構文です。詳細については、他のQ&Aをリンクしました)

29

確かに、あなたの考えは正しいです。つまり、blには5が含まれ、clにはbufferのメモリアドレスが含まれます(実際にはラベルバッファ自体がメモリアドレスです)。


さて、あなたが言及した操作の違いを説明しましょう:

  • レジスタへのイミディエイトの移動は、mov reg,immを使用して行うことができます。混乱を招く可能性があるのは、バッファなどのラベルが、アドレスを含むイミディエート値そのものであることです。

  • 即値は2またはFF1Ahのような定数であるため、レジスタを即値に実際に移動することはできません。定数を指す場所にレジスタを移動することができます。mov [const], regのように実行できます。

  • mov reg2,[reg1]などの間接アドレス指定を使用して、reg1が有効な場所を指すようにすることもできます。これにより、reg1が指す値がreg2に転送されます。


したがって、mov cl, bufferは実際の値を取得しますが、mov cl, [buffer]はバッファのaddressをclに移動します(clは1バイトしかないため、正しいアドレスを提供する場合としない場合があります)。

概要

  • [a]を使用する場合、aが指す場所の値を参照します。たとえば、aがF5B1の場合、[a]は[〜のアドレスF5B1を参照します#〜] ram [〜#〜]
  • ラベルはアドレス、つまりF5B1のような値です。
  • レジスタにはアドレスがないため、レジスタに格納された値を[reg]として参照する必要はありません。実際、レジスタは即値と考えることができます。
15
byrondrossos

角括弧は基本的に逆参照演算子のように機能します(例:* in C)。

だから、のようなもの

mov REG, x

xの値をREGに移動しますが、

mov REG, [x]

xが指すメモリ位置の値をREGに移動します。 xがラベルの場合、その値はそのラベルのアドレスです。

あなたは質問です:

Blには値5が含まれ、clには変数バッファのメモリアドレスが含まれることを理解しても正しいですか?

はい。それで合っています。ただし、CLの幅は8ビットしかないため、bufferのアドレスの最下位バイトのみが含まれることに注意してください。

21
Job

あなたはアイデアを得ています。ただし、覚えておくべき詳細がいくつかあります。

  1. アドレスは、8ビットが保持できるものよりも大きい場合があります(clは8ビット、cxは16ビット、ecxは32ビット、rcxは64ビットです)。したがって、clは変数bufferのアドレスと等しくない可能性があります。アドレスの最下位8ビットのみが含まれます。
  2. 上記のコードをプリエンプトしたり、bufferにアクセスしたりできる割り込みルーチンまたはスレッドがある場合、blの値は5とは異なる場合があります。壊れた割り込みルーチンは、レジスタ値を保持します。
6
Alexey Frunze

Ramの場所に値を書き込むため(またはその中で計算するため)のオペランドとして即値を使用するすべての命令では、アクセスするバイト数を指定する必要があります。私たちのアセンブルは、1つのbyteWord、またはdopplewordの1つだけにアクセスする必要があるかどうかを知ることができないため(たとえば、即値がより低い場合)次の手順に示すように、値。

array db 0FFh, 0FFh, 0FFh, 0FFh
mov byte [array], 3

結果:

array db 03h, 0FFh, 0FFh, 0FFh

....

mov Word [array], 3

結果:

array db 03h, 00h, 0FFh, 0FFh

....

mov dword [array], 3

結果:

array db 03h, 00h, 00h, 00h

ダーク

3