69,371
社区成员
发帖
与我相关
我的任务
分享
#include <stdio.h>
#define __va_rounded_size(TYPE) \
(((sizeof(TYPE)+sizeof(int)-1)/sizeof(int))*sizeof(int))
#define va_start(AP,LASTART) \
(AP = ((char* )&LASTART+ __va_rounded_size(LASTART)))
#define va_arg(AP,TYPE) \
(AP += __va_rounded_size(TYPE), \
*((TYPE* )(AP - __va_rounded_size(TYPE))))
void get_display(int first,int second,...)
{
char* args;
va_start(args,second);
second = va_arg(args,int);
while(second>=0)
{
printf("%d\n",second);
second = va_arg(args,int);
}
}
int main()
{
get_display(1,2,3,4,5,6,7);
getchar();
return 0;
}
.file "test_args.c"
.section .rodata
.LC0:
.string "%d\n"
.text
.globl get_display
.type get_display, @function
get_display:
pushl %ebp
movl %esp, %ebp
subl $24, %esp
leal 12(%ebp), %eax
addl $4, %eax
movl %eax, -4(%ebp)
addl $4, -4(%ebp)
movl -4(%ebp), %eax
subl $4, %eax
movl (%eax), %eax
movl %eax, 12(%ebp)
jmp .L2
.L3:
movl 12(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
addl $4, -4(%ebp)
movl -4(%ebp), %eax
subl $4, %eax
movl (%eax), %eax
movl %eax, 12(%ebp)
.L2:
movl 12(%ebp), %eax
testl %eax, %eax
jns .L3
leave
ret
.size get_display, .-get_display
.globl main
.type main, @function
main:
leal 4(%esp), %ecx
andl $-16, %esp
pushl -4(%ecx)
pushl %ebp
movl %esp, %ebp
pushl %ecx
subl $36, %esp
movl $7, 24(%esp)
movl $6, 20(%esp)
movl $5, 16(%esp)
movl $4, 12(%esp)
movl $3, 8(%esp)
movl $2, 4(%esp)
movl $1, (%esp)
call get_display
call getchar
movl $0, %eax
addl $36, %esp
popl %ecx
popl %ebp
leal -4(%ecx), %esp
ret
.size main, .-main
.ident "GCC: (GNU) 4.1.2 20070925 (Red Hat 4.1.2-33)"
.section .note.GNU-stack,"",@progbits
andl $-16, %esp
.file "test_args.c"
.section .rodata
.LC0:
.string "%d\n"
.text
.globl get_display
.type get_display, @function
get_display:
pushl %ebp ;
movl %esp, %ebp;
subl $24, %esp
leal 12(%ebp), %eax
addl $4, %eax
movl %eax, -4(%ebp)
addl $4, -4(%ebp)
movl -4(%ebp), %eax
subl $4, %eax
movl (%eax), %eax
movl %eax, 12(%ebp)
jmp .L2
.L3:
movl 12(%ebp), %eax
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
addl $4, -4(%ebp)
movl -4(%ebp), %eax
subl $4, %eax
movl (%eax), %eax
movl %eax, 12(%ebp)
.L2:
movl 12(%ebp), %eax
testl %eax, %eax
jns .L3
leave
ret
.size get_display, .-get_display
.globl main
.type main, @function
main:
leal 4(%esp), %ecx ;ecx=esp+4
andl $-16, %esp ;esp指针下移16,对齐用
pushl -4(%ecx) ;将函数返回地址入栈,ecx=esp+4;所以esp=ecx-4;
pushl %ebp
movl %esp, %ebp ;跟上句维护了一个栈环境
pushl %ecx ;ecx记录着main函数返回地址相关信息
subl $36, %esp ;栈顶指针下移36 为用户的变量分配足够的空间
movl $7, 24(%esp)
movl $6, 20(%esp)
movl $5, 16(%esp)
movl $4, 12(%esp)
movl $3, 8(%esp)
movl $2, 4(%esp)
movl $1, (%esp) ;相关参数从右到左依次入栈
call get_display ;调用get_display函数,程序跳转到get_display:,从那开始执行指令
call getchar
movl $0, %eax ;main函数的返回值设为0
addl $36, %esp ;栈顶指针恢复先前位置,相当于清栈
popl %ecx ;取栈顶值存入ecx,实际就是取的ecx
popl %ebp
leal -4(%ecx), %esp ;main函数返回地址设为ecx-4
ret
.size main, .-main
.ident "GCC: (GNU) 4.1.2 20070925 (Red Hat 4.1.2-33)"
.section .note.GNU-stack,"",@progbits
在call的时候call语句的下一条语句的代码的地址会入栈
00411C70 push ebp ;保存主调函数的局部变量栈的最高地址
00411C71 mov ebp,esp ;将当前栈顶作为这个函数的栈上的变量的分配地址
00411C73 sub esp,40h ;40是作为一个空白空间,一般的时候会大于40h这些就是栈上的变量所占的空间,这个时候如果有函数调用就会从已经有变化的esp上开始分配空间
00411C76 push ebx;
00411C77 push esi;
00411C78 push edi;保存必要的值
9: return 0;
00411C79 xor eax,eax;设置返回值
10: }
00411C7B pop edi;
00411C7C pop esi;
00411C7D pop ebx;还原必要的值
00411C7E mov esp,ebp;还原esp
00411C80 pop ebp;还原被调函数的栈变量的最高地址
00411C81 ret;保存在栈上的那个call语句的下一条语句的地址出栈,并放到EIP里,并开始执行那里的代码