30天自制操作系统-day7

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
效果如下:

源码链接:https://github.com/zchrissirhcz/osask-linux.git

原文地址:https://www.cnblogs.com/wangdongfang/p/14364994.html