跟我一起写操作系统(三)——打印函数和qemu虚拟机

  转载注明出处:http://www.cnblogs.com/lucasysfeng/p/4847662.html

  上一讲地址:http://www.cnblogs.com/lucasysfeng/p/4847662.html

  项目地址:https://github.com/lucasysfeng/lucasOS

  

  本讲主要涉及以下三个方面:1. 打印函数封装;2. qemu的使用;3. 项目目录结构调整。 理由如下:1. 后续开发无疑会遇到打印变量的操作,因此有必要封装打印函数(内核开发阶段,无法调用库函数);2. 前两节,我们都是生成镜像文件,然后由VMvare启动,过程较繁琐,后续我们使用qemu虚拟机,可以直接在Linux环境下启动qemu;3. 随着项目的复杂,有必要调整目录结构,并调整Makefile.

  本讲没有过多讲解,看代码完全可以理解。本讲只是列出了部分代码,全部代码对应https://github.com/lucasysfeng/lucasOS上的code/chapter3.

清屏



  0xb8000h是显存开始的地址,因此打印就是操作0xb8000h开始的地址,从0xb8000h这个地址开始,每2个字节表示一个字符,前一个字节是字符的ASCII码,后一个字节是这个字符的颜色和属性。

  lib/kprint.c

// 一屏25行
#define LINE_COUNT 25
// 一行80个字符
#define LINE_LENGTH 80
// 字符颜色
#define COLOR 0x04

// 显存开始地址
static unsigned short *display_buf = (unsigned short *) 0xb8000;
// 字符属性
static const unsigned short char_attr = COLOR << 8;

// 当前光标的坐标
static unsigned char cursor_x = 0;
static unsigned char cursor_y = 0;

/**
 * 清屏
 */
void print_clear()
{
	unsigned int i;
	for (i = 0; i < LINE_COUNT * LINE_LENGTH; i++)
	{
		display_buf[i] = 0x20 | char_attr;
	}

	cursor_x = 0;
	cursor_y = 0;
}

  

打印字符


/**
 * 打印一个字符(为简化逻辑,某些特殊字符均作为换行符处理)
 */
void print_char(const char c)
{
	if (c >= ‘ ‘)
	{
		display_buf[cursor_y * LINE_LENGTH + cursor_x] = c | char_attr;
		cursor_x++;
	}
	else
	{
		cursor_x = 0;
		cursor_y++;
	}

	// 每行80个字符,满80个字符换行
	if (cursor_x >= 80)
	{
		cursor_x = 0;
		cursor_y++;
	}

	scroll();  // 满一屏时,向上滚屏
}

打印字符串



  调用打印字符函数。

/**
 * 打印以\0结尾的字符串
 */
void print_str(const char* str)
{
	while (*str)
	{
		print_char(*str++);
	}
}

内核入口



  print_dec()   print_hex()在github上,此处没给出实现。

#include "kprint.h"

int kernel_main()
{
    print_clear();

    print_str("hello world, print is OK\n");
    print_dec(123);
    print_char(‘\n‘);
    print_dec(-123);
    print_char(‘\n‘);
    print_hex(11);

    return 0;
}

编译和运行



  我们使用qemu启动虚拟机,所以先要安装qemu,qemu的安装和使用此处略。

$ make

$ make qemu

  make后会生成kernel内核,并将内核拷贝到lucasOS.img中,运行make qemu就会加载lucasOS.img,并出现下面窗口,表示成功了:        

代码获取



  本系列GitHub地址 https://github.com/lucasysfeng/lucasOS,本讲的代码是code/chapter3.

  上一讲

跟我一起写操作系统(三)——打印函数和qemu虚拟机

时间: 2024-12-06 13:12:29

跟我一起写操作系统(三)——打印函数和qemu虚拟机的相关文章

awk(三)函数

函数是一个独立计算的过程,它接收一些参数并返回一些值 awk有很多内置函数,分为:算术函数和字符串函数 算术函数 cos(x) 返回x的余弦(x为弧度) exp(x) 返回e的x次幂 int(x) 返回x的整数部分的值 log(x) 返回x的自然对数(以e为底) sin(x) 返回x的正弦(x为弧度) sqrt(x) 返回x atan2(y,x) 返回y/x的反正切,其值在-180度到180度之间 rand() 返回随机数r,其中0<=r<1 srand(x) 建立rand()的新的种子数,如

