C 组装,总和上的负值处理

C 组装,总和上的负值处理,c,gcc,assembly,x86,signed,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: /*************************

带有注释的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
/*********************************************************************************/
但是为什么呢?
在其他add函数中已经使用了相同的算法,并且没有问题。

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

pushl   %eax        

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

popl    %eax        ; <-- overwrites what the add2 call returned
pushl%eax
第4幕(%ebx),%esi
pushl%esi
呼叫地址2
加4美元,特别是

popl%eax;谢谢@Michael,说得好。另一个add函数没有
调用
,因此没有
pushl%eax
popl%eax
崩溃。我还忘记了
addl(%ebx),%eax
之后的
jmp end
。我在通话后添加了
%edi
以接收
%eax
值,并维护了它的
pushl
popl
。之后,
movl
返回
%eax
的最终值。关于负值的修改(后面是减法,不是标准的加法),这是我所知道的唯一一种处理负值的算法。你知道另一个吗?
neg:negl    (%ebx)          /* c = |c|                              */
    subl    (%ebx), %eax    /* return x->(-)c + add2(x->next);      */
pushl   %eax        

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

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