何が起こっているのかを説明するには、コードを 1 行ずつ見ていくのが最も簡単です。
1. movl 8(%ebp), %ecx
これにより、ebp+8 のパラメータで ecx がロードされますi。
2. movl 12(%ebp), %eax
これは eax に ebp+12 のパラメータをロードしますj。
3. leal (%eax, %eax, 8), %eax
これは eax を eax+eax*8 に設定し、基本的にそれ自体を 9 倍しますj*9。
4. movl %ecx, %edx
これにより、edx が ecx に設定されますi。
5. sall $6, %edx
そして、これは左に 6 ビットシフトし、64 を掛けるので、edx はi*64.
6. sub1 %ecx, %edx
しかし今i、その値から ecx (つまり ) を引くと、edx は になりi*63ます。
7. addl %edx, %eax
これにより、edx( i*63) が eax() に追加さj*9れるため、eax は になりi*63 + j*9ました。
8. addl 16(%ebp), %eax
そして、これは ebp+16 にパラメータを追加するkので、eax は になりi*63 + j*9 + kました。
9. movl A(,%eax,4), %edx
Aこれは、オフセット eax*4 で配列にアクセスし、edx に格納しています。
eax はi*63 + j*9 + kであるため、これは、オフセットで単一の次元の int 配列にアクセスするものと考えることができますi*63 + j*9 + k。int のサイズなので、4 を掛けます。
そのインデックス式を のように書き換えることができることに注意してくださいi*7*9 + j*9 + k。このことから、配列のさまざまな次元がどのようにアクセスされているかがわかると思います。
10. movl 20(%ebp), %eax
これは、ebp+20 のパラメータで eax をロードしますdest。
11. movl %edx, (%eax)
これにより、配列から取得したばかりの edx が eax ( dest) のアドレスに格納されます。単一次元の int 配列の*dest = A[i*7*9 + j*9 + k]場合は効果的です。A
12. movl $2772, %eax
これは、 のサイズである値 2772 を返しているだけですA。
のサイズがわかったので、配列を逆参照するときにをどのように乗算したAかを振り返ってみると、との値が簡単にわかると思います。ijkRST
更新: 寸法の計算
配列の次元がR、Sおよびの場合、 、、Tの要素にアクセスするには、どの式を使用しますか?ijk
配列を次元を持つ大きな 3 次元ブロックと考えてくださいR x S x T。インデックスはi、次元を持つブロックから 2 次元のスライスを選択しますS x T。jインデックスは長さのスライスから行を選択しますT。そして、kインデックスはkその行の th 項目です。
したがって、1 次元アドレスは次のように表すことができますi*S*T + j*T + k。上記の逆アセンブルでの配列計算を振り返ってみると、同じパターンに気付きませんか? S逆アセンブリでどの値がおよびにマップされているかがわかりますTか?
検索に関してRは、配列内の項目の数が 693 (2772 バイトのサイズを int サイズの 4 で割った値) であることがわかっています。また、アイテムの数を で計算できることも知っていますR*S*T(3 次元ブロックをもう一度考えてみてください)。したがってR*S*T = 693、 そして と を知っているSのでT、見つけることRは単なる除算の問題です。