30天自制操作系统-day7
这次我们更改main.c以及相关文件,生成彩色条纹,与上次彩色条纹区分开
main.c
#include<header.h>
void bootmain(void){
//注意这里的函数名字为bootmain,因为在entry.S中设定的入口名字也是bootmain,两者要保持一致
int i;
char *p;
init_palette();
for(i=0xa0000; i<=0xaffff; i++){
//write_mem8(i, i&0x0f);
p=(char *)i;
*p=i&0x0f;
}
for(;;){
io_halt();
}
}
header.h
#ifndef header
#define header
#include <x86.h>
#define io_halt() asm("hlt")
#define write_mem8(addr,data8) (*(volatile char *)(addr))=(char)data8
#define io_cli() asm("cli") //!!!本次添加部分
#define io_sti() asm("sti")//!!!本次添加部分
extern void clear_screen(char color) ; //color=15 pure white color=40 red
extern void color_screen(char color) ;
extern void init_palette(void);
extern void set_palette(int start, int end, unsigned char *rgb);
#endif
entry.s
#include <mmu.h>
# Start the CPU: switch to 32-bit protected mode, jump into C.
# The BIOS loads this code from the first sector of the hard disk into
# memory at physical address 0x7c00 and starts executing in real mode
# with %cs=0 %ip=7c00.
#define CYLS 0x0ff0
#define LEDS 0x0ff1
#define VMODE 0x0ff2
#define SCRNX 0x0ff4
#define SCRNY 0x0ff6
#define VRAM 0x0ff8
.set PROT_MODE_CSEG, 0x8 # kernel code segment selector
.set PROT_MODE_DSEG, 0x10 # kernel data segment selector
.set CR0_PE_ON, 0x1 # protected mode enable flag
.globl start
start:
.code16 # Assemble for 16-bit mode
# Set up the important data segment registers (DS, ES, SS).
xorw %ax,%ax # Segment number zero
movw %ax,%ds # -> Data Segment
movw %ax,%es # -> Extra Segment
movw %ax,%ss # -> Stack Segment
movb $0x13,%al # ;vga 320x200x8 位,color mode
movb $0x00,%ah
int $0x10
#save color mode in ram 0x0ff0
movb $8,(VMODE)
movw $320,(SCRNX)
movw $200,(SCRNY)
movl $0x000a0000,(VRAM)
#get keyboard led status
movb $0x02,%ah
int $0x16 #keyboard interrupts
movb %al,(LEDS)
#diplay something
movw $msg,%si
call puts
movw $try,%si
call puts
#jmp .
cli # Disable interrupts
cld # String operations increment
# Enable A20:
# For backwards compatibility with the earliest PCs, physical
# address line 20 is tied low, so that addresses higher than
# 1MB wrap around to zero by default. This code undoes this.
seta20.1:
inb $0x64,%al # Wait for not busy
testb $0x2,%al
jnz seta20.1
movb $0xd1,%al # 0xd1 -> port 0x64
outb %al,$0x64
seta20.2:
inb $0x64,%al # Wait for not busy
testb $02,%al
jnz seta20.2
movb $0xdf,%al # 0xdf -> port 0x60
outb %al,$0x60
# Switch from real to protected mode, using a bootstrap GDT this is vip ,but i don`t know it clearly now
# and segment translation that makes virtual addresses
# identical to their physical addresses, so that the
# effective memory map does not change during the switch.
lgdt gdtdesc
movl %cr0, %eax
orl $CR0_PE_ON, %eax
movl %eax, %cr0
# Jump to next instruction, but in 32-bit code segment.
# Switches processor into 32-bit mode.
ljmp $PROT_MODE_CSEG, $protcseg
msg:
.asciz "
my kernel is runing jos"
try:
.asciz "
try it again"
puts:
movb (%si),%al
add $1,%si
cmp $0,%al
je over
movb $0x0e,%ah
movw $15,%bx
int $0x10
jmp puts
over:
ret
.code32 # Assemble for 32-bit mode
protcseg:
# Set up the protected-mode data segment registers
movw $PROT_MODE_DSEG, %ax # Our data segment selector
movw %ax, %ds # -> DS: Data Segment
movw %ax, %es # -> ES: Extra Segment
movw %ax, %fs # -> FS
movw %ax, %gs # -> GS
movw %ax, %ss # -> SS: Stack Segment
# Set up the stack pointer and call into C.
movl $start, %esp
call bootmain
# If bootmain returns (it shouldn't), loop.
spin:
jmp spin
# Bootstrap GDT
.p2align 2 # force 4 byte alignment
gdt:
SEG_NULL # null seg
SEG(STA_X|STA_R, 0x0, 0xffffffff) # code seg
SEG(STA_W, 0x0, 0xffffffff) # data seg
gdtdesc:
.word 0x17 # sizeof(gdt) - 1
.long gdt # address gdt
#.fill 310
screen.c
#include<header.h>
void clear_screen(char color) //15:pure white
{
int i;
for(i=0xa0000;i<0xaffff;i++)
{
write_mem8(i,color);
}
}
void color_screen(char color) //15:pure white
{
int i;
color=color;
for(i=0xa0000;i<0xaffff;i++)
{
write_mem8(i,i&0x0f);
}
}
void set_palette(int start, int end, unsigned char* rgb){
int i, eflags;
eflags = read_eflags(); //替代作者的io_load_eflags()
io_cli();
outb(0x03c8, start); //替代作者的io_out8()
for(i=start; i<=end; i++){
outb(0x03c9,rgb[0]/4);
outb(0x03c9,rgb[1]/4);
outb(0x03c9,rgb[2]/4);
rgb+=3;
}
write_eflags(eflags); //替代作者的io_store_eflags(eflags)
return;
}
void init_palette(void){
//16种color,每个color三个字节。
static unsigned char table_rgb[16*3]=
{
0x00,0x00,0x00, /*0:black*/
0xff,0x00,0x00, /*1:light red*/
0x00,0xff,0x00, /*2:light green*/
0xff,0xff,0x00, /*3:light yellow*/
0x00,0x00,0xff, /*4:light blue*/
0xff,0x00,0xff, /*5:light purper*/
0x00,0xff,0xff, /*6:light blue*/
0xff,0xff,0xff, /*7:white*/
0xc6,0xc6,0xc6, /*8:light gray*/
0x84,0x00,0x00, /*9:dark red*/
0x00,0x84,0x00, /*10:dark green*/
0x84,0x84,0x00, /*11:dark yellow*/
0x00,0x00,0x84, /*12:dark 青*/
0x84,0x00,0x84, /*13:dark purper*/
0x00,0x84,0x84, /*14:light blue*/
0x84,0x84,0x84, /*15:dark gray*/
};
set_palette(0,15,table_rgb);
return;
}
kernel/makefile
addr=0x7c00
OBJDIR=.
CFLAGS := $(CFLAGS) -O1 -fno-builtin -I$(OBJDIR) -MD
CFLAGS += -fno-omit-frame-pointer
CFLAGS += -Wall -Wno-format -Wno-unused -Werror -gstabs -m32
LDFLAGS=-m elf_i386
all:kernel
kernel:entry.o main.o screen.o
ld $(LDFLAGS) -N -e start -Ttext $(addr) -o $@.out $^
objdump -S $@.out >$@.asm
# objcopy -S -O binary -j .text $@.out $@
objcopy -S -O binary $@.out $@
entry.o:entry.S
gcc -nostdinc $(CFLAGS) -c -o $@ $<
main.o:main.c
gcc -nostdinc $(CFLAGS) -Os -c -o $@ $<
screen.o:screen.c
gcc -nostdinc $(CFLAGS) -c -o $@ $<
run:
qemu-system-i386 -drive file=kernel,if=floppy
clean:
@rm -f entry.o main.o screen.o kernel.out kernel.asm kernel *.d