我的教授星期五在演讲中向我们提出了一个“挑战”问题。他给了我们一个C程序的程序集,然后从C代码中删除了两个常量。 大会:
sum_element:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%eax
movl 12(%ebp),%ecx
sall $2,%ecx
leal 0(,%eax,8),%edx
subl %eax,%edx
leal (%eax,%eax,4),%eax
movl mat2(%ecx,%eax,4),%eax
addl mat1(%ecx,%edx,4),%eax
movl %ebp,%esp
popl %ebp
ret
然后是C代码:
#define M ____
#define N ____
int mat1[M][N];
int mat2[N][M];
int sum_element(int i, int j)
{
return mat1[i][j] + mat2[i][j];
}
然后他告诉我们M和N的值是多少。
到目前为止我做了什么:
movl %esp,%ebp
(这会将esp寄存器移到ebp寄存器中)
movl 8(%ebp),%eax
(这会将ebp寄存器中8的内容移到eax寄存器中)
movl 12(%ebp),%ecx
(这会将12的ebp寄存器的内容移到ecx寄存器中)
sall $2,%ecx
(这会将存储在ecx左侧的数字偏移2位,因此除以4)
leal 0(,%eax,8),%edx
(我不确定表达式前面的0是做什么的,否则它将eax * 8加载到edx中)
subl %eax,%edx
(edx = edx - eax)
leal (%eax,%eax,4),%eax
(eax = eax ^ 2 * 4)
movl mat2(%ecx,%eax,4),%eax
(eax =无论mat2(ecx,eax,4)是什么)
addl mat1(%ecx,%edx,4),%eax
(eax = eax +无论mat1(ecx,edx,4)是什么)
我不理解的部分是mat1,mat2和前面有0的leal。
谢谢!
编辑:总结一下到目前为止:
ecx=ecx/4
edx=eax*8-eax
eax=eax*4+eax
我以为在知道mat1和mat2之后我能够计算M和N的值,但是我要么忽略了明显的,要么还有一点点要做。任何方向都会很棒。
ecx是j而eax是我吗?
再次感谢!
答案 0 :(得分:3)
mat1
和mat2
只是内存位置的命名地址,与C代码中的相同。
movl mat2(%ecx,%eax,4),%eax -> load *(ecx + mat2 + (eax * 4)) into eax
addl mat1(%ecx,%edx,4),%eax -> add *(ecx + mat1 + (edx * 4) to eax
其中mat2
和mat1
是表示汇编程序已知的某些地址的常量数值。
leal
指令只是一个奇怪的名称,用于"整数加/乘"操作,通常用于地址计算:
leal 0(,%eax,8),%edx -> load eax * 8 + 0 into edx
答案 1 :(得分:1)
mat1
和mat2
是变量的地址。一旦它们不在堆栈中,它们就有固定的值...(它们被声明为静态变量)...所以它们只是意味着mat1
和mat2
ecx = j
eax = i
在函数的开头......但稍后
ecx = j
eax
和edx
(第10行和第11行)都在执行来自i
的数组偏移量。这是因为矩阵在第一个索引处具有不同的大小。一个是M
,另一个是N
。关于leal 0(,%eax,8),%edx
,这意味着edx = 8 * eax
它用于计算来自i
的偏移量,但由于subl %eax,%edx
,edx = edx - eax = edx - i = i * 8 - i = 7 * i
有,所以最终edx = 7 * i
... M = 7
。
同样的方式:在第10行%eax = i * N = i + 4 * i = 5 * i
中,N = 5
。 i + 4 * i
来自leal (%eax,%eax,4),%eax
mat1[i][j] > mat1 + ( M + i ) * 4 + j * 4 > mat2(%ecx,%eax,4),%eax
mat2[i][j] > mat2 + ( N + i ) * 4 + j * 4 > mat1(%ecx,%edx,4),%eax
顺便说一下:
leal (%eax,%eax,4),%eax
= eax += eax + eax * 4
而非eax = eax^2*4
sall $2,%ecx
= ecx *= 4
而非ecx = ecx/4