我正在嘗試改進我的彙編編程,並且我遇到了這個用於導出此函數中參數值的練習,但我不確定我應該如何使用給定的彙編代碼來執行它。
這是我很困惑的彙編代碼(嘗試註釋一些行):
arrayfunc:
leaq 15992(%rdx),%rax // get 1999th element frm Array2
leaq -8(%rdx),%r10 //start of Array2
movq %rcx,%r9 // store address of Array1 in rcx into r9
.L2:
leaq -400(%rdx), %r8 //Array2 - 50longs? but why minus 50longs
movq %r9,%rdx //move address in Array1[i][j] into rdx
.L3: //inner loop
movslq (%rdx),%rcx //move value in Array1[i][j] into rcx
subq $8,%rax // increment j so becomes Array2[M-1-i][N-1-2j]
addq $4,%rdx //increment address to Array1[i][2j]
movq %rcx,8(%rax)// what does this line do
cmpq %r8,%rax //compare j<N
jne .L3
addq $200,%r9 //Not sure what this line does with the 200
cmpq %r10,%rax
jne .L2
ret
這是給出的 C 代碼:
void arrayfunc(int Array1[M][N], long Array2[M][N])
{
long i,j;
for(i=0;i<M;++i)
for(j=0;j<N;++j)
{
Array2[M-1-i][N-1-j] = Array1[i][j];
}
}
有人可以教我如何正確解釋 asm 以便我可以準確地推導出 M 和 N 的值嗎?我在解釋這些行時遇到了困難(不確定我的評論是否正確,但有些行我真的不確定發生了什麼)
請幫助我更好地理解這個 asm(註釋代碼會很有幫助),因為我真的不知道如何找到 M 和 N 值。
任何和所有的幫助表示讚賞。
由於這些代碼中存在一些錯誤,這一點變得更加困難。第三個 leaq
只有一個操作數,因此缺少目標寄存器。 M
and N
是常量,否則索引會有顯式乘法(沒有),但是 C 代碼說 ++M
,這在常量上是不允許的(這應該是 ++i )。
因為M
&N
是常量,所以元素 atArray2[M-1][N-1]
是一個常量偏移量Array2
(指數組的最後一個元素)。由於這是在循環中使用的,代碼在所謂的循環不變代碼運動中計算該地址——一種優化技術,將一些固定/常數計算重新定位到循環之外,預先完成,而不是在每次迭代時重複相同的事情循環。
從Array2[M-1]
零件中,我們得出(M-1)*N
最後一行的偏移量。從[N-1]
部分,我們添加到N-1
,然後將整個事物乘以 8,因為 8 字節每長Array2
。
索引的那個常量部分的完整偏移量然後通過公式計算((M-1)*N+N-1)*8
,並且,簡化(M*N-1)*8
和M*N*8-8
。因此,15992 = M*N*8-8
與16000 = M*N*8
和2000 = M*N
。
外循環200
每次迭代按字節向前推進,這對應於 遞增i
,用於 的第一個索引位置Array1
。由於映射到字節+1
的第一個索引,一行的大小(以元素而不是字節為單位)是or ,因此。Array1
200
Array1
200/4
50
N=50
由於N=50
我們可以推理,2000=M*50
因此,2000/50=40=M
。
基本上,一種方法是搜索代碼以找出它是如何計算的Array2[M-1-i][N-1-j]
。這是關鍵 b/c 它是彙編代碼中使用M
.
(Array1[i][j]
可能涉及N
,但不是M
——但這裡已經優化,作者/編譯器識別訪問模式是順序的,所以i*N+j
不需要,只需要一個增量為 4 的運行值)。
這不是微不足道的,因為已經應用了優化技術;這些將計算分散到代碼的不同部分,而不是像人們期望的那樣一起出現在一個地方。變量也被消除(或大量修改),用索引和循環控制變量代替指針。
這一行:movq %rcx,8(%rax)// what does this line do
將賦值寫入 的內存Array2
,基本上是 中的=
運算符Array2[][]=...
。一旦意識到這一點,我們就可以向後推理以找到整個索引計算,其中部分展開並組合了各種常量。
(另一種方法是弄清楚如何完成i<M
以及如何j<N
完成,儘管由於這些循環控制變量已更改為有利於指針,因此分析並非易事,並且包括上述一些分析。)
循環在 C 和彙編中都有一次讀取和一次寫入。因此,內存寫入必須是對 的元素的賦值Array2
,而內存讀取movslq (%rdx),%rcx
必須是從 中獲取元素Array1
。
請注意,進一步的優化可能會發生很大的變化,例如,循環展開和向量寄存器的使用。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句