linux 可变参数 原理,Linux C variadic可变参数:va_list 在x86和x64下的区别与实现原理...

#include

#include

#if __GNUC__

#if __x86_64__

#define ENVIRONMENT64

#else

#define ENVIRONMENT32

#endif

#endif

#if defined(ENVIRONMENT64)

long add(long num, ...)

{

long sum = 0, i, tmp;

/*

(gdb) pt va_list

type = struct __va_list_tag {

unsigned int gp_offset;

unsigned int fp_offset;

void *overflow_arg_area;

void *reg_save_area;

} [1]

*/

va_list va;

printf("ENVIRONMENT64\n");

/*

(gdb) p va

$2 = {{

gp_offset = 8,

fp_offset = 48,

overflow_arg_area = 0x7fffffffe520,

reg_save_area = 0x7fffffffe460

}}

(gdb) x/6g va.reg_save_area // 这里g表示一次打印8字节

0x7fffffffe460: 0x0000000000000001 0x0000000000000002

0x7fffffffe470: 0x0000000000000003 0x0000000000000004

0x7fffffffe480: 0x0000000000000005 0x0000000000000006

(gdb) x/2g va.overflow_arg_area

0x7fffffffe520: 0x0000000000000007 0x0000000000000008

*/

va_start(va, num);

for (i = 0; i < num; i++) {

tmp = va_arg(va, int);

sum += tmp;

printf("%ld ", tmp);

}

printf("\n");

va_end(va);

return sum;

}

#endif

#if defined(ENVIRONMENT32)

long add(long num, ...)

{

long sum = 0, i, tmp;

long *arg = &num + 1;

printf("ENVIRONMENT32\n");

for (i = 0; i < num; i++)

{

tmp = arg[i];

sum += tmp;

printf("%ld ", tmp);

}

printf("\n");

return sum;

}

#endif

int main()

{

/* ENVIRONMENT32, 使用栈来传参

0x080484f5 : movl $0x8,0x1c(%esp)

0x080484fd : movl $0x7,0x18(%esp)

0x08048505 : movl $0x6,0x14(%esp)

0x0804850d : movl $0x5,0x10(%esp)

0x08048515 : movl $0x4,0xc(%esp)

0x0804851d : movl $0x3,0x8(%esp)

0x08048525 : movl $0x2,0x4(%esp)

0x0804852d : movl $0x7,(%esp)

0x08048534 : call 0x804847d

*/

/* ENVIRONMENT64, 使用寄存器+栈(默认calling convention)

0x0000000000400711 : movl $0x8,0x8(%rsp)

0x0000000000400719 : movl $0x7,(%rsp)

0x0000000000400720 : mov $0x6,%r9d

0x0000000000400726 : mov $0x5,%r8d

0x000000000040072c : mov $0x4,%ecx

0x0000000000400731 : mov $0x3,%edx

0x0000000000400736 : mov $0x2,%esi

0x000000000040073b : mov $0x7,%edi

0x0000000000400740 : mov $0x0,%eax

0x0000000000400745 : callq 0x4005bd

*/

long sum = add(7, 2, 3, 4, 5, 6, 7, 8);

printf("sum is %ld\n", sum);

return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值