アセンブリ 8086 に問題があります。2D 配列の使用方法がわかりません。このように使用
するとエラーが発生し、配列で使用したい場合にもエラーが返されますmov ar[cx][dx]
。SI
DI
3 に答える
アセンブリ言語で配列ルックアップセマンティクスを提供するCPUに非常に感銘を受けました。むしろ、もっと重要なものが犠牲にされたということを意味するのなら、私はイライラするでしょう。
アセンブリで配列ルックアップを実行する一般的な方法は、2D配列の2つのインデックスを1D配列の単一のインデックスに変換し、要素サイズを調整するために自分で計算を行うことです。例(擬似コード):
ax = cx * major_dimension
ax = ax + dx
ax = ax * element_size
ax = peek[base+ax]
ここでmajor_dimension
、は2D配列の次元の1つ(使用する次元はデータがメモリに配置される方法に完全に依存します)、element_size
は各要素のサイズ、base
は配列の開始、cx/dxはインデックスです。アレイへのアクセスに再使用します。
たとえば、a[0-2][0-3]
メモリ位置0x0700
に3行4列()の配列があり、これらが32ビット整数である場合:
+--------+--------+--------+--------+
0x0700: | a[0,0] | a[0,1] | a[0,2] | a[0,3] |
+--------+--------+--------+--------+
0x0710: | a[1,0] | a[1,1] | a[1,2] | a[1,3] |
+--------+--------+--------+--------+
0x0720: | a[2,0] | a[2,1] | a[2,2] | a[2,3] |
+--------+--------+--------+--------+
配列要素を見つけるa[n,m]
には、メジャーインデックスに4を掛けたものにマイナーインデックスを加えたものを計算し、それを正しい要素サイズ(4バイト)にスケーリングしてから、ベースを追加します。要素を見つけるにはa[2,1]
addr = base + (n * 4 + m) * 4
= 0x0700 + (2 * 4 + 1) * 4
= 0x0700 + (8 + 1) * 4
= 0x0700 + (9 ) * 4
= 0x0700 + 36
= 0x0700 + 0x24
= 0x0724
次に、それが1D配列の検索に使用するアドレスです。
そして、そのコメントに基づいて:
ar db 3dup(3dup(0))
mov ar[bx][si],al
うまくいくでしょう、それは完全には正しくありません(ar[bx][si]
masm固有の構文はと同等ですar[bx+si]
)。
ar
行うのは、アドレスbx
とレジスタを単純に追加することだけですsi
。メジャーディメンションを考慮してまたはレジスタをスケーリングせず、要素サイズの値をスケーリングしません。したがって、主要な次元が1であるバイトの2D配列に対しては、現状のままでのみ機能します。これにより、1D配列になると確信しています:-)bx
si
bx+si
いずれの場合でも機能するには、最初に主次元を乗算するbx
か、si
(主次元に使用されているものに応じて)主次元を乗算し、次にbx
要素si
サイズを乗算する必要があります。
私はあなたが尋ねている正確な質問については本当にはっきりしていませんが、あなたはこのようなもの(ベース/インデックス付きアドレッシングモードを使用)を求めていますか?
lea bx, array_base
mov si, array_index
mov ax, [bx][si]
これはあなたを助けることができます。
2D 配列は 1D 配列と同じようにメモリに格納されますが、行と列を持つものとして表されます。
以下は、メモリに線形に格納される 2D 配列を宣言するコードです。
このような:
+----------+----------+----------+----------+----------+----------+----------+
index | arr[0][0]| arr[0][1]| arr[0][2]| arr[0][3]| arr[0][4]| arr[1][0]| arr[1][1]|
+----------+----------+----------+----------+----------+----------+----------+
value | 0 | 1 | 2 | 3 | 4 | 10 | 11 |
+----------+----------+----------+----------+----------+----------+----------+
memory address | 1000 | 1004 | 1008 | 1012 | 1016 | 1020 | 1024 |
+----------+----------+----------+----------+----------+----------+----------+
ここでは、各行に 4 つのエントリと 5 つの列があります。
ここで、値 11 ,arr[1][1] 行 1 列 1 を見つけたい場合、メモリ アドレスは 1024 になります。このエントリを見つけるには、最初に行インデックスを計算してから列インデックスを計算する必要があります。
行インデックスの計算:
したがって、各行にはそれぞれ 4 バイトの 5 つのエントリがあるため、各行は 4*5=20 バイトになります。エントリ 11 は行インデックス 1 にあるため、1*20 = 20 となり、行 1 になります。
列インデックスの計算:
その後、エントリ 11 は列インデックス 1 にあるため、1*4= 4 となり、列インデックス 1 になります。4 バイトの DWORD として宣言したため、4 を掛けます。
最後に、結果 (行インデックス + 列インデックス) 20+4 = 24 を追加します。これを最初のエントリのメモリ アドレスに追加すると、エントリ 11 にジャンプします。
すなわち: 1000+24 = 1024
。データ
arr DWORD 0, 1, 2, 3, 4 ; これは、4 行、5 列の 2D 配列の宣言です。DWORD であるため、各エントリに 4 バイトが必要です。
DWORD 10,11,12,13,14 DWORD 20,21,22,23,24 DWORD 30,31,32,33,34
ROWSIZE EQU SIZEOF arr ; 各行が20バイトであることを意味する名前付き定数です。各行には 5 つの列があり、5 つのエントリを意味し、各エントリは 4 バイトなので、4*5 = 20 です。
。コード
mov ebx, 2*ROWSIZE ; 行インデックス = 2
動く esi, 3 ; 列インデックス = 3
mov eax, arr[ebx+esi*4] ; EAX = arr[2][3]、ここで arr[0] を呼び出すとエントリ 0 になるため、エントリ 11 は arr[24] になります。これは、配列の開始メモリ アドレスから 24 バイトをスキップすることを意味します。