I believe I have set up the GDT correctly like this:
# 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 "\r\n\n\rmy kernel is runing jos"
try:
.asciz "\r\n\n\rtry 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
Jump to C part of code like this:
.code32 # Assemble for 32-bit mode
protcseg:
# Set up the protected-mode data segment registers
movw 0x10, %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
C code like following:
#define io_halt() asm("hlt")
#define write_mem8(addr,data8) (*(volatile char *)(addr))=(char)data8
void color_screen(char color) // 15:pure white
{
int i;
color = color;
for (i = 0xa0000; i < 0xaffff; i++)
{
write_mem8(i, i & 0x0f); // if we write 15 ,all pixels color will be white,15 mens pure white ,so the screen changes into white
}
}
void bootmain(void)
{
color_screen(3);
}
Screen was displaying strips different colors.
My question is, GDT first segment 8 bytes is null, second segment is code segment, third segment is data segment.
After I386 went into protect mode, why load DS with third segment value 0x10?
To display something write to address 0xa0000, how the address 0xa0000 relate to protect mode? Looks like 0xa0000 is a real address in display card, if I do not init protect mode, direct write this address, will the display still work?