可变参数函数printf的实现(不使用va_list等内置宏定义)

来源:互联网 发布:网络怎么赚钱最快 编辑:程序博客网 时间:2024/06/06 04:20

一直好奇c语言中int printf( const char* format, …) 可变参数函数是怎样实现的,网上关于可变参数函数的实现基本上使用了va_list,va_start,va_end等内置宏定义,为了更深入的理解可变参数函数,决定直接使用内置汇编来实现关键操作。
1.可变参数函数的形参使用(…)来表示可变个数的参数,在实际调用时,所有的参数都会被压入栈中,需要自行从栈中读取参数,这只能使用内置汇编来实现了。关键汇编代码如下:

asm("pushl %%ebp;addl %1,%%ebp;movl (%%ebp),%%eax;popl %%ebp;":"=a"(v):"m"(offset));

my_printf.c

#include <stdio.h>#define is_digit(c) ((c) >= '0' && (c) <= '9')//#define NULL ((void *) 0)static int my_atoi(const char *s){    int i=0;    while (is_digit(*s))        i = i*10 + *(s++) - '0';    return i;}static int my_itoa(const int v,char *s){    int yi=0,result=0,a=v;    char c[11];    if(a==0){        s[0]='0',s[1]='\0';        return 1;    }    while(a!=0){        yi=a%10;        a=a/10;        result++;        c[result]=(char)(yi+48);    }    s[result]='\0';    int i=0;    for(i=result;i>0;i--)s[result-i]=c[i];    return result;}static int my_itox(const int v,char *s){    int yi=0,result=0,value=v;    char c[8]={'0','0','0','0','0','0','0','0'};    if(value!=0){        while(value!=0){            yi=value%16;            if(yi>9){                yi=yi-9;                c[result]=(char)(yi+64);            }else{                c[result]=(char)(yi+48);            }            value=value/16;            result++;        }    }else{        s[0]='0',s[1]='\0';        return 1;    }    c[result]='\0';    s[result]='\0';    int i=0;    for(i=result;i>0;i--)s[result-i]=c[i-1];    return result;}int my_strcpy(char *des,char *src,int skip){    int i=0;    char *p=src;    while(*p!='\0'){        des[skip+(i++)]=*(p++);    }    return i;}static int my_strlen(const char *s){    int i=0;    while(*(s++)!='\0')i++;    return i;}static int my_printf(const char *fmt, ...){    int num=1;    int buf_index=0;    char buf[1024]={'0'};//存储将打印到屏幕的字符串    char* p=fmt;    while(*p!='\0'){        buf[buf_index++]=*p;        if(*p=='%'){            buf_index--;            p++;            switch (*p){            case 'd':{                int v=0;                char a[10];                int offset=num*4+8;                asm("pushl %%ebp;addl %1,%%ebp;movl (%%ebp),%%eax;popl %%ebp;":"=a"(v):"m"(offset));                int len=my_itoa(v,a);                my_strcpy(buf,a,buf_index);                buf_index=buf_index+len;                break;                }            case 'c':{                int v=0;                int offset=num*4+8;                asm("pushl %%ebp;addl %1,%%ebp;movl (%%ebp),%%eax;popl %%ebp;":"=a"(v):"m"(offset));                buf[buf_index]=(char)v;                buf_index=buf_index+1;                 break;                }            case 's':{                char* v=NULL;                int offset=num*4+8;                asm("pushl %%ebp;addl %1,%%ebp;movl (%%ebp),%%eax;popl %%ebp;":"=a"(v):"m"(offset));                int vlen=my_strcpy(buf,v,buf_index);                buf_index=buf_index+vlen;                 break;                }            case 'x':{                int v=0;                char a[10];                int offset=num*4+8;                asm("pushl %%ebp;addl %1,%%ebp;movl (%%ebp),%%eax;popl %%ebp;":"=a"(v):"m"(offset));                int len=my_itox(v,a);                my_strcpy(buf,a,buf_index);                buf_index=buf_index+len;                 break;                }            default:                break;            }//switch            num++;//²ÎÊý¸öÊý        }//if        p++;    }//while    buf[buf_index]='\0';    printf("\n%s",buf);    return buf_index;}int main(){   my_printf("a=%d,b=%x,d=%c,s=%s",322343,0xabcd,'A',"hello\n");    return 0;}
0 0
原创粉丝点击