SnailOS 这里算是坐上C++的列车了吗?

本文介绍了一个名为snailOS的操作系统内核的构建和启动过程,使用了汇编和C语言进行编程,涉及编译器配置、链接器脚本、启动代码和多引导规范2(Multiboot2)。内核能够显示中文字符并填充屏幕背景色。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

AS = as
C = g++
CF = -c
LD = ld
LDF = -Ttext 0x100000
OBJ = boot.o kernel.o ./font/myfont1.o ./font/myfont.o

default: $(OBJ)
	make boot.o
	make kernel.o

boot.o: boot.s
	$(AS) -o $@ $<
	
kernel.o: kernel.cpp
	$(C) $(CF) -o $@ $<
	
kernel:	$(OBJ)
	$(LD) $(LDF) -o kernel $(OBJ)
	objcopy -I pe-i386 -O elf32-i386 kernel
	mount.cmd
  
run: kernel
	make default
	start virtualbox --startvm "C:\Users\Administrator\VirtualBox VMs\snailOS\snailOS.vbox" 

clean:
	del *.o
	del kernel

	
	
MULTIBOOT2_HEADER_MAGIC = 0xe85250d6
GRUB_MULTIBOOT_ARCHITECTURE_I386 = 0x0
MULTIBOOT_HEADER_TAG_ADDRESS = 0x2
MULTIBOOT_HEADER_TAG_OPTIONAL = 0x1
MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS = 0x3
MULTIBOOT_HEADER_TAG_END = 0x0
MULTIBOOT_HEADER_TAG_FRAMEBUFFER = 0x5

.globl _start
.extern _mymain

_start:
	jmp multiboot_entry
.align 8

multiboot_header:
	.int MULTIBOOT2_HEADER_MAGIC
	.int GRUB_MULTIBOOT_ARCHITECTURE_I386
	.int multiboot_header_end - multiboot_header
	.int -(MULTIBOOT2_HEADER_MAGIC + GRUB_MULTIBOOT_ARCHITECTURE_I386 + (multiboot_header_end - multiboot_header))

.align 8
	
address_tag_start:
	.short MULTIBOOT_HEADER_TAG_ADDRESS
	.short MULTIBOOT_HEADER_TAG_OPTIONAL
	.int address_tag_end - address_tag_start
	.int multiboot_header
	.int _start
	.int 0x0
	.int 0x0
address_tag_end:

.align 8

entry_address_tag_start:
	.short MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS
	.short MULTIBOOT_HEADER_TAG_OPTIONAL
	.int entry_address_tag_end - entry_address_tag_start
	.int multiboot_entry
entry_address_tag_end:

.align 8

framebuffer_tag_start:
	.short MULTIBOOT_HEADER_TAG_FRAMEBUFFER
	.short MULTIBOOT_HEADER_TAG_OPTIONAL
	.int framebuffer_tag_end - framebuffer_tag_start
	.int 1024
	.int 768
	.int 32
framebuffer_tag_end:

.align 8

undefined_tag:
	.short MULTIBOOT_HEADER_TAG_END
	.short 0
	.int 8
	
multiboot_header_end:
.align 8
multiboot_entry:
	movl $stack, %esp
	pushl $0
	popf
	
	pushl %ebx
	pushl %eax
	
	call _mymain
	
1:
	hlt
	jmp 1b

.align 0x1000
.fill 0x1000, 1, 0
stack:
//在打印函数中,字符串常量定义为(强制类型转换)无符号常字符指针似乎是必须的
//但不知道原理为何!
extern "C" {	
	typedef unsigned int _u_i;
	struct Draw{
		static void fillbox(_u_i* fb, _u_i xsize, int color,
		int x0, int y0, int x1, int y1);
		static void makeascii(_u_i* fb, _u_i xsize, int color,
		int x, int y, char *font);
		static void makegb2312(_u_i* fb, _u_i xsize, int color,
		int x, int y, short *font);
		static void drawfont(int color, int x, int y,
		const unsigned char *str);
	};
	int mymain(int eax, int ebx);
}


