带有注释的c版本的程序集函数:

/*
struct X
{
    int c;       // 4 bytes
    struct X *next;  // 4 bytes
};

int add2 (struct X *x)
{
    if (x == NULL) return 0;
    else return x->c + add2(x->next);
}
*/

.text

.globl add2
add2:
/********************************** prologue *************************************/
    pushl   %ebp
    movl    %esp, %ebp
    pushl   %ebx
    pushl   %esi
/********************************************************************************/

    movl    8(%ebp), %ebx
    cmpl    $0, %ebx
    jne     out
    movl    $0, %eax
    jmp     end

out:
/***************************** calculates in x->next *******************************/
    pushl   %ecx
    pushl   %edx
    pushl   %eax

    movl    4(%ebx), %esi
    pushl   %esi
    call    add2
    addl    $4, %esp

    popl    %eax
    popl    %edx
    popl    %ecx
/********************************************************************************/

    cmpl    $0, (%ebx)      /* > negative values                     */
    js      neg             /*   treatment <                        */

    addl    (%ebx), %eax    /* return    x->c + add2(x->next);      */

neg:negl    (%ebx)          /* c = |c|                              */
    subl    (%ebx), %eax    /* return x->(-)c + add2(x->next);      */
end:
/****************************************end *************************************/
    popl    %esi
    popl    %ebx
    movl    %ebp, %esp
    popl    %ebp
    ret
/*********************************************************************************/

主c代码:
#include <stdio.h>
#include <stdlib.h>

struct X
{
    int c;
    struct X * next;
};
typedef struct X Xlist;

Xlist * lst_create (void)
{
    return NULL;
}

Xlist * lst_insert (Xlist * l, int c)
{
    Xlist * new = (Xlist*) malloc(sizeof(Xlist));
    new->c = c;
    new->next = l;

    return new;
}

int add2 (struct X * x);

int main (void)
{
//  int i;
    Xlist * l;
    l = lst_create();

    //for (i=-9;i<10;i++)
    l = lst_insert(l, -1);

    printf("%d\n", add2(l));

    return 0;
}

其目的是打印链接列表元素的总和。
当使用负值时,我会得到内存垃圾。我相信错误就在这里:
neg:negl    (%ebx)          /* c = |c|                              */
    subl    (%ebx), %eax    /* return x->(-)c + add2(x->next);      */

但为什么呢?
已经在其他add函数中使用了相同的算法,这是可以的。

最佳答案

在我看来,一个大问题是对add2()的递归调用忽略了返回值:

pushl   %eax

movl    4(%ebx), %esi
pushl   %esi
call    add2
addl    $4, %esp

popl    %eax        ; <-- overwrites what the add2 call returned

而且,您的C等价代码似乎并不真正等价。程序集版本将列表中的负值修改为正值;这不会反映在C代码版本中。

关于c - 组装,总和的负值处理,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24178455/

10-12 05:46