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

一直好奇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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值