阅读有关使用双数组的IA32汇编代码

时间:2011-09-25 23:21:01

标签: assembly x86

这是一个确切的问题:

  

以下代码转换M x M数组的元素,其中M   是#define:

定义的常量
void transpose(Marray_t A) {
    int i, j;
    for (i = 0; i < M; i++)
        for (j = 0; j < i; j++) {
           int t = A[i][j];
           A[i][j] = A[j][i];
           A[j][i] = t;
       } 
}
  

使用优化级别-02编译时,GCC会生成以下内容   函数内循环的代码:

1. .L3 
2. movl (%ebx),%eax 
3. movl (%esi,%ecx,4),%edx 
4. movl %eax, (%esi,%ecx,4) 
5. addl $1, %ecx 
6. movl %edx, (%ebx) 
7. addl $52,%ebx 
8. cmpl %edi,%ecx 
9. jl .L3
  

一个。 M的价值是多少?

     

B中。什么寄存器保存程序值i和   J&prime;

     

℃。编写一个使用的转置的C代码版本   在此循环中发生的优化。在你的使用中使用参数M.   代码而不是数字常量。

因此,在我试图理解这一点时,我注意到它乘以4,这意味着它存储了4个字节的类型(可能是int或指针)。然后,它增加$ 52(我假设我),因为它是一个更大的值,因此转到下一个数组)和$ 52/4是13.所以我猜M = 13.错了吗?

对于B,我猜想%ebx包含i而%ecx包含i。

对于C,我不完全确定,因为我不完全理解所呈现的循环。让我试着通过行号来理解并告诉我哪里错了。 1.显然是循环标签的开头。 2.大概将i的值移到%eax中。然后3.将A [i] [j]存储到t中。但是......我真的不明白。 :/ 救命??

1 个答案:

答案 0 :(得分:7)

我修复了汇编代码中的一些错误(%ecs - &gt; %ecx(ebx) -> (%ebx))我希望我不会无意中引入新的错误。

关于问题,你几乎在那里有了解。让我们逐行采用代码并尝试将其转换为C.

   L3:
2. movl (%ebx),%eax
   // We load a 32-bit value from the address stored in ebx. We can't yet deduce the type, but let's assume int for now
   int *ebx = ??;         
   int eax = *ebx; 
3. movl (%esi,%ecx,4),%edx
   // As you noted we're dealing with 32-bit values, so when converting to C we divide the index by 4
   int *esi = ??;
   int ecx = ??; 
   int edx = esi[ecx]; 
4. movl %eax, (%esi,%ecx,4)
   esi[ecx] = eax; 
5. addl $1, %ecx 
   ecx++;
6. movl %edx, (%ebx)
   *ebx = edx; 
7. addl $52,%ebx
   // Again we have to remember to divide by the size of the type used (4)
   ebx += 13; 
8. cmpl %edi,%ecx 
9. jl .L3
   int edi = ??; 
   if (ecx < edi) goto L3;

由此我们看到我们有一些在内循环之外初始化的未知值,但我们也可以对它们是什么做出很好的猜测。

  • ecx在每次循环迭代时递增,然后用于决定是否应该继续循环:它显然来自C代码j
  • edi是我们在决定是否循环时比较j的值,但在内循环中没有更改:它是i
  • esi使用ecxj)逐行编入索引,因此它对应&a[i][j]
  • ebx每次循环迭代增加52(13个索引位置) - 因为您可能已经猜到13是M - 它对应于&m[j][i]并且移动到指向j - 每次迭代时下一列的第一行元素。

现在我们可以回答这些问题:

  

一个。 M的价值是什么?

13

  

B中。什么寄存器保存程序值i和j?

分别为

ediecx

  

℃。编写transpose的C代码版本,利用此循环中发生的优化。在代码中使用参数M而不是数值常量。

此时应该是直截了当的。