带有注释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); */
但为什么呢? 已经在其他添加功能中使用了相同的算法,这没问题。
答案 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代码版本中。