C x86汇编代码混乱

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

我们刚刚开始讨论组装的话题,我已经在这个问题上呆了很长时间了。我必须将程序集转换为C代码,如下所示:

C代码:

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)