void Draw::fillbox(_u_i* fb, _u_i xsize, int color,
			int x0, int y0, int x1, int y1) {
	int x, y;
	for (y = 0; y <= y1 - y0; y++) {
		for (x = 0; x <= x1 - x0; x++) {
			fb[x0 + x + (y0 + y) * xsize] = color;
		}
	}
}


void Draw::makeascii (_u_i* fb, _u_i xsize, int color,
			int x, int y, char *font) {
	char d;
	_u_i* p;
	int i;
	for (i = 0; i < 16; i++){
		p = (_u_i*)fb + (y + i) * xsize + x;
		d = font[i];
		if ((d & 0x80) != 0) {p[0] = color;}
		if ((d & 0x40) != 0) {p[1] = color;}
		if ((d & 0x20) != 0) {p[2] = color;}
		if ((d & 0x10) != 0) {p[3] = color;}
		if ((d & 0x08) != 0) {p[4] = color;}
		if ((d & 0x04) != 0) {p[5] = color;}
		if ((d & 0x02) != 0) {p[6] = color;}
		if ((d & 0x01) != 0) {p[7] = color;}
	}
}

void Draw::makegb2312 (_u_i* fb, _u_i xsize, int color,
			int x, int y, short *font) {
	short d;
	_u_i* p;
	int i;
	for (i = 0; i < 16; i++){
		p = (_u_i*)fb + (y + i) * xsize + x;
		d = font[i];
		if ((d & 0x80) != 0) {p[0] = color;}
		if ((d & 0x40) != 0) {p[1] = color;}
		if ((d & 0x20) != 0) {p[2] = color;}
		if ((d & 0x10) != 0) {p[3] = color;}
		if ((d & 0x08) != 0) {p[4] = color;}
		if ((d & 0x04) != 0) {p[5] = color;}
		if ((d & 0x02) != 0) {p[6] = color;}
		if ((d & 0x01) != 0) {p[7] = color;}
		if ((d & 0x8000) != 0) {p[8] = color;}
		if ((d & 0x4000) != 0) {p[9] = color;}
		if ((d & 0x2000) != 0) {p[10] = color;}
		if ((d & 0x1000) != 0) {p[11] = color;}
		if ((d & 0x800) != 0) {p[12] = color;}
		if ((d & 0x400) != 0) {p[13] = color;}
		if ((d & 0x200) != 0) {p[14] = color;}
		if ((d & 0x100) != 0) {p[15] = color;}
	}
}

void Draw::drawfont(int color, int x, int y, const unsigned char *str) {
	extern short font[0x8000];
	extern char myfont[0x1000];
	int i = 0, j = 0;
	unsigned char a, b;
	unsigned int offset;
	while (str[i] != 0) {
		if (str[i] < 0x80) {
			a = str[i];
			Draw::makeascii((_u_i*)0xe0000000, 1024, color, x + j, y, myfont + a * 16);
			if (str[i + 1] == 0)
				break;
			i++;
			j += 8;
		} else {	
			a = str[i] - 0xa0;
			b = str[i + 1] - 0xa0;
			offset = ((a - 1) * 94 + (b - 1)) * 16;
			Draw::makegb2312((_u_i*)0xe0000000, 1024, color, x + j , y, font + offset);
			i += 2;
			j += 16;
		}
	}
}

int mymain(int eax, int ebx) {
	Draw::fillbox((_u_i*)0xe0000000, 1024, 0x1e90ff, 0, 0, 1024 - 1, 768 - 1);
	Draw::drawfont(0xffffffff, 0, 0, (const unsigned char*)"我爱你!snailOS!");
	Draw::drawfont(0x00ff0000, 160, 320, (const unsigned char*)"庆幸的是我们的开发环境很好,能够让我们即是看到效果,开心^_^");
	while(1) {
		asm("hlt"::);
	}
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_39410618

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值