從彙編代碼和骨架 C 派生數組的大小

梅根達西

我正在嘗試改進我的彙編編程,並且我遇到了這個用於導出此函數中參數值的練習,但我不確定我應該如何使用給定的彙編代碼來執行它。

這是我很困惑的彙編代碼(嘗試註釋一些行):

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)*8M*N*8-8因此,15992 = M*N*8-816000 = M*N*82000 = 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

請注意,進一步的優化可能會發生很大的變化,例如,循環展開和向量寄存器的使用。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何從給定的數組和函數為給定的算法編寫 matlab 代碼?

彙編 --> 操作碼和操作數的無效組合

從數組 Typescript 派生類型

從 C 調用彙編函數時出現分段錯誤錯誤

在 C++ 代碼的 VS 反彙編中,“dword ptr[this]”是什麼意思?

C++ 數組大小的編譯時間規範

我如何用 C++ 編寫這個偽代碼?函數返回兩個數組到兩個初始化數組

使用 C# 代碼從 MongoDB 數組中獲取不同的值,它專門匹配某些值

從 C# 代碼讀取 Azure Function App 的函數超時

從 N 和 M 大小的 2 個數組/列表創建 NxM 數組

我想通過 RMI 從數據庫中獲取完整的數據。我使用了數組方法。我無法成功編寫代碼

在 C++ 中查找字符數組的大小

如何使用一行代碼在 C# 中連接兩個數組

C++ 2D 算法代碼讀取數組錯誤

C 帶有打印和數組的反向數字

使用 fork() 和 exec() 從 C++ 執行 Python 代碼

C中的整數數組大小而不使用動態內存分配

為什麼當我用 stl 向量替換數組時,我的代碼會變慢,在 C++ 中,數組是否比向量更快?

從C中的數組中刪除元素

在 C++ 中從數組打印值

我想在 Angular 和 C# 中生成從“A”到“ZZ”的數組。怎麼可能?

為 K 排序數組問題編譯此代碼時出錯

在C中將奇數索引元素從一個數組複製到另一個數組

彙編程序如何訪問數組元素?

C語言如何比較char數組和char

如何從 IL 指令生成 C# 代碼

c++ 從函數中返回兩個數組

將多個整數從行輸入到二維數組 c++

NEON 彙編代碼在 Cortex-A72 和 Cortex-A53 上需要更多的周期