//在打印函数中,字符串常量定义为无符号常字符指针似乎是必须的(强制类型转换)
//但不知道原理为何!
//在变量转化为字符串的函数中,如果'/'为奇数个就很可能会出现显示乱码。
//看来是个棘手的问题,还是等到将来再解决吧!
extern "C" {
typedef unsigned int _u_i;
struct Draw{
static char buf[0xff];
static void fillbox(_u_i* fb, _u_i xsize, int color,
int x0, int y0, int x1, int y1);
static void drawfont(int color, int x, int y,
const unsigned char *str);
static void myprintf(char* buf, const char* s, ...);
private:
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 int mydiv(int* n,unsigned int b);
static void myitoa(char* buf, int n, unsigned int b);
static int mystrlen(char* s);
static int sign;
static char mybuf[0xff];
};
int mymain(int eax, int ebx);
}
char Draw::buf[] = {0,};
int Draw::sign = 0;
char Draw::mybuf[] = {0,};
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 Draw::mystrlen(char* s){
int len = 0;
while(*s++){
len++;
}
return len;
}
int Draw::mydiv(int* n, unsigned int b){
int res;
res = *n % b;
*n /= b;
return res;
}
void Draw::myitoa(char* buf, int n, unsigned int b){
char s[] = "0123456789abcdef";
char tmpbuf[0xff];
char* tmp = tmpbuf;
if(n < 0){
sign = -1;
n = -n;
}
while(n){
*tmp++ = s[Draw::mydiv(&n, b)];
}
*tmp = '\0';
for(int i = mystrlen(tmpbuf) - 1; i >= 0 ; i--) {
*buf++ = tmpbuf[i];
}
*buf = '\0';
}
void Draw::myprintf(char* buf, const char* s, ...){
void** varg = (void**)&s;
varg++;
char* tmp;
int n;
while(*s){
if('%' != *s){
if('\\' != *s){
*buf++ = *s++;
} else{
s++;
switch(*s){
case '\\':
*buf++ = '\\';
break;
case 'n':
case 't':
case 'b':
s++;
break;
}
}
} else {
s++;
switch(*s){
case '%':
s++;
*buf++ = '%';
break;
case 's':
s++;
tmp = (char*)*varg++;
while(*tmp){
*buf++ = *tmp++;
}
break;
case 'c':
s++;
tmp = (char*)varg++;
*buf++ = *tmp;
break;
case 'd':
case 'i':
s++;
n = (int)*varg++;
myitoa(Draw::mybuf, n, 10);
tmp = Draw::mybuf;
if(-1 == sign)
*buf++ = '-';
while(*tmp){
*buf++ = *tmp++;
}
break;
case 'x':
case 'X':
s++;
n = (int)*varg++;
myitoa(Draw::mybuf, n, 16);
tmp = Draw::mybuf;
*buf++ = '0';
*buf++ = 'x';
while(*tmp){
*buf++ = *tmp++;
}
break;
case 'b':
case 'B':
s++;
n = (int)*varg++;
myitoa(Draw::mybuf, n, 2);
tmp = Draw::mybuf;
while(*tmp){
*buf++ = *tmp++;
}
*buf++ = 'b';
break;
default:
break;
}
}
}
*buf = '\0';
return;
}
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, 319, (const unsigned char*)"庆幸的是我们的开发环境很好,能够让我们即是看到效果,开心^_^");
int i = 253;
char str[] = "Welcome to SnailOS! 测试变量。";
Draw::drawfont(0x0000ff00, 0, 15, (const unsigned char*)Draw::buf);
Draw::myprintf(Draw::buf, " %b \\\\ \\b %s \\n %x\\t", 0xff, str, i);
Draw::drawfont(0x00000000, 0, 31, (const unsigned char*)Draw::buf);
while(1) {
asm("hlt"::);
}
}
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:
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