汇总,负值处理总和

时间:2014-06-12 07:10:19

标签: c gcc assembly x86 signed

带有注释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);      */

但为什么呢? 已经在其他添加功能中使用了相同的算法,这没问题。

1 个答案:

答案 0 :(得分:1)

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

pushl   %eax        

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

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

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