20天自制操作系统(三)

我们看\projects\03_day\harib00j中的文件 ipl10.nas: 相当于一个boot源文件,它使用int 0x13 ah=0x2加载某些扇区的文件(loader+kernel)到内存0x从c200中 asmhead.nas:相当于一个loader源文件,作用是 1.设置VGA为320x200x8bit,并把这些参数保存起来 MOV AL,0x13 ; VGA 320x200x8bit MOV AH,0x00 INT 0x10 MOV BYTE [VMODE],8 MOV W

定制自己的打印函数---初级篇

平时在Linux平台写代码的时候,虽然gdb的调试功能很强大,但很多时候我更喜欢调用系统打印函数来调试我的程序,可是直接调用的话难免显得很愚蠢(中国好像就是不缺愚蠢的coder),除非我需要打印的地方不超过3处,否则我是绝对无法容忍的,可是应该怎么做呢,别急,先去倒杯白开水,然后随便泡点什么,再坐下来一步一步慢慢的整理. 首先要先明确自己的需求,限于是初级篇,所以我设定的需求是: 可以像系统打印函数一样打印信息: 使用上不能比系统打印函数更复杂: 可以自动输出打印信息的具体位置: 具备统一开启和

一步一步写算法(之函数堆栈显示)

原文:一步一步写算法(之函数堆栈显示) [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com ] 在继续图的讨论之前,我们今天开个小差,讨论一下函数堆栈的基本原理.有过编程经验的朋友都知道,堆栈调试是我们在程序开发中经常应用的一个功能.那么大家有没有想过,函数堆栈是怎么开始的啊?其实我们可以自己写一个函数堆栈输出函数分析一下. 因为一般来说,函数的压栈过程是这样的: |    参数三  | |    参数二  | |    参数一  | |  

面试官:能解释一下javascript中bind、apply和call这三个函数的用法吗

一.前言    不知道大家还记不记得前几篇的文章:<面试官:能解释一下javascript中的this吗> 那今天这篇文章虽然是介绍javascript中bind.apply和call函数,但是多少也和this有点关联. 假如在前面那场面试末尾,面试官不依不饶继续问你javascript中的this,那看完本篇文章后一定还会有收获. (本篇文章不会站在this的角度去回答问题,而是重于解释bind.apply和call这三个函数的用法和使用场景) 二.正戏开始 面试官:能解释一下javascr

[C++] 用Xcode来写C++程序[4] 函数

用Xcode来写C++程序[4] 函数 此节包括引用函数,内联函数,防止修改函数入参,函数自身带有默认值. 引用函数:防止复制对象,减少系统开销 内联函数:编译的时候根据具体情形将代码嵌入进去,成不成功编译器说了算,减少系统开销提升性能 引用函数(防止篡改初始值的入参声明方式):防止修改数据源 函数参数带有默认值:函数的某个参数可以给定默认值,精简函数的使用 最简单的函数 #include <iostream> using namespace std; int addition (int a,

[C++] 用Xcode来写C++程序[5] 函数的重载与模板

用Xcode来写C++程序[5] 函数的重载与模板 此节包括函数重载,隐式函数重载,函数模板,带参数函数模板 函数的重载 #include <iostream> using namespace std; int operate (int a, int b) { return (a * b); } double operate (double a, double b) { return (a / b); } int main () { int x = 5; int y = 2; double n

php+mssql 已经写好的万能函数

<?php /************************************************************************************************** | 类名:databaseClass | 功能描述:操作数据库.内有函数link_array(),equation_array(),insert(),update(),delete(),query() | 初始化数据: $select(要操作的数据库名),$link(已经打开的一个数据库

Objective-C与Swift下的自定义打印函数(Debug和Release)

1.Objective-C 在使用Objective-C进行开发的过程中,为了Debug会不断的设置打印函数.如下图是我们经常用的,用来测试监听方法的实现与否: 1 NSLog(@"%s", __func__); 2 NSLog(@"%s", __FUNCTION__); 需要说明的是,__func__和__FUNCTION__都是C的预定义符号,代表的含义完全相同,就是返回 类名+方法名 的字符串. 注意:1.返回的字符串是C语言的字符串 char * 类型,注意