我正在嘗試改進我的匯編編程,并且我遇到了這個用于匯出此函式中引數值的練習,但我不確定我應該如何使用給定的匯編代碼來執行它。
這是我很困惑的匯編代碼(嘗試注釋一些行):
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 值。
任何和所有的幫助表示贊賞。
uj5u.com熱心網友回復:
由于這些代碼中存在一些錯誤,這一點變得更加困難。第三個leaq只有一個運算元,因此缺少目標暫存器。 M并且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 ,因此。Array1200Array1200/450N=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。
請注意,進一步的優化可能會發生很大的變化,例如,回圈展開和向量暫存器的使用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/313730.html
下一篇:如何使代碼輸出兩條資訊
