Assembly 读取与使用双数组相关的IA32汇编代码
这正是问题所在: 下面的代码转置一个M x M数组的元素,其中M 是由#define定义的常数: A.M的值是多少 B.哪些寄存器保存程序值i和 j 编写一个C代码版本的转置,利用 在此循环中发生的优化。在您的应用程序中使用参数M 代码而不是数字常量 因此,在我试图理解这一点时,我注意到它乘以4,这意味着它存储了4个字节的类型(可能是一个int或一个指针)。然后,它将i增加$52(我假设i),因为它是一个更大的值,因此将进入下一个数组),并且$52/4是13。所以我猜M=13。错了吗 对于B,我猜%ebx包含I,%ecx包含IAssembly 读取与使用双数组相关的IA32汇编代码,assembly,x86,Assembly,X86,这正是问题所在: 下面的代码转置一个M x M数组的元素,其中M 是由#define定义的常数: A.M的值是多少 B.哪些寄存器保存程序值i和 j 编写一个C代码版本的转置,利用 在此循环中发生的优化。在您的应用程序中使用参数M 代码而不是数字常量 因此,在我试图理解这一点时,我注意到它乘以4,这意味着它存储了4个字节的类型(可能是一个int或一个指针)。然后,它将i增加$52(我假设i),因为它是一个更大的值,因此将进入下一个数组),并且$52/4是13。所以我猜M=13。错了吗 对于B,我
对于C,我不太确定,因为我不完全理解所呈现的循环。让我试着用行号来理解,告诉我哪里错了。1.显然是循环标签的开始。2.将i的值移动到%eax中。然后是3。将[i][j]存储到t中。但是我真的不明白帮助 我修复了汇编代码中的一些错误(
%ecs
->%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;
L3:
2.移动百分比(%ebx),%eax
//我们从ebx中存储的地址加载一个32位的值。我们还不能推断类型,但现在让我们假设int
int*ebx=??;
int eax=*ebx;
3.movl(%esi,%ecx,4),%edx
//正如您所指出的,我们处理的是32位值,因此当转换为C时,我们将索引除以4
int*esi=??;
int-ecx=??;
int-edx=esi[ecx];
4.movl%eax,(%esi,%ecx,4)
esi[ecx]=eax;
5.加成$1,%ecx
ecx++;
6.移动%edx,(%ebx)
*ebx=edx;
7.加成52美元,ebx
//同样,我们必须记住除以所用类型的大小(4)
ebx+=13;
8.cmpl%edi,%ecx
9jl.L3
int edi=??;
如果(ecx
由此我们可以看出,我们有一些在内部循环外部初始化的未知值,但我们也可以很好地猜测它们是什么
在每次循环迭代中递增,然后用于决定是否继续循环:显然,它是C代码中的ecx
j
是我们在决定是否循环时比较edi
的值,但它在内部循环中没有改变:它是j
i
通过esi
(ecx
)按行索引,因此它对应于j
李>&a[i][j]
在每次循环迭代中增加52(13个索引位置)-正如您可能猜到的13是M-它对应于ebx
,并移动到每次迭代下一列的第&M[j][i]
-行元素j
edi
和ecx
C.编写一个转置的C代码版本,利用此循环中发生的优化。在代码中使用参数M,而不是数字常量
在这一点上,这应该是直截了当的
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
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;