Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2159602
  • 博文数量: 438
  • 博客积分: 3871
  • 博客等级: 中校
  • 技术积分: 6075
  • 用 户 组: 普通用户
  • 注册时间: 2011-09-10 00:11
个人简介

邮箱: wangcong02345@163.com

文章分类

全部博文(438)

文章存档

2017年(15)

2016年(119)

2015年(91)

2014年(62)

2013年(56)

2012年(79)

2011年(16)

分类: LINUX

2016-08-24 17:45:52

1.1 整理一下代码
  1. cong@msi:/work/os/code/6print$ tree
  2. .
  3. ├── boot
  4. │   ├── loader.S
  5. │   └── mbr.S
  6. ├── include
  7. │   ├── print.h
  8. │   └── stdint.h
  9. ├── kernel
  10. │   └── main.c
  11. ├── lib
  12. │   ├── printf.c
  13. │   ├── printf.o
  14. │   ├── put_char.o
  15. │   └── put_char.S
  16. ├── Makefile
  17. ├── makefile_bak
  18. └── Makefile_bak
1.2 Makefile
  1. cong@msi:/work/os/code/6print$ cat Makefile
  2. ENTRY_POINT = 0xc0001500
  3. AS = nasm
  4. CC = gcc
  5. LD = ld
  6. LIB = -I lib/ -I lib/kernel/ -I lib/user/ -I kernel/ -I device/
  7. ASFLAGS = -f elf
  8. CFLAGS = -Wall $(LIB) -c -fno-builtin -W -Wstrict-prototypes \
  9.          -Wmissing-prototypes
  10. LDFLAGS = -Ttext $(ENTRY_POINT) -e main -Map $(BUILD_DIR)/kernel.map

  11. all: mbr loader kern
  12. mbr:
  13.     nasm ./boot/mbr.S -I ./boot/include/ -o ./boot/mbr.bin
  14. loader:
  15.     nasm ./boot/loader.S -I ./boot/include/ -o ./boot/loader.bin
  16. kern:put_char.o printf.o main.o
  17.     ld -m elf_i386 -Ttext 0xc0001500 -e main -o ./kernel/kernel.bin \
  18.         ./kernel/main.o ./lib/put_char.o ./lib/printf.o
  19. main.o:
  20.     gcc $(CFLAGS) -c -m32 -I ./include -o ./kernel/main.o ./kernel/main.c
  21. printf.o:
  22.     gcc $(CFLAGS) -c -m32 -I ./include -o ./lib/printf.o ./lib/printf.c
  23. put_char.o:
  24.     nasm $(ASFLAGS) ./lib/put_char.S -o ./lib/put_char.o

  25. clean:
  26.     -rm /work/os/code/disk.img ./boot/mbr.bin ./boot/loader.bin ./kernel/*.o ./kernel/kernel.bin
  27. flash:
  28.     -rm /work/os/code/disk.img
  29.     dd if=/dev/zero of=/work/os/code/disk.img bs=1M count=30
  30.     dd if=./boot/mbr.bin of=/work/os/code/disk.img bs=512 count=1 conv=notrunc
  31.     dd if=./boot/loader.bin of=/work/os/code/disk.img bs=512 count=5 seek=2 conv=notrunc
  32.     dd if=./kernel/kernel.bin of=/work/os/code/disk.img bs=512 count=200 seek=9 conv=notrunc
  33. show:
  34.     echo "show loader.bin"
  35.     xxd ./loader.bin
  36.     echo "show disk.img"
  37.     xxd -seek 0x400 -l 0x200 /work/os/code/disk.img
1.3 printf.c
原书中实现了put_char,那么进一步就可以实现printf
  1. cong@msi:/work/os/code/6print/lib$ cat printf.c
  2. #include "print.h"
  3. #include <stdarg.h>
  4. void put_string(char *str)
  5. {
  6.     while(*str!='\0')
  7.     {
  8.         put_char(*str);
  9.         str++;
  10.     }
  11. }
  12. static void itoa(char **buf, unsigned char i, unsigned char base)    -->这儿有个bug,unsigned char应该换成int
  13. {
  14.     static char *s;
  15. #define LEN 20
  16.     unsigned char rem;
  17.     static char rev[LEN+1];

  18.     rev[LEN] = 0;
  19.     if (i == 0)
  20.     {
  21.         (*buf)[0] = '0';
  22.         ++(*buf);
  23.         return;
  24.     }
  25.     s = &rev[LEN];
  26.     while (i)
  27.     {
  28.         rem = i % base;
  29.         if (rem < 10)
  30.             *--s = rem + '0';
  31.         else if (base == 16)
  32.             *--s = "abcdef"[rem - 10];
  33.         i /= base;
  34.     }
  35.     while (*s)
  36.     {
  37.         (*buf)[0] = *s++;
  38.         ++(*buf);
  39.     }
  40. }
  41. char print_buf[250];
  42. void printf(char *fmt,...)
  43. {
  44.     va_list ap;
  45.     int ival;
  46.     char *p;
  47.     char *bp;
  48.     bp= print_buf;
  49.     *bp= '\0';

  50.     va_start (ap, fmt);
  51.     for (p= fmt; *p; p++)
  52.     {
  53.         if (*p != '%')
  54.         {
  55.             *bp++= *p;
  56.             continue;
  57.         }
  58.         switch (*++p) {
  59.             case 'd':
  60.                 ival= va_arg(ap, int);
  61.                 itoa (&bp, ival, 10);
  62.                 break;
  63.             case 'x':
  64.                 ival= va_arg(ap, int);
  65.                 itoa (&bp, ival, 16);
  66.                 break;
  67.         }
  68.     }
  69.     *bp = '\0';
  70.     put_string(print_buf);        
  71.     va_end (ap);
  72. }
1.4 main函数测试
  1. cong@msi:/work/os/code/6print$ cat kernel/main.c
  2. #include "print.h"
  3. void main(void)
  4. {
  5.     int a=3;
  6.     put_char('k');
  7.     printf("a=%d\n",a);
  8.     while(1)
  9.     {
  10.     }
  11.     return ;
  12. }
1.5 代码打包
6print.rar (下载后改名为6print.tar.gz)
1.6 运行测试


printf实现了

1.7  一个问题
1.7.1 printf.c中使用了系统中的stdarg.h
Makefile中加入-nostdinc时就会报错
./lib/printf.c:2:20: fatal error: stdarg.h: No such file or directory
1.7.2 自己实现一个va_list
  1. #ifndef __LIB_STDARG_H
  2. #define __LIB_STDARG_H
  3. typedef char * va_list;
  4. #define _INTSIZEOF(n) ((sizeof(n)+sizeof(int)-1)&~(sizeof(int) - 1) )
  5. #define va_start(ap,v) ( ap = (va_list)&v + _INTSIZEOF(v) )
  6. #define va_arg(ap,t) ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
  7. #define va_end(ap) ( ap = (va_list)0 )
  8. #endif
1.7.3 代码打包
6print.rar (下载后改名为6print.tar.gz)
阅读(1365) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~