C x86汇编代码混乱
我们刚刚开始讨论组装的话题,我已经在这个问题上呆了很长时间了。我必须将程序集转换为C代码,如下所示: C代码:C x86汇编代码混乱,c,assembly,x86,intel,C,Assembly,X86,Intel,我们刚刚开始讨论组装的话题,我已经在这个问题上呆了很长时间了。我必须将程序集转换为C代码,如下所示: C代码: int foo(int *a, int n, int val) { int i; for (i = _________; ____________________________ ; i =___________) { ; } return i; } 大会: // what I've gathered so far foo() : fo
int foo(int *a, int n, int val) {
int i;
for (i = _________; ____________________________ ; i =___________) {
;
}
return i;
}
大会:
// what I've gathered so far
foo()
:
foo:
pushl %ebp
movl %esp,%ebp
movl 8(%ebp),%ecx // ecx: a
movl 16(%ebp),%edx // edx: val
movl 12(%ebp),%eax // eax: n
decl %eax // n = n--
js .L3 // if n < 0 goto done
.L7: // loop
cmpl %edx,(%ecx,%eax,4) // I don't understand how you would compute the
// address for (%ecx,%eax,4) I know it would be %ecx + %eax*4 = %ecx + eax << 2
jne .L3 // if (%ecx, %eax, 4) != val goto done (?)
decl %eax // n = n--
jns .L7 // if (n >= 0) jump to loop
.L3: // done
movl %ebp,%esp
popl %ebp
ret
//到目前为止我收集了什么
foo()
:
傅:
推力%ebp
移动%esp,%ebp
movl 8(%ebp),%ecx//ecx:a
movl 16(%ebp),%edx//edx:val
movl 12(%ebp),%eax//eax:n
decl%eax//n=n--
js.L3//如果n<0,则转到完成
.L7://循环
cmpl%edx,(%ecx,%eax,4)//我不明白您将如何计算
//(%ecx,%eax,4)的地址我知道它将是%ecx+%eax*4=%ecx+eax=0)跳转到循环
.L3://完成
移动%ebp,%esp
popl%ebp
ret
我不知道如何弄清楚我被初始化为什么,循环的主体是什么。我假设I=n,因为n作为更新。似乎有两个条件,一个是n>0,另一个是cmpl线。如果我对代码的理解不正确,请纠正我,对此问题的任何线索都将不胜感激 我本可以通过1个错误消除一些错误,但基本上是这样的:
int foo(int *a, int n, int val) {
int i;
for (i = n - 1; i >= 0 && a[i] == val; i = i - 1) {
;
}
return i;
}
i
是%eax
寄存器;它从n-1
循环到0。cmpl
索引访问(%ecx,%eax,4)
以字节为单位寻址-这相当于a[i]
,因为ia32上的int
的大小为4字节。因此寻址的4个字节与val
进行比较
%eax
被隐式返回
还要注意,js
表示<0
,而jns
=0
另一种写作方式:
i = n;
i --; // decl %eax
if (i < 0) {
goto L3; // js .L3
}
L7:
if (a[i] != val) // cmpl %edx,(%ecx,%eax,4)
goto L3; // jne .L3
i --; // decl %eax
if (i >= 0)
goto L7; // jns .L7
L3:
return i;
i=n;
我--;//十二月%eax
if(i<0){
转到L3;//js.L3
}
L7:
如果(a[i]!=val)//cmpl%edx,(%ecx,%eax,4)
转到L3;//jne.L3
我--;//十二月%eax
如果(i>=0)
转到L7;//约七
L3:
返回i;
使用预处理器的替代方案:
#define _________ n - 1
#define ____________________________ i >= 0 && a[i] == val
#define ___________ i + 1
int foo(int *a, int n, int val) {
int i;
for (i = _________; ____________________________ ; i =___________) {
;
}
return i;
}
当然,你只能用它来取乐或取笑新程序员;-) 它在数组中寻找一个值,但我不打算为您编写一个非常简单的循环。小心终端条件!。。。。循环体是什么:在C中,循环可以没有体。根据C模式中显示的形式,情况似乎是这样。所有有趣的工作都是在初始条件(第一个
)、测试条件(第二个)、和“increment”语句(第三个)、编译器设法为函数中的所有局部变量使用寄存器。这是一个简单的循环,你几乎做到了。for
语句中的第一个和最后一个表达式非常简单,条件表达式测试两个条件。还要记住,a
是指向int
s数组的指针。另一个线索:这个循环的编写方式很麻烦。您可以简化它以保持相同的语义,同时删除更新(第三个)表达式并缩短编译后的代码。@chqrlie我猜发布的C代码是赋值所需的模板。行:cmpl%edx,(%ecx,%eax,4)jne.L3不是说如果[i]!=val,跳转到L3(哪个是完成代码)?为什么它会继续在for循环中?当然,注释有点离题,因为cmpl+jne一起是if@AnttiHaapala上面的评论员试图在不做作业的情况下提供帮助。Downvote.OP显示了对程序集的理解,但在本例中,在如何将其转换为C方面却迷失了方向-鉴于主题是理解程序集,那么将其转换为C最多只是表面现象。这并不完全是一次性错误,但测试表达式中的变量名是错误的。使用此:for(i=n-1;i>=0&&a[i]==val;i=i-1)