Code: Select all
/* boot.asm */
[bits 16] ;asign to 16bit CPU
[org 0x7c00] ;origin start point
[section .text]
jmp start
;Data
BootTitle db 'OS BootLoader x16 07122012 - Loading in Real Mode ...',13,10,0
start:
mov ax, 0x0000 ;asignning a 0 address to ax for data segment address
mov ds, ax ;move the address 0x0000 to data segment register
mov si, BootTitle ;moving the String data to String interrupts register preper to print out
call printString ;call print out method
call reset_drive ;load kernel
;;Read GDT
cli
pusha ;Save registers
lgdt [gdt_desc] ;Load GDT Descriptor
sti ;enable interrupts
popa ;Pop/restore registers
;;Setup a stack
cli
mov ax, 0x0000
mov ss, ax
mov sp, 0x7C00
sti
jmp 0:0xEFFF ;code selector is 8 , goto loader position EFFFh
hlt ;Stop CPU moving
;-----------------------------------------------------------------------------------------------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Set GDT
;If you write wrong any word
;means you will die for debugging
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; GDT:
;00000000 00000000 00000000 00000000 00000000 00000000 ;GDT_Null
;11111111 00000000 00000000 10011010 11001111 00000000 ;GDT_Code
;11111111 00000000 00000000 10010010 11001111 00000000 ;GDT_Data
gdt: ;making Global Description Table
;first is null segment description
;then is code segment
;and the last is data segment
gdt_null: ;Null Segment
dd 0 ;all 64bits 0
dd 0 ;
gdt_code: ;Code Segment description
dw 0FFFFh ;16 bits
dw 0 ;16 bits
db 0 ;8 bits
db 10011010b ;8 bits
db 11001111b ;8 bits
db 0 ;8 bits
gdt_data: ;Data Segment description
dw 0FFFFh
dw 0
db 0
db 10010010b ;number 4 bit will change to 0 mean data segment description
db 11001111b
db 0
gdt_end:
gdt_desc:
dw gdt_end - gdt - 1
dd gdt
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;Startup Drive
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
reset_drive: ;reset floppy drive
mov ah, 0x00 ;
int 0x13 ;floppy drive interrupt
or ah, ah ;if it's 0(return code)
jnz reset_drive ;jump back
mov ax, 0 ;
mov es, ax ;reset extended segment
mov bx, 0xEFFF ;set kernel location to 0000:EFFF(ES:BX)
mov ah, 0x02 ;commend - "read sector from disk"
mov al, 0x02 ;Number of sectors need to read
mov ch, 0 ;disk cylinder
mov cl, 0x02 ;set sector (0x01 is bootloader)
mov dh, 0 ;disk head
int 0x13 ;call floppy drive interrupt
or ah, ah ;check error
jnz reset_drive
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;String printing
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
printString: ;method (printString)
pusha
mov ah, 0x0E ;asignning 0x0E(video display) instruction to ah(accumulator register)
mov bh, 0x00 ;asignning page no (default is 0x00)
mov bl, 0x07 ;asignning text color (07 = White)
;
;FULL string display in 16bits
;AX(AH+AL) 0x0E?? <-- adding to register, not yet execute (int)
; | |-Means ACSII code (XY) X = bg color Y = Text Color (16bit)
; |---Means Display
;
;BX(BH+BL) 0x00?? <-- adding to register, means display usage
; | |-Means front color (Can't display without no color
; |---Means Page no (Default is page 0)
;
;int 0x10 <------------ interrupt address (execute)
; |------ 0x10 is display port address services
;
.getChar:
;lodsb ;load a string block 'x''y''z' = "xyz" (LOaD String Block)
;load a put it into AL register
mov al,[si] ;get data from pointer of source index ;This method same as using lodsb
inc si ;si check location + 1 ;
or al,al ;or gate (if-or)
jz .return ;jump if the or gate returns 0
int 0x10 ;interrupt the Video Display instruction
jmp .getChar ;loop if bytes not equals to 0
.return:
popa
ret ;return method back to main
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
times 510-($-$$) db 0 ;for boot loader size MUST be 512bytes
;adding bytes with 0 to increase the size of file
dw 0xAA55 ;BOOT sign
Code: Select all
/* loader.asm */
[bits 16]
[org 0xEFFF]
jmp start
start:
mov al, 'J' ;Jump to kernel
call printChar
mov al, 'u'
call printChar
mov al, 'm'
call printChar
mov al, 'p'
call printChar
mov al, ' '
call printChar
mov al, 't'
call printChar
mov al, 'o'
call printChar
mov al, ' '
call printChar
mov al, 'k'
call printChar
mov al, 'e'
call printChar
mov al, 'r'
call printChar
mov al, 'n'
call printChar
mov al, 'e'
call printChar
mov al, 'l'
call printChar
mov al, 13
call printChar
mov al, 10
call printChar
;;;;;;;;;;;;;;;;;;;;;;;
;Switch PMode
;;;;;;;;;;;;;;;;;;;;;;;
mov eax, cr0 ;move cr0(including protected mode instruction) to eax for checking
or eax, 1 ;checking al(2bits) 0001b
mov cr0, eax ;giving back
jmp 08:loadBit ;jump to 32bit kernel loader
;;;;;;;;;;;;;;;;;;;;;;
;Print Char
;;;;;;;;;;;;;;;;;;;;;;
printChar:
mov ah, 0x0E ;instruction of 0x10 (display char)
mov bx, 0x0007 ;00 = page 07 = black color bg and white text
int 0x10 ;interrupt display code
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;String printing
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
printString: ;method (printString)
pusha
mov ah, 0x0E ;asignning 0x0E(video display) instruction to ah(accumulator register)
mov bh, 0x00 ;asignning page no (default is 0x00)
mov bl, 0x07 ;asignning text color (07 = White)
;
;FULL string display in 16bits
;AX(AH+AL) 0x0E?? <-- adding to register, not yet execute (int)
; | |-Means ACSII code (XY) X = bg color Y = Text Color (16bit)
; |---Means Display
;
;BX(BH+BL) 0x00?? <-- adding to register, means display usage
; | |-Means front color (Can't display without no color
; |---Means Page no (Default is page 0)
;
;int 0x10 <------------ interrupt address (execute)
; |------ 0x10 is display port address services
;
.getChar:
;lodsb ;load a string block 'x''y''z' = "xyz" (LOaD String Block)
;load a put it into AL register
mov al,[si] ;get data from pointer of source index ;This method same as using lodsb
inc si ;si check location + 1 ;
or al,al ;or gate (if-or)
jz .return ;jump if the or gate returns 0
int 0x10 ;interrupt the Video Display instruction
jmp .getChar ;loop if bytes not equals to 0
.return:
popa
ret ;return method back to main
;================================================================================
;================================================================================
[bits 32]
loadBit:
mov ax, 10h ;reset segment to 10h (data selector)
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
call enable_A20
mov word [es: 0xb8000],'P' ;Protected Mode
mov word [es: 0xb8001],02h
mov word [es: 0xb8002],'M'
mov word [es: 0xb8003],02h
mov word [es: 0xb8004],'o'
mov word [es: 0xb8005],02h
mov word [es: 0xb8006],'d'
mov word [es: 0xb8007],02h
mov word [es: 0xb8008],'e'
mov word [es: 0xb8009],02h
jmp 8:10000h ;long jump to 1M offset
hlt
enable_A20:
cli
call a20wait
mov al,0xAD
out 0x64,al
call a20wait
mov al,0xD0
out 0x64,al
call a20wait2
in al,0x60
push eax
call a20wait
mov al,0xD1
out 0x64,al
call a20wait
pop eax
or al,2
out 0x60,al
call a20wait
mov al,0xAE
out 0x64,al
call a20wait
sti
ret
a20wait:
in al,0x64
test al,2
jnz a20wait
ret
a20wait2:
in al,0x64
test al,1
jz a20wait2
ret
Code: Select all
/* kernel */
[bits 32]
[org 0x100000]
[global start]
[section .text]
;[extern k_main]
jmp start
start:
mov word [es: 0xb8000],'K' ;Kernel Mode
mov word [es: 0xb8001],02h
mov word [es: 0xb8002],'M'
mov word [es: 0xb8003],02h
mov word [es: 0xb8004],'o'
mov word [es: 0xb8005],02h
mov word [es: 0xb8006],'d'
mov word [es: 0xb8007],02h
mov word [es: 0xb8008],'e'
mov word [es: 0xb8009],02h
mov word [es: 0xb800A],'-'
mov word [es: 0xb800B],02h
mov word [es: 0xb800C],'x'
mov word [es: 0xb800D],02h
;call k_main
hlt
and mix it up (cat boot.bin loader.bin kernel.bin >> System.img )
the result is the program goes to the second file (loader.asm) but can't access the kernel through 0x100000
The file of boot.asm is in real mode which read the gdt table, and the loader.asm is activate the protected mode and enable A20 gate
finally the bottom of the file which is start the far jump into the kernel
Did I miss something? I have copied the log file from Bochs but I'm not so understand
Code: Select all
00105666114i[BIOS ] Booting from 0000:7c00
00105705543i[FDD ] partial read() on floppy image returns 328/512
00105749989i[FDD ] read() on floppy image returns 0
00105871500e[CPU0 ] load_seg_reg(ES, 0xffff): invalid segment
00105871500e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
00105871500e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
00105871500i[CPU0 ] CPU is in protected mode (active)
00105871500i[CPU0 ] CS.mode = 32 bit
00105871500i[CPU0 ] SS.mode = 32 bit
00105871500i[CPU0 ] EFER = 0x00000000
00105871500i[CPU0 ] | EAX=60000018 EBX=00000007 ECX=ffffffff EDX=00000000
00105871500i[CPU0 ] | ESP=00007bec EBP=00007bfc ESI=000e7c02 EDI=0000ffac
00105871500i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df IF tf sf zf AF PF CF
00105871500i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00105871500i[CPU0 ] | CS:0008( 0001| 0| 0) 00000000 ffffffff 1 1
00105871500i[CPU0 ] | DS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00105871500i[CPU0 ] | SS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00105871500i[CPU0 ] | ES:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00105871500i[CPU0 ] | FS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00105871500i[CPU0 ] | GS:0010( 0002| 0| 0) 00000000 ffffffff 1 1
00105871500i[CPU0 ] | EIP=0003000c (0003000c)
00105871500i[CPU0 ] | CR0=0x60000011 CR2=0x00000000
00105871500i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00105871500i[CPU0 ] 0x000000000003000c>> les edi, ds:[esi+6] : C47E06
00105871500e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00105871500i[SYS ] bx_pc_system_c::Reset(HARDWARE) called
00105871500i[CPU0 ] cpu hardware reset