QEMU裸机开发之格式化打印
在前面的程序中我们实现了简单的字符串输出函数,在实际使用时,我们还需要进行格式化打印,比如打印某个变量的值,按十进制或者十六进制打印等等,本章节我们在“uart.c”中实现一个简单的printf函数,用于后续程序的调试,在“uart.c”中添加的代码如下所示。
//printf functions static char digits[] = "0123456789abcdef"; static void print_int(int xx, int base, int sign) { char buf[16]; int i; unsigned int x; if(sign && (sign = xx < 0)) x = -xx; else x = xx; i = 0; do { buf[i++] = digits[x % base]; } while((x /= base) != 0); if(sign) buf[i++] = '-'; while(--i >= 0) uart_putc(buf[i]); } static void print_ptr(unsigned long x) { int i; uart_putc('0'); uart_putc('x'); for (i = 0; i < (sizeof(unsigned long) * 2); i++, x <<= 4) uart_putc(digits[x >> (sizeof(unsigned long) * 8 - 4)]); } // Print to the console. only understands %d, %x, %p, %s. void printf(char *fmt, ...) { va_list ap; int i, c; char *s; if (fmt == 0) return; va_start(ap, fmt); for(i = 0; (c = fmt[i] & 0xff) != 0; i++) { if(c != '%'){ uart_putc(c); continue; } c = fmt[++i] & 0xff; if(c == 0) break; switch(c){ case 'd': print_int(va_arg(ap, int), 10, 1); break; case 'x': print_int(va_arg(ap, int), 16, 1); break; case 'p': print_ptr(va_arg(ap, unsigned long)); break; case 's': if((s = va_arg(ap, char*)) == 0) s = "(null)"; for(; *s; s++) uart_putc(*s); break; case '%': uart_putc('%'); break; default: // Print unknown % sequence to draw attention. uart_putc('%'); uart_putc(c); break; } } }
这个printf实现参考xv6,功能也很简单,主要有以下几个功能:
- %d:32位数据按十进制打印。
- %x:32位数据按十六进制打印。
- %p:按16进制打印指针数值。
- %s:打印字符串。
有了这几个功能之后,基本能对付大部分的打印调试需求了,将“start.c”中的打印换成printf,如下所示。
#include "uart.h" void start(void) { printf("%s %d.\r\n", __func__, __LINE__); }
在命令行执行“make qemu”,可以在最后看到打印的函数名以及行号信息,如下所示。
gewenbin@gewenbin-virtual-machine:~/Desktop/qemu_test/lesson2$ make qemu riscv64-unknown-elf-gcc -Wall -Werror -O -fno-omit-frame-pointer -ggdb -mcmodel=medany -ffreestanding -fno-common -nostdlib -mno-relax -I. -fno-stack-protector -fno-pie -no-pie -c -o start.o start.c riscv64-unknown-elf-gcc -Wall -Werror -O -fno-omit-frame-pointer -ggdb -mcmodel=medany -ffreestanding -fno-common -nostdlib -mno-relax -I. -fno-stack-protector -fno-pie -no-pie -c -o uart.o uart.c riscv64-unknown-elf-ld -z max-page-size=4096 -T kernel.ld -o kernelimage entry.o start.o uart.o riscv64-unknown-elf-objdump -S kernelimage > kernel.asm riscv64-unknown-elf-objdump -t kernelimage | sed '1,/SYMBOL TABLE/d; s/ .* / /; /^$/d' > kernel.sym qemu-system-riscv64 -machine virt -bios none -kernel kernelimage -m 128M -smp 1 -nographic start 5.
工程源码:链接:https://pan.baidu.com/s/1TnTYr7mywdKj5bxpdmWnyA,提取码:q772,见lesson2。
评论