Yes,
Now it is one step ahead
A little kernel (sorry it is not right to call it a kernel) program that goes to protected mode, and prints a string. Done using nasm and c . Here it is
%define CS_ACCES 10011011b
%define DS_ACCES 10010011b
[bits 16]
[org 0x0] ; Begins at 0x0:Whatever you define next
jmp boot
%include "GDT.INC"
boot:
mov ax,0x07C0 ; Define the beginning of boot at 0x0000:0x07c0
mov ds,ax
mov es,ax
mov ax,0x8000 ; Define Stack
mov ss,ax
mov sp,0xf000 ; Stack begins at 0xf000 and fills from there
; Read the kernel binary from floppy to your memory location
; at 0x100:0x0000
; In real mode 0x7c00 = 0x7c0:0 or 0x7c0:0 = 0x07c0 shifted left once + 0
; so 0x1000 = 0x100:0 = 0x0100 shifted left once + 0
; 0x1000 = es, 0x0000 = bx
; First restart the motor
xor ax,ax
int 0x13
push es ; es has stack defined
mov ax,0x100
mov es,ax
mov bx,0
mov ah,2
mov al,30
mov ch,0
mov cl,2
mov dh,0
mov dl,0
int 0x13
pop es; Now es holds stack addresss
; Fill in the GDT now, before doing the lgdt
; Because GDT is all 0's now
descInit 0,0xFFFFF,CS_ACCES,1101b,gdt_cs
descInit 0,0xFFFFF,DS_ACCES,1101b,gdt_ds
; Before doing lgdt, we must supply two parameters to lgdt
; One is the limit, and the other is the linear address of GDT
; Refer to the GDT structure below
; Size of gdt = gdtend - gdt
mov ax, gdtend
mov bx, gdt
sub ax,bx
mov word [gdtptr], ax
; Linear address
xor ax,ax ; Clear eax
mov ax,ds ; Move segment 0x7c0 to ax
mov bx,gdt; Move offset to bx
call calcadr; Calculate linear address and store it in ecx
mov dword [gdtptr+2], ecx ; Move it to gdtptr
; Load gdt using lgdt. Disable interrupts before that
cli
lgdt[gdtptr]
; Move to protected mode. Set cr0's first bit to 1 by oring it
mov eax,cr0
or ax,1
mov cr0,eax
; Re define segments and offsets in protected mode
; cs -> as defined by gdt ie., using jmp instruction
; Define ds -> as the pointer to the data segment register's
; displacement with gdt, ie 0x10
jmp next
next:
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax ; Stack also begins at data segment
mov esp,0x9f000 ; Stack begins filling at this address
; code segment pointed by cs register at a displacement of 0x8 bytes
; from the beginning of gdt
; Now jump to the location of kernel binary w.r.t. code segment
; protected mode segmented address = cs:0x1000
jmp dword 0x8:0x1000
end:
jmp end ; Just in case it slips the earlier step !
; Definition of Zeroed out GDT
; GDT initially has 0's in all places
; GDT has 3, 8 byte segment descriptors defined
; The three are, NULL, Code segment and Data segment descriptor
; Remember the following are all variables
gdt:
gdt_null:
dw 0,0,0,0
gdt_cs:
dw 0,0,0,0
gdt_ds:
dw 0,0,0,0
gdtend:
; gdtptr is supposed to be passed to lgdt. It has been zeroed in the beginning
gdtptr:
dw 0x0000 ; 16 bit size of GDT
dd 0 ; 32 bit linear address of GDT
; Fill the rest of 510 bytes with NOP (0x144)
times 510-($-$$) db 144
dw 0xaa55 ; The signature of boot sector
void _start(void) {
main();
}
int main(void){
unsigned char *video = (unsigned char *) 0xb8000;
char *string = "Kernel loaded";
while (*string !=0)
{
*video = *string;
*video++;
*video = 0x07;
*video++;
*string++;
};
while(1);
}
compile as
nasm -f bin -o boot boot.asm
gcc -w -c kernel.c -o kernel.o
ld -Ttext 0x1000 --oformat binary kernel.o -o kernel
cat boot kernel >
use bochs and boot
Now it is one step ahead
A little kernel (sorry it is not right to call it a kernel) program that goes to protected mode, and prints a string. Done using nasm and c . Here it is
%define CS_ACCES 10011011b
%define DS_ACCES 10010011b
[bits 16]
[org 0x0] ; Begins at 0x0:Whatever you define next
jmp boot
%include "GDT.INC"
boot:
mov ax,0x07C0 ; Define the beginning of boot at 0x0000:0x07c0
mov ds,ax
mov es,ax
mov ax,0x8000 ; Define Stack
mov ss,ax
mov sp,0xf000 ; Stack begins at 0xf000 and fills from there
; Read the kernel binary from floppy to your memory location
; at 0x100:0x0000
; In real mode 0x7c00 = 0x7c0:0 or 0x7c0:0 = 0x07c0 shifted left once + 0
; so 0x1000 = 0x100:0 = 0x0100 shifted left once + 0
; 0x1000 = es, 0x0000 = bx
; First restart the motor
xor ax,ax
int 0x13
push es ; es has stack defined
mov ax,0x100
mov es,ax
mov bx,0
mov ah,2
mov al,30
mov ch,0
mov cl,2
mov dh,0
mov dl,0
int 0x13
pop es; Now es holds stack addresss
; Fill in the GDT now, before doing the lgdt
; Because GDT is all 0's now
descInit 0,0xFFFFF,CS_ACCES,1101b,gdt_cs
descInit 0,0xFFFFF,DS_ACCES,1101b,gdt_ds
; Before doing lgdt, we must supply two parameters to lgdt
; One is the limit, and the other is the linear address of GDT
; Refer to the GDT structure below
; Size of gdt = gdtend - gdt
mov ax, gdtend
mov bx, gdt
sub ax,bx
mov word [gdtptr], ax
; Linear address
xor ax,ax ; Clear eax
mov ax,ds ; Move segment 0x7c0 to ax
mov bx,gdt; Move offset to bx
call calcadr; Calculate linear address and store it in ecx
mov dword [gdtptr+2], ecx ; Move it to gdtptr
; Load gdt using lgdt. Disable interrupts before that
cli
lgdt[gdtptr]
; Move to protected mode. Set cr0's first bit to 1 by oring it
mov eax,cr0
or ax,1
mov cr0,eax
; Re define segments and offsets in protected mode
; cs -> as defined by gdt ie., using jmp instruction
; Define ds -> as the pointer to the data segment register's
; displacement with gdt, ie 0x10
jmp next
next:
mov ax,0x10
mov ds,ax
mov es,ax
mov fs,ax
mov gs,ax
mov ss,ax ; Stack also begins at data segment
mov esp,0x9f000 ; Stack begins filling at this address
; code segment pointed by cs register at a displacement of 0x8 bytes
; from the beginning of gdt
; Now jump to the location of kernel binary w.r.t. code segment
; protected mode segmented address = cs:0x1000
jmp dword 0x8:0x1000
end:
jmp end ; Just in case it slips the earlier step !
; Definition of Zeroed out GDT
; GDT initially has 0's in all places
; GDT has 3, 8 byte segment descriptors defined
; The three are, NULL, Code segment and Data segment descriptor
; Remember the following are all variables
gdt:
gdt_null:
dw 0,0,0,0
gdt_cs:
dw 0,0,0,0
gdt_ds:
dw 0,0,0,0
gdtend:
; gdtptr is supposed to be passed to lgdt. It has been zeroed in the beginning
gdtptr:
dw 0x0000 ; 16 bit size of GDT
dd 0 ; 32 bit linear address of GDT
; Fill the rest of 510 bytes with NOP (0x144)
times 510-($-$$) db 144
dw 0xaa55 ; The signature of boot sector
void _start(void) {
main();
}
int main(void){
unsigned char *video = (unsigned char *) 0xb8000;
char *string = "Kernel loaded";
while (*string !=0)
{
*video = *string;
*video++;
*video = 0x07;
*video++;
*string++;
};
while(1);
}
compile as
nasm -f bin -o boot boot.asm
gcc -w -c kernel.c -o kernel.o
ld -Ttext 0x1000 --oformat binary kernel.o -o kernel
cat boot kernel >
use bochs and boot