自己用C语言实现Printf(二)

上一节分析了怎么实现printf但是在实践时候又发现了点东西分享一下,本节主要是在linux平台用gcc实现打印。

在南大JYY的实验课程里M1需要自己实现Printf,给了putch和putstr接口

#ifndef KLIB_MACROS_H__
#define KLIB_MACROS_H__

#define ROUNDUP(a, sz)      ((((uintptr_t)a) + (sz) - 1) & ~((sz) - 1))
#define ROUNDDOWN(a, sz)    ((((uintptr_t)a)) & ~((sz) - 1))
#define LENGTH(arr)         (sizeof(arr) / sizeof((arr)[0]))
#define RANGE(st, ed)       (Area) { .start = (void *)(st), .end = (void *)(ed) }
#define IN_RANGE(ptr, area) ((area).start <= (ptr) && (ptr) < (area).end)

#define STRINGIFY(s)        #s
#define TOSTRING(s)         STRINGIFY(s)
#define _CONCAT(x, y)       x ## y
#define CONCAT(x, y)        _CONCAT(x, y)

#define putstr(s) \
  ({ for (const char *p = s; *p; p++) putch(*p); })

#define io_read(reg) \
  ({ reg##_T __io_param; \
    ioe_read(reg, &__io_param); \
    __io_param; })

#define io_write(reg, ...) \
  ({ reg##_T __io_param = (reg##_T) { __VA_ARGS__ }; \
    ioe_write(reg, &__io_param); })

#define static_assert(const_cond) \
  static char CONCAT(_static_assert_, __LINE__) [(const_cond) ? 1 : -1] __attribute__((unused))

#define panic_on(cond, s) \
  ({ if (cond) { \
      putstr("AM Panic: "); putstr(s); \
      putstr(" @ " __FILE__ ":" TOSTRING(__LINE__) "  \n"); \
      halt(1); \
    } })

#define panic(s) panic_on(1, s)

#endif

所以我们在此基础上完成prinf的打印

首先定义变量


#if !defined(__ISA_NATIVE__) || defined(__NATIVE_USE_KLIB__)

#define _INTSIZE_(n)  4
#define ap_start(ap,v) (ap=(char *)&v + _INTSIE_(v))
#define ap_arg(ap,t) (*(t*)(ap=ap+_INTSIZE_(n),ap-_INTSIZE_(n)))
#define ap_end (ap = (char *)0)

然后以下是stdio.c里的代码;需要注意编译器不一样有的地方要自己稍微改改

#include <am.h>
#include <klib.h>
#include <klib-macros.h>
#include <stdarg.h>

#if !defined(__ISA_NATIVE__) || defined(__NATIVE_USE_KLIB__)

#define _INTSIZE_(n)  4
#define ap_start(ap,v) (ap=(char *)&v + _INTSIE_(v))
#define ap_arg(ap,t) (*(t*)(ap=ap+_INTSIZE_(n),ap-_INTSIZE_(n)))
#define ap_end (ap = (char *)0)
unsigned char hex_tab[] = { '0','1','2','3','4','5','6','7',\
						 '8','9','a','b','c','d','e','f' };               //输出各种进制下的字符

int _fun_int_(char * ap)
{
	
	{
		//long n=ap_arg(ap,int);
		unsigned long m=0 ;
		char buf[250],* s = buf + sizeof(buf);
		int count = 0;
		*--s = '\0';  
		m=(ap_arg(ap,int));
		
		do{
			*--s = hex_tab[m%10];
			count++;
		}while((m/=10)!=0);
		if ((ap_arg(ap,int)) < 0)
			*--s = '-';
		 
		putstr(s);
		 
	}
	return 0;
}

int printf(const char *fmt, ...) {
  //panic("Not implemented");
  
  
  char * ap;int maxwidth;
  ap = (char *)&fmt + _INTSIZE_(fmt);
  
  for (const char *p = fmt; *p; p++) 
  {
  	if(*p != '%')
  		putch(*p);
  	else
	{
		if(*p++);
		
  		while((*p)>= '0' && (*p)<='9')
  		{
  			maxwidth *= 10;
  			maxwidth +=(*p - '0');
  			if ( *p++);
   		}
   		
   		switch(*p)
   		{
   			
   			case 'd' :_fun_int_(ap);break;
   			case 'c' :putch(*ap_arg(ap,char *));break;
   			case 's' :putstr(ap_arg(ap,char *));break;
   		
   		}
	}
	
   }
      
  
  return 0;
}

int vsprintf(char *out, const char *fmt, va_list ap) {
  panic("Not implemented");
}

int sprintf(char *out, const char *fmt, ...) {
  panic("Not implemented");
}

int snprintf(char *out, size_t n, const char *fmt, ...) {
  panic("Not implemented");
}

int vsnprintf(char *out, size_t n, const char *fmt, va_list ap) {
  panic("Not implemented");
}

#endif

下面是应用程序:

#include <am.h>
#include <klib.h>
#include <klib-macros.h>

#define MAX_CPU 8

typedef union task {
  struct {
    const char *name;
    union task *next;
    void      (*entry)(void *);
    Context    *context;
  };
  uint8_t stack[8192];
} Task;

Task *currents[MAX_CPU];
#define current currents[cpu_current()]

// user-defined tasks

int locked = 0;
void lock()   { while (atomic_xchg(&locked, 1)); }
void unlock() { atomic_xchg(&locked, 0); }

void func(void *arg) {
  while (1) {
    lock();
    printf("Thread-%s on CPU #%d\n", arg, cpu_current());
    unlock();
    for (int volatile i = 0; i < 100000; i++) ;
  }
}

Task tasks[] = {
  { .name = "A", .entry = func },
  { .name = "B", .entry = func },
  { .name = "C", .entry = func },
  { .name = "D", .entry = func },
  { .name = "E", .entry = func },
};

// ------------------

Context *on_interrupt(Event ev, Context *ctx) {
  extern Task tasks[];
  if (!current) current = &tasks[0];
  else          current->context = ctx;
  do {
    current = current->next;
  } while ((current - tasks) % cpu_count() != cpu_current());
  return current->context;
}

void mp_entry() {
  iset(true);
  yield();
}

int main() {
  cte_init(on_interrupt);

  for (int i = 0; i < LENGTH(tasks); i++) {
    Task *task    = &tasks[i];
    Area stack    = (Area) { &task->context + 1, task + 1 };
    task->context = kcontext(stack, task->entry, (void *)task->name);
    task->next    = &tasks[(i + 1) % LENGTH(tasks)];
  }
  mpe_init(mp_entry);
}

结果:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值