【问题标题】:Reading IA32 Assembly Code pertaining to using double arrays阅读与使用双数组有关的 IA32 汇编代码
【发布时间】:2011-09-25 23:21:01
【问题描述】:

这是确切的问题:

以下代码转置 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

A. M的值是多少?

B.哪些寄存器保存程序值 i 和 j?

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

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

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

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

【问题讨论】:

    标签: assembly x86


    【解决方案1】:

    我修正了汇编代码中的一些错误(%ecs -> %ecx(ebx) -&gt; (%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 使用ecx (j) 按行索引,因此它对应于&amp;a[i][j]
    • ebx 每次循环迭代都会增加 52(13 个索引位置) - 正如您可能已经猜到的那样,13 是 M - 它对应于 &amp;m[j][i] 并被移动到指向 j 的每一行的下一列元素迭代。

    现在我们可以回答问题了:

    A. M的值是多少?

    13

    B.哪些寄存器保存程序值 i 和 j?

    分别是ediecx

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

    此时应该是直截了当的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-07
      • 2012-06-01
      • 1970-01-01
      相关资源
      最近更新 更多