【问题标题】:Converting Assembly to C将汇编转换为 C
【发布时间】:2014-06-13 11:07:08
【问题描述】:

我的教授在周五的讲座中向我们提出了一个“挑战”问题。他给了我们一个 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(这会将 8 的内容从 ebp 寄存器移到 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 是 i 吗?

再次感谢!

【问题讨论】:

  • 你从哪里得到eax=eax^2*4?错了……
  • from leal (%eax,%eax,4),%eax 实际上是 eax = eax + eax*4?
  • eax = eax + eax*4 不是 eax=eax^2*4

标签: c assembly


【解决方案1】:

mat1mat2 是变量的地址。一旦它们不在堆栈中,它们就具有固定值......(它们被声明为静态变量)......所以它们只是指mat1mat2的内存地址

  • ecx = j
  • eax = i

在函数的开头......但后来

  • ecx = j
  • eaxedx(第 10 行和第 11 行)都在执行来自 i 的数组偏移量。发生这种情况是因为矩阵在第一个索引处具有不同的大小。一个是M,另一个是N

关于leal 0(,%eax,8),%edx,意思是edx = 8 * eax 它用于计算来自i的偏移量,但由于subl %eax,%edxedx = edx - eax = edx - i = i * 8 - i = 7 * i与 ,所以最终的edx = 7 * i...M = 7

同理:在第 10 行 %eax = i * N = i + 4 * i = 5 * i,因此是 N = 5i + 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

【讨论】:

  • 我仍然不明白这两个或 sizeof(int) 的来源。与 Oakad 相比,这是一种不同的方法吗?
  • 它是在编译时生成的。编译器知道 sizeof(int)=4 也知道 M=2,所以它在 COMPILE TIME 2*4=8 中执行并将 8 放在那里。
  • 对不起,我搞错了...i*sizeof(int) 的跳转是由第 10 行和第 11 行的指令进行的。所以M = 8
【解决方案2】:

mat1mat2 只是内存位置的命名地址,与 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

其中mat2mat1 是表示汇编程序已知的一些地址的常量数值。

leal 指令只是“整数加/乘”操作的花哨名称,通常用于地址计算:

leal 0(,%eax,8),%edx -> load eax * 8 + 0 into edx

【讨论】:

  • 感谢您的回复,但是我仍然不知道如何计算 M 和 N 的值。我更新了我的帖子以澄清。
  • 这不是一个家庭作业帮助网站,但这里有一个提示:你想将 2 个数字相加,一个位于 mat1 + i * N + j 处;另一个在 mat2 + i * M + j 处。 j 显然在 ecx 中。 eax 在某些时候持有 i * M。 edx 在某些时候持有 i * N。
  • 如果 eax 在某个时候持有 iM 而 edx 在某个时候持有 iN 那么我会假设 M 是 4 而 N 是 8。如果这是正确的,我'还想知道你是如何知道 eax = iM 和 edx = iN 的。再次感谢!
  • N 实际上是 7。而 M 是 5。
  • 谢谢!但是你能解释一下为什么我的答案被偏移(sp?) 1 吗?
猜你喜欢
  • 2021-04-23
  • 1970-01-01
  • 1970-01-01
  • 2015-12-03
  • 2021-02-26
  • 2017-08-31
  • 2013-10-20
  • 2017-01-08
  • 2014-06-07
相关资源
最近更新 更多