그래서 간단한 OS를 구축하고 부팅 섹터에서 커널 코드를 호출 할 때 위에 언급 한 오류가 발생합니다. 나는 고생하고 며칠 동안 고생했다.load_seg_reg (ES, 0xfffc) : 부팅 섹터에서 커널 코드를 실행할 때 세그먼트가 올바르지 않습니다.
코드 KERNEL_OFFSET에서 코드가 실패합니다. 내가 잘못된 세그먼트로 점프하려고했기 때문에 그 실패를 알고 있지만 어떻게 그리고 어디서 그림을 그릴 수 없습니다. 나는 또한 실제로 디스크를 읽지 않는 것으로 나타났습니다. 내 load_kernel 코드는 10 섹터를 읽을 것을 요구하지만 읽은 것으로 보입니다. 프로그램은 보호 모드로 들어갈 수 있고, 로딩 동작이 이상하게 들리더라도 디스크에서로드 할 때 필요한 것을로드 할 수 있습니다.
나는 또한 아마도 내가 링크 일을 제대로하지 못했기 때문에 내 메이크 파일을 보여줍니다. 나는 OSX btw를 실행하고 있으므로 쉘 명령어가 올바른 명령어라면 idk를 사용한다.
나는 며칠 간 모든 도움을 주셨습니다. 감사합니다
boot_sector
;
; A simple boot sector program.
; BIOS stores the boot drive in DL
;
[org 0x7c00]
[bits 16]
mov [BOOT_DRIVE], dl ; Move boot drive info to memory.
; Setup stack to a position we know is free.
mov bp, 0x9000
mov sp, bp
; Output a nice message.
mov dx, REAL_MODE_MSG
call PrintString16
; Load the kernel.
mov dx, [BOOT_DRIVE]
call LoadKernel
mov dx, LOADED_KERNEL_MSG
call PrintString16
; Switch to protected mode.
; Note, we never break from Protected mode.
call SwitchToProtectedMode
jmp $
; Including some useful routines.
%include "string_utils_16.s"
%include "gdt.s"
%include "string_utils.s"
%include "load_kernel.s"
%include "switch_to_pm.s"
[bits 32]
BeginProtectedMode:
mov edx, PROT_MODE_MSG
call PrintString
; This call should, theoritecally, run the instructions we just loaded.
; AKA, the C code.
; KERNEL_OFFSET is defined in load_kernel.s
call KERNEL_OFFSET
jmp $
BOOT_DRIVE db 0
LOADED_KERNEL_MSG db "Loaded kernel with no errors!", 0
REAL_MODE_MSG db "Welcome! Started in 16-bit Real Mode!", 0
PROT_MODE_MSG db "Now running in 32-bit Protected Mode", 0
times 510 -($ - $$) db 0
dw 0xaa55
switch_to_pm
[bits 16]
SwitchToProtectedMode:
cli
lgdt [gdt_descriptor]
; To actually switch to 32 bit mode, set LSB of cr0 to 1
; Can't touch the cr0 register directly so gotta do it the hard way.
mov eax, cr0
or eax, 0x1
mov cr0, eax
; Technically, after that last move instruction, we're in 32 bit mode BUT
; the CPU may have been doing work in between all this, since, the CPU can do
; certain things in parallel if its got different circuitry to do those things,
; which it probably does. Few of the things the CPU could do in parallel is
; fetch, decode and execute. We dont want the CPU to be fetching the next
; instruction while our stuff is happening (those next things that will be
; fetched probably wont work in 32 bit mode) and we want it to finish whatever
; it is currently executing. so, we're going to do a far jump to
; somewhere so that the CPU cannot make any extrapolations on what to fetch next
; and anything being executed can finish executing.
jmp CODE_SEGMENT:init_pm
[bits 32]
; Initialize segment registers. In 32 bit mode, they all point to an entry in
; the GDT.
init_pm:
mov ax, DATA_SEGMENT
mov ds, ax
mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
; Define the stack somewhere we're sure has free memory.
mov ebp, 0x90000
mov esp, ebp
call BeginProtectedMode
load_kernel
[bits 16]
KERNEL_OFFSET equ 0x1000
; Will load the kernel into memory.
; dl will contain the boot drive.
LoadKernel:
push dx ; Save the boot drive info
mov dx, LOAD_KERNEL_MSG
call PrintString16
pop dx ; Get it back. DL contains boot drive.
mov bx, KERNEL_OFFSET ; Where we want kernel to be loaded to.
mov dh, 10 ; How many sectors to load
; dl is also a parameter but we already have it.
call LoadFromDisk
ret
%include "disk_load.s"
LOAD_KERNEL_MSG db "Loading kernel...", 0
커널
// Simple kernel.
#include "screen.h"
void main() {
print("It worked!");
// char* video = (char*) 0xb800;
// video[0] = 'S';
}
,
메이크
INCLUDE = include/
# List is expanded when used not when declared.
OBJECTS = $(wildcard temp/*.o)
# -------------------- Build the os_image
os_image.bin : temp/boot_sect.bin temp/kernel.bin
cat temp/boot_sect.bin temp/kernel.bin > os_image.bin
# -------------------- Build the boot sector image
temp/boot_sect.bin : boot/boot_sect.s
nasm boot/boot_sect.s -i boot/ -f bin -o temp/boot_sect.bin
# -------------------- Build kernel image
temp/kernel.bin : kernel.o kernel_entry.o
clang -ffreestanding -m32 kernel_entry.o $(OBJECTS) kernel.o -o temp/kernel.bin
# -------------------- Build object files
kernel.o : kernel/kernel.c temp/screen.o
clang -ffreestanding -m32 -c -I $(INCLUDE) kernel/kernel.c -o kernel.o
kernel_entry.o : kernel/kernel_entry.s
nasm -f macho -o kernel_entry.o kernel/kernel_entry.s
# -------------------- Build driver objects
temp/screen.o : include/screen.h drivers/screen.c temp/low_level.o
clang -ffreestanding -m32 -c -I $(INCLUDE) drivers/screen.c -o temp/screen.o
temp/low_level.o : include/low_level.h kernel/low_level.c
clang -ffreestanding -m32 -c -I $(INCLUDE) kernel/low_level.c -o temp/low_level.o
clean :
rm *.o
rm ./temp/*.o
rm ./temp/*.bin
rm *.bin
관련 Bochs와 콘솔 덤프
00014040953i[BIOS ] Booting from 0000:7c00
00014479618i[FDD ] partial read() on floppy image returns 172/512
00014561257i[MEM0 ] allocate_block: block=0x10 used 0x3 of 0x20
00014561312e[CPU0 ] load_seg_reg(ES, 0xfffc): invalid segment
00014561312e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
00014561312e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
00014561312i[CPU0 ] CPU is in protected mode (active)
00014561312i[CPU0 ] CS.mode = 32 bit
00014561312i[CPU0 ] SS.mode = 32 bit
00014561312i[CPU0 ] EFER = 0x00000000
00014561312i[CPU0 ] | EAX=0008fffc EBX=00001000 ECX=00090003 EDX=ffff0136
00014561312i[CPU0 ] | ESP=0008fff8 EBP=00090003 ESI=000e0000 EDI=00007d2d
00014561312i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf SF zf AF pf CF
00014561312i[CPU0 ] | SEG sltr(index|ti|rpl) base limit G D
00014561312i[CPU0 ] | CS:0008(0001| 0| 0) 00000000 ffffffff 1 1
00014561312i[CPU0 ] | DS:0010(0002| 0| 0) 00000000 ffffffff 1 1
00014561312i[CPU0 ] | SS:0010(0002| 0| 0) 00000000 ffffffff 1 1
00014561312i[CPU0 ] | ES:0010(0002| 0| 0) 00000000 ffffffff 1 1
00014561312i[CPU0 ] | FS:0010(0002| 0| 0) 00000000 ffffffff 1 1
00014561312i[CPU0 ] | GS:0010(0002| 0| 0) 00000000 ffffffff 1 1
00014561312i[CPU0 ] | EIP=0000107c (0000107c)
00014561312i[CPU0 ] | CR0=0x60000011 CR2=0x00000000
00014561312i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
(0).[14561312] [0x000000000000107c] 0008:000000000000107c (unk. ctxt): pop es ; 07
00014561312e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting