アセンブリ-アドレッシングモード
ほとんどのアセンブリ言語命令では、オペランドを処理する必要があります。オペランドアドレスは、処理されるデータが格納される場所を提供します。一部の命令はオペランドを必要としませんが、他の一部の命令は1つ、2つ、または3つのオペランドを必要とする場合があります。
命令に2つのオペランドが必要な場合、通常、最初のオペランドはデスティネーションであり、レジスタまたはメモリ位置にデータが含まれ、2番目のオペランドはソースです。ソースには、配信されるデータ(即時アドレス指定)またはデータのアドレス(レジスタまたはメモリ内)のいずれかが含まれます。通常、ソースデータは操作後も変更されません。
アドレス指定の3つの基本モードは次のとおりです。
- レジスタアドレス
- 即時アドレス指定
- メモリアドレス指定
レジスタアドレス指定
このアドレッシングモードでは、レジスタにオペランドが含まれます。命令に応じて、レジスタは第1オペランド、第2オペランド、またはその両方になります。
例えば、
MOV DX, TAX_RATE ; Register in first operand
MOV COUNT, CX ; Register in second operand
MOV EAX, EBX ; Both the operands are in registers
レジスタ間のデータ処理にはメモリが含まれないため、データの処理が最速になります。
即時アドレス指定
即値オペランドには定数値または式があります。2つのオペランドを持つ命令が即時アドレス指定を使用する場合、最初のオペランドはレジスタまたはメモリ位置であり、2番目のオペランドは即時定数です。最初のオペランドは、データの長さを定義します。
例えば、
BYTE_VALUE DB 150 ; A byte value is defined
WORD_VALUE DW 300 ; A word value is defined
ADD BYTE_VALUE, 65 ; An immediate operand 65 is added
MOV AX, 45H ; Immediate constant 45H is transferred to AX
ダイレクトメモリアドレス指定
メモリアドレッシングモードでオペランドを指定する場合は、メインメモリ(通常はデータセグメント)に直接アクセスする必要があります。このアドレス指定方法では、データの処理が遅くなります。メモリ内のデータの正確な場所を見つけるには、セグメントの開始アドレスが必要です。これは通常、DSレジスタとオフセット値にあります。このオフセット値は、effective address。
直接アドレッシングモードでは、オフセット値は命令の一部として直接指定され、通常は変数名で示されます。アセンブラはオフセット値を計算し、プログラムで使用されるすべての変数のオフセット値を格納するシンボルテーブルを維持します。
直接メモリアドレス指定では、オペランドの1つはメモリ位置を参照し、他のオペランドはレジスタを参照します。
例えば、
ADD BYTE_VALUE, DL ; Adds the register in the memory location
MOV BX, WORD_VALUE ; Operand from the memory is added to register
直接オフセットアドレス指定
このアドレッシングモードでは、算術演算子を使用してアドレスを変更します。たとえば、データのテーブルを定義する次の定義を見てください。
BYTE_TABLE DB 14, 15, 22, 45 ; Tables of bytes
WORD_TABLE DW 134, 345, 564, 123 ; Tables of words
次の操作は、メモリ内のテーブルからレジスタにデータにアクセスします-
MOV CL, BYTE_TABLE[2] ; Gets the 3rd element of the BYTE_TABLE
MOV CL, BYTE_TABLE + 2 ; Gets the 3rd element of the BYTE_TABLE
MOV CX, WORD_TABLE[3] ; Gets the 4th element of the WORD_TABLE
MOV CX, WORD_TABLE + 3 ; Gets the 4th element of the WORD_TABLE
間接メモリアドレス指定
このアドレッシングモードは、コンピューターのセグメント:オフセットアドレッシングの機能を利用します。一般に、この目的には、メモリ参照用の角括弧内にコード化されたベースレジスタEBX、EBP(またはBX、BP)およびインデックスレジスタ(DI、SI)が使用されます。
間接アドレス指定は、通常、配列などのいくつかの要素を含む変数に使用されます。配列の開始アドレスは、たとえばEBXレジスタに格納されます。
次のコードスニペットは、変数のさまざまな要素にアクセスする方法を示しています。
MY_TABLE TIMES 10 DW 0 ; Allocates 10 words (2 bytes) each initialized to 0
MOV EBX, [MY_TABLE] ; Effective Address of MY_TABLE in EBX
MOV [EBX], 110 ; MY_TABLE[0] = 110
ADD EBX, 2 ; EBX = EBX +2
MOV [EBX], 123 ; MY_TABLE[1] = 123
MOV命令
あるストレージスペースから別のストレージスペースにデータを移動するために使用されるMOV命令はすでに使用しています。MOV命令は2つのオペランドを取ります。
構文
MOV命令の構文は次のとおりです。
MOV destination, source
MOV命令には、次の5つの形式のいずれかがあります。
MOV register, register
MOV register, immediate
MOV memory, immediate
MOV register, memory
MOV memory, register
注意してください-
- MOV演算の両方のオペランドは同じサイズである必要があります
- ソースオペランドの値は変更されません
MOV命令は、あいまいさを引き起こすことがあります。たとえば、ステートメントを見てください-
MOV EBX, [MY_TABLE] ; Effective Address of MY_TABLE in EBX
MOV [EBX], 110 ; MY_TABLE[0] = 110
数値110に相当するバイトまたはワードを移動するかどうかは明確ではありません。そのような場合は、を使用するのが賢明です。 type specifier。
次の表は、一般的な型指定子のいくつかを示しています-
タイプ指定子 | アドレス指定されたバイト |
---|---|
バイト | 1 |
語 | 2 |
DWORD | 4 |
QWORD | 8 |
TBYTE | 10 |
例
次のプログラムは、上記の概念のいくつかを示しています。メモリのデータセクションに名前「ZaraAli」を格納し、その値をプログラムで別の名前「Nuha Ali」に変更して、両方の名前を表示します。
section .text
global _start ;must be declared for linker (ld)
_start: ;tell linker entry point
;writing the name 'Zara Ali'
mov edx,9 ;message length
mov ecx, name ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov [name], dword 'Nuha' ; Changed the name to Nuha Ali
;writing the name 'Nuha Ali'
mov edx,8 ;message length
mov ecx,name ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
name db 'Zara Ali '
上記のコードをコンパイルして実行すると、次の結果が得られます。
Zara Ali Nuha Ali