하!~~~ 전 포스트에서 어찌어찌 해서 보호모드 까지 진입 했다. 이제 바람OS 커널을 읽어서 커널로 이동하면 되는데 Visual Studio 툴로 컴파일 하다 보니 PE 포맷이다. ㅠㅠ 아~~~메모리에 커널이미지를 재배치라는 걸 해줘야 커널로 이동 할 수 있다. 젠장 할일 정말 많네…
여튼, 보호모드 까지.. 진입 했으니 커널 이미지를 읽는 작업부터 해야 겠다.
그런데 보호모드에서는 BIOS 인터럽트를 이용 할 수 없으니 , 보호모드에서 파일 읽는 방법을 찾아야 한다.
어디 보자~~~~~~~
음… http://wiki.osdev.org/ATA_read/write_sectors#Read_in_LBA_mode 이 사이트에서 방법을 찾았다. 다만 기존의 만들어 놓은 걸 다시 고쳐서 만들어야 하니.. 그냥… 보호모드 들어가기 전에 커널 이미지를 읽자 ㅡㅡ;;;; 너~~~~~~~~~~~~~~~~~무 귀찮고… 힘들다 ….
그러면.. 기존의 부트로더에서 OS_LDR.SYS 읽는 방법을 그대로 사용…….
;; creator : cyj (mangg@manggong.org) ;; date : 2014. 3. 27 ;; desc : 커널 로더. ;; 1. BARAMOS.SYS 파일을 찾아서 읽자. ;; 1. 보호모드로 진입한다. ;; 2. OK 문자 화면에 출력 [bits 16] org 0x8000 OS_LDR_ENTRY: ;; CS, DS, ES, & SS을 초기화 하자. cli xor eax, eax mov ds, ax mov ss, ax mov es, ax mov sp, 0xFFFF mov bp, sp sti mov dl,[0x0550] ; 부트 드라이브 mov [BootDrive], dl lea si, [LOADING_MSG] call PRINT call FAT_INFO ; RootDirectoryEntry 읽어 첫번째 파일을 읽자. mov eax, 0x9000 mov [TEMP_MEMORY], eax mov eax, [RootDirectoryEntry] mov [READ_SECTOR], eax mov eax, 0x10000000 ; 0x10000 위치 mov ebx, eax mov [FILE_MEMORY], eax call READ mov ebx, [TEMP_MEMORY] add ebx, 0x200 ; find file name mov ax, [TEMP_MEMORY] FIND_LOOP: cmp eax, ebx je NOTFOUND add ax, 0x20 mov si, ax mov di, KERNEL_NAME mov cx, 11 repe cmpsb jnz FIND_LOOP mov ax, [si+9] push ax mov ax, [si+15] push ax pop eax mov [CurrentCluster], eax DATA_READ: lea si,[DOT] call PRINT sub eax, 2 xor ebx, ebx mov bl, [BPB_SecPerClus] mul ebx mov ebx, [RootDirectoryEntry] add eax, ebx mov [READ_SECTOR], eax mov eax, [FILE_MEMORY] mov [TEMP_MEMORY], eax call READ mov eax, [BytsPerCluster] mov ebx, [FILE_MEMORY] add eax, ebx mov [FILE_MEMORY], eax xor ebx, ebx ; FAT 리스트 mov eax, 0x9000 mov [TEMP_MEMORY], eax mov eax, [CurrentCluster] ;xor ebx, ebx mov bx, [BPB_BytsPerSec] shr bx, 2 xor edx, edx div ebx push edx add eax, [FATsector] mov [READ_SECTOR], eax call READ pop edx mov esi, 0x9000 sal edx, 2 add esi, edx mov eax, [esi] mov [CurrentCluster], eax cmp eax, [FATEoFMask] jz END jmp DATA_READ END: lea si, [KERNEL_LOADING] call PRINT ; GDT 등록 xor eax, eax lgdt [GDT_INFO] cli mov eax, cr0 or eax, 1 mov cr0, eax jmp $+2 nop nop jmp 0x08:Entry32 NOTFOUND: lea si,[FAIL_MSG] call PRINT jmp $ ; 하드디스크 읽기 READ: ; Disk Address Packet (DAP) xor ax,ax ;INT 13h AH=00h: Reset Disk Drive mov dl,BYTE [BootDrive] ;DL = Drive Number int 0x13 jc READ mov al, 0x10 ; 크기 mov [0x500], al mov al, [BPB_SecPerClus] ; 읽을 섹터 수 mov [0x502], ax mov eax, [TEMP_MEMORY] ; 데이터가 들어갈 주소 mov [0x504], eax ; Segment:offset mov eax, [READ_SECTOR] ; 접근 할 LBA 번호 mov [0x508], eax mov ax, 0x500 ; DAP의 Segment:offset mov si, ax mov ax, 0 mov ds, ax mov ah, 0x42 ; LBA 읽기 명령 mov dl, [BootDrive] ; 장치 int 0x13 jc READ_ERROR ret READ_ERROR: lea si,[READ_ERR] call PRINT jmp $ PRINT: pusha ; 모든 레지스터를 스택에 넣는다. PRINT_LOOP: mov al, [si] ; al에 글자 하나 저장한다. inc si ; si 주소를 증가한다. or al, al ; or 연산. jz PRINT_END ; 문자열 끝이 or 연산이 0 이라면. 종료 mov ah,0x0E ; ah = 0xE int 0x10 ; 인터럽트 0x10h jmp PRINT_LOOP ; 다음 문자 출력 루프 PRINT_END: popa ;모든 레지스터 스택에서 뺀다. ret ;호출 한곳으로 리턴. FAT_INFO: pusha xor ebx, ebx mov eax, 0x9000 mov [TEMP_MEMORY], eax xor eax, eax mov eax, 0 mov [READ_SECTOR], eax call READ xor ebx, ebx mov si, [TEMP_MEMORY] mov bl, [si+454] mov bl, 0x80 mov eax, 0x9000 mov [TEMP_MEMORY], eax mov eax, ebx mov [READ_SECTOR], eax call READ mov si, [TEMP_MEMORY] mov bx, [si] mov bx, [si + 11] ; BytePerSec mov [BPB_BytsPerSec], bx xor ebx, ebx mov bl, [si + 13] ; SecPerCluster mov [BPB_SecPerClus], bl xor ecx, ecx xor ebx, ebx xor eax, eax mov cl, [si + 16] ; FAT NUM mov ebx, [si + 28] ; Hidden Sector mov eax, [si + 36] ; FAT 32 mul ecx mov cx, [si + 14] ; Reserved Sector add eax, ecx add eax, ebx mov [RootDirectoryEntry], eax xor eax, eax mov eax, ebx add eax, ecx mov [FATsector], eax xor eax, eax xor ebx, ebx mov bx, [si + 11] mov al, [si + 13] mul ebx mov [BytsPerCluster], eax lea si,[FAT32_OK] call PRINT popa ret DOT: db ".", 0x0D, 0x0A,0 FAT32_OK: db "Loading FAT's Info...", 0x0D, 0x0A, 0 KERNEL_LOADING: db "Loading BARAMOS.SYS...", 0x0D, 0x0A, 0 READ_ERR: db "Can't Read Disk..", 0x0D, 0x0A, 0 KERNEL_NAME: db "BARAMOS SYS",0 LOADING_MSG db 0x0D, 0x0A, "Searching for BARAMOS.SYS...", 0x0D, 0x0A, 0x00 FAIL_MSG db 0x0D, 0x0A, "ERROR.... ", 0x0D, 0x0A, 0x0A, 0x00 BPB_BytsPerSec dw 0 BPB_SecPerClus db 1 BootDrive db 0x00 RootDirectoryEntry dd 0 FATsector dd 0 BytsPerCluster dd 0 FATClusterMask dd 0 FATEoFMask dd 0x0FFFFFFF CurrentCluster dd 2 TEMP_MEMORY dd 0x9000 READ_SECTOR dd 0 FILE_MEMORY dd 0x10000 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 보호모드 GDT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GDT_INFO: dw GDT_TABLE_END - GDT_TABLE - 1 dd GDT_TABLE GDT_TABLE: dw 0x0000 ; null dw 0x0000 db 0x00 db 0x00 db 0x00 db 0x00 dw 0xFFFF ; Code dw 0x0000 db 0x00 db 0x9A db 0xCF db 0x00 dw 0xFFFF ; Data dw 0x0000 db 0x00 db 0x92 db 0xCF db 0x00 GDT_TABLE_END: [bits 32] Entry32: xor eax, eax mov ax, 0x10 mov ds, ax mov es, ax mov ss, ax xor esp, esp mov esp, 0xFFFF mov BYTE [0xB8000], 'O' mov BYTE [0xB8002], 'K' hang: jmp hang
위와 같이 작성..
이제 BARAMOS.SYS 파일을 만들어야 하는데~~~
음..
동작 까진 필요 없는 테스트이니깐....
Visual Studio 에서 콘솔에 프로그램 임의로 하나 작성..
// testKernel.cpp : 콘솔 응용 프로그램에 대한 진입점을 정의합니다. // #include "stdafx.h" int _tmain(int argc, _TCHAR* argv[]) { return 0; }
Visual Studio 에서 기본 으로 생성해주는 파일 그대로 컴파일 해서 BARAMOS.SYS 로 변경!!!
자 테스트 해보잣!!!
흐흐흐흐 잘된다…
자~~~~~ 이제 읽은 이미지 데이터를 이제 메모리에 재배치 하잣!!!!
메모리 0x10000위치에 커널 이미지(BARAMOS.SYS) 데이터를 섹션별로 재배치~~~
..
……
…………..
PE포맷은 ImageBase + AddressOfEntryPoint 가 실제 주소란다.. 그렇겠지..ImageBase는 기본 메모리 시작점이라고 했고, AddressOfEntryPoint가 RVA 가상 위치 오프셋 이라고 하니..
근데 … 진짜 근데…보통 실행파일은 0x400000라는데….(?)
그래서 PCVIEW 프로그램으로 내가 예제로 만든 프로그램을 분석해 봤다.
역쉬 4M 위치다. 리얼모드 모드에서는 1M 이상은 접근 안된다고 했는데????
아~~~~ 맞다… ㅡㅡ;;; 보호 모드로 넘어가서 재배치 해야 하는거군 … 에휴!!
음. 근데 초기 메모리 레이아웃에는 0x10000 위치에 커널 이미지 올린다고 했는데 … 0x400000으로 바꿔야 하나??? 흠…
구분 |
위치 |
부트로더 | 0x7C00 |
커널 로더 | 0x8000 |
커널 임시 | 0x10000 |
커널 재배치 | 0x400000 |
자… 이제 커널 재배치를 해보잣!!!!
0x10000 커널 데이터에서 ImageBase를 우선 구해야 하니, 요넘은 IMAGE_NT_HEADER 구조체 IMAGE_OPTIONAL_HEADER32 구조체 안에 있으니… 우선 IMAGE_OPTIONAL_HEADER32 구조체 위치를 찾아야겠다.
IMAGE_DOS_HEADER의 e_lfanew 에 IMAGE_NT_HEADER위치가 기록 되어 있고, IMAGE_OPTIONAL_HEADER32 위치는 e_lfanew + 0x18 에 있네.. 여기서 다시 ImageBase 위치는 아~~~ 그냥 e_lfanew + 0x34 구만..
ImageBase = e_lfanew(IMAGE_DOS_HEADER) + 0x34
PCVIEW 프로그램으로 찾아보니 쉽네 ㅋㅋㅋㅋ
ImageBase를 찾았으니, 섹션만 ImageBase 위치에 순차적으로 복사하면 되겠군..
섹션 첫 위치는 IMAGE_OPTIONAL_HEADER32 구조체의 SizeOfHeaders에 기록되니까 ImageBase 찾는거랑 마찬가지로…
Section = e_lfanew + 0x54
아.. 그런데 섹션위치는 알았는데 얼마만큼 복사하는지 섹션 크기가 알아야 하네… 그리고 섹션이 하나가 아니고 여러개 존재 하니깐…. Section 첫번째 위치는 별 의미가 없다… 흠… 그러면 섹션들 헤더를 열고.. 섹션 크기, 섹션 실제 위치, ImageBase + 섹션 RVA를 구한후 복사해줘야 할듯… 그러자면 섹션이 몇개 있는지에 대한 정보도 필요하다..섹션갯수는 elfanew 에서 …
SectionCount = e_lfanew + 0x06
그리고 각 섹션헤더 위치는 IMAGE_OPTION_HEADER 다음 위치에 있으니깐 IMAGE_FILE_HEADER구조체 SizeOfOptionalHeader가 IMAGE_OPTION_HEADER 크기니깐 ㅡㅡ;;;
SizeOfOptionHeader = e_lfanew + 0x14 구하고,
SectionHeader = e_lfanew + SizeOfOptionHeader + IMAGE_FILE_HEADER크기
IMAGE_FILE_HEADER크기는 0x14 크기니깐..
SectionHeader = e_lfanew + SizeOfOptionHeader + 0x14
에다가 다시 Signature 4바이트 더하면…
SectionHeader = e_lfanew + SizeOfOptionHeader + 0x14 + 0x04
만큼 있다.
아고 힘들어…
이제 섹션 갯수 만큼루프 돌면서 섹션 헤더를 보고 섹션의 실제 저장된 데이터를 ImageBase + 섹션 RVA만큼 위치에다가 복사해주면 된다!!!!
그럼 코딩해 보잣!!!!
;; creator : cyj (mangg@manggong.org) ;; date : 2014. 3. 27 ;; desc : 커널 로더. ;; 1. BARAMOS.SYS 파일을 찾아서 읽자. ;; 1. 보호모드로 진입한다. ;; 2. OK 문자 화면에 출력 [bits 16] org 0x8000 OS_LDR_ENTRY: ;; CS, DS, ES, & SS을 초기화 하자. cli xor eax, eax mov ds, ax mov ss, ax mov es, ax mov sp, 0xFFFF mov bp, sp sti mov dl,[0x0550] ; 부트 드라이브 mov [BootDrive], dl lea si, [LOADING_MSG] call PRINT call FAT_INFO ; RootDirectoryEntry 읽어 첫번째 파일을 읽자. mov eax, 0x9000 mov [TEMP_MEMORY], eax mov eax, [RootDirectoryEntry] mov [READ_SECTOR], eax mov eax, 0x10000000 mov ebx, eax mov [FILE_MEMORY], eax call READ mov ebx, [TEMP_MEMORY] add ebx, 0x200 ; find file name mov ax, [TEMP_MEMORY] FIND_LOOP: cmp eax, ebx je NOTFOUND add ax, 0x20 mov si, ax mov di, KERNEL_NAME mov cx, 11 repe cmpsb jnz FIND_LOOP mov ax, [si+9] push ax mov ax, [si+15] push ax pop eax mov [CurrentCluster], eax DATA_READ: lea si,[DOT] call PRINT sub eax, 2 xor ebx, ebx mov bl, [BPB_SecPerClus] mul ebx mov ebx, [RootDirectoryEntry] add eax, ebx mov [READ_SECTOR], eax mov eax, [FILE_MEMORY] mov [TEMP_MEMORY], eax call READ mov eax, [BytsPerCluster] mov ebx, [FILE_MEMORY] add eax, ebx mov [FILE_MEMORY], eax xor ebx, ebx ; FAT 리스트 mov eax, 0x9000 mov [TEMP_MEMORY], eax mov eax, [CurrentCluster] ;xor ebx, ebx mov bx, [BPB_BytsPerSec] shr bx, 2 xor edx, edx div ebx push edx add eax, [FATsector] mov [READ_SECTOR], eax call READ pop edx mov esi, 0x9000 sal edx, 2 add esi, edx mov eax, [esi] mov [CurrentCluster], eax cmp eax, [FATEoFMask] jz END jmp DATA_READ END: lea si, [KERNEL_LOADING] call PRINT ; GDT 등록 xor eax, eax lgdt [GDT_INFO] cli mov eax, cr0 or eax, 1 mov cr0, eax jmp $+2 nop nop jmp 0x08:Entry32 NOTFOUND: lea si,[FAIL_MSG] call PRINT jmp $ ; 하드디스크 읽기 READ: ; Disk Address Packet (DAP) xor ax,ax ;INT 13h AH=00h: Reset Disk Drive mov dl,BYTE [BootDrive] ;DL = Drive Number int 0x13 jc READ mov al, 0x10 ; 크기 mov [0x500], al mov al, [BPB_SecPerClus] ; 읽을 섹터 수 mov [0x502], ax mov eax, [TEMP_MEMORY] ; 데이터가 들어갈 주소 mov [0x504], eax ; Segment:offset mov eax, [READ_SECTOR] ; 접근 할 LBA 번호 mov [0x508], eax mov ax, 0x500 ; DAP의 Segment:offset mov si, ax mov ax, 0 mov ds, ax mov ah, 0x42 ; LBA 읽기 명령 mov dl, [BootDrive] ; 장치 int 0x13 jc READ_ERROR ret READ_ERROR: lea si,[READ_ERR] call PRINT jmp $ PRINT: pusha ; 모든 레지스터를 스택에 넣는다. PRINT_LOOP: mov al, [si] ; al에 글자 하나 저장한다. inc si ; si 주소를 증가한다. or al, al ; or 연산. jz PRINT_END ; 문자열 끝이 or 연산이 0 이라면. 종료 mov ah,0x0E ; ah = 0xE int 0x10 ; 인터럽트 0x10h jmp PRINT_LOOP ; 다음 문자 출력 루프 PRINT_END: popa ;모든 레지스터 스택에서 뺀다. ret ;호출 한곳으로 리턴. FAT_INFO: pusha xor ebx, ebx mov eax, 0x9000 mov [TEMP_MEMORY], eax xor eax, eax mov eax, 0 mov [READ_SECTOR], eax call READ xor ebx, ebx mov si, [TEMP_MEMORY] mov bl, [si+454] mov bl, 0x80 mov eax, 0x9000 mov [TEMP_MEMORY], eax mov eax, ebx mov [READ_SECTOR], eax call READ mov si, [TEMP_MEMORY] mov bx, [si] mov bx, [si + 11] ; BytePerSec mov [BPB_BytsPerSec], bx xor ebx, ebx mov bl, [si + 13] ; SecPerCluster mov [BPB_SecPerClus], bl xor ecx, ecx xor ebx, ebx xor eax, eax mov cl, [si + 16] ; FAT NUM mov ebx, [si + 28] ; Hidden Sector mov eax, [si + 36] ; FAT 32 mul ecx mov cx, [si + 14] ; Reserved Sector add eax, ecx add eax, ebx mov [RootDirectoryEntry], eax xor eax, eax mov eax, ebx add eax, ecx mov [FATsector], eax xor eax, eax xor ebx, ebx mov bx, [si + 11] mov al, [si + 13] mul ebx mov [BytsPerCluster], eax lea si,[FAT32_OK] call PRINT popa ret DOT: db ".", 0x0D, 0x0A,0 FAT32_OK: db "Loading FAT's Info...", 0x0D, 0x0A, 0 KERNEL_LOADING: db "Loading BARAMOS.SYS...", 0x0D, 0x0A, 0 READ_ERR: db "Can't Read Disk..", 0x0D, 0x0A, 0 KERNEL_NAME: db "BARAMOS SYS",0 LOADING_MSG db 0x0D, 0x0A, "Searching for BARAMOS.SYS...", 0x0D, 0x0A, 0x00 FAIL_MSG db 0x0D, 0x0A, "ERROR.... ", 0x0D, 0x0A, 0x0A, 0x00 BPB_BytsPerSec dw 0 BPB_SecPerClus db 1 BootDrive db 0x00 RootDirectoryEntry dd 0 FATsector dd 0 BytsPerCluster dd 0 FATClusterMask dd 0 FATEoFMask dd 0x0FFFFFFF CurrentCluster dd 2 TEMP_MEMORY dd 0x9000 READ_SECTOR dd 0 FILE_MEMORY dd 0x10000 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 보호모드 GDT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; GDT_INFO: dw GDT_TABLE_END - GDT_TABLE - 1 dd GDT_TABLE GDT_TABLE: dw 0x0000 ; null dw 0x0000 db 0x00 db 0x00 db 0x00 db 0x00 dw 0xFFFF ; Code dw 0x0000 db 0x00 db 0x9A db 0xCF db 0x00 dw 0xFFFF ; Data dw 0x0000 db 0x00 db 0x92 db 0xCF db 0x00 GDT_TABLE_END: [bits 32] Entry32: xor eax, eax mov ax, 0x10 mov ds, ax mov es, ax mov ss, ax xor esp, esp mov esp, 0xFFFF ; 메모리 재배치 해보자 mov esi, 0x10000 ; 커널 이미지 저장된곳 xor edx, edx xor eax, eax add edx, 0x3C mov eax, [esi+edx] mov [NT_POINTER], eax ; e_lfanew 위치 구하기(IMAGE_NT_HEADER위치) mov ebx, eax mov edx, 0x34 add edx, ebx mov eax, [esi+edx] mov [IMAGE_BASE], eax ; IMAGE_BASE 위치 구하기 mov edx, 0x28 add edx, ebx mov eax, [esi+edx] mov [ENTRY_POINT], eax ; ENTRY_POINT 위치 구하기 mov edx, 0x06 add edx, ebx mov ax, WORD [esi+edx] mov [SECTION_COUNT], ax ; 섹션 갯수 구하기 mov edx, 0x14 add edx, ebx mov ax, WORD [esi+edx] mov [OPTIONHEADER_SIZE], ax ;IMAGE_OPTION_HEADER크기 구하기 mov edx, 0x18 add dx, WORD[OPTIONHEADER_SIZE] add edx, ebx mov eax, edx mov [SECTION_HEADER], eax ;섹션 헤더 위치 구하기 xor ecx, ecx mov cx, [SECTION_COUNT] ; 섹션 갯수 만큼 반복 SECTION_LOOP: mov esi, 0x10000 mov ebx, [SECTION_HEADER] ; 섹션 헤더 위치 mov edx, 0x0C ; 섹션 RVA = 섹션 헤더 위치 + 0x0C add edx, ebx mov eax, [esi+edx] mov [SECTION_RVA], eax mov edx, 0x10 ; 섹션 크기 = 섹션 헤더 위치 + 0x10 add edx, ebx mov eax, [esi+edx] mov [SECTION_SIZE], eax mov edx, 0x14 ; 섹션 데이터 위치 = 섹션 헤더 위치 + 14 add edx, ebx mov eax, [esi+edx] mov [SECTION_POINTER], eax ; 복사할 원본 위치 add esi, [SECTION_POINTER] ; 섹션 데이터가 있는 위치 . mov edi, [IMAGE_BASE] ; 복사될 메모리 위치 add edi, [SECTION_RVA] ; IMAGE_BASE 에서 섹션 RVA 만큼 위치 push ecx cld mov ecx, [SECTION_SIZE] ; 섹션 사이즈 만큼 repz movsb ; 복사 pop ecx mov eax, [SECTION_HEADER] ; 섹션 헤더 위치를 다음 섹션 헤더 위치로 변경 add eax, 40 mov [SECTION_HEADER], eax loop SECTION_LOOP mov BYTE [0xB8000], 'O' mov BYTE [0xB8002], 'K' mov eax, [IMAGE_BASE] add eax, [ENTRY_POINT] call eax hang: jmp hang IMAGE_BASE dd 0 ENTRY_POINT dd 0 NT_POINTER dd 0 OPTIONHEADER_SIZE dw 0 SECTION_COUNT dw 0 SECTION_HEADER dd 0 SECTION_RVA dd 0 SECTION_SIZE dd 0 SECTION_POINTER dd 0
PE 메모리 재배치 하는 코드 찾다가 http://1228.tistory.com/entry/%EC%9A%B4%EC%98%81%EC%B2%B4%EC%A0%9C-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EC%96%B4%EC%85%88%EB%B8%94%EB%A6%AC%EC%BD%94%EB%93%9C%EC%97%90%EC%84%9C-C%EC%BD%94%EB%93%9C%EB%A1%9C-%EC%A0%90%ED%94%84%ED%95%98%EA%B8%B0-%EB%A1%9C%EB%8D%94-%EC%9E%91%EC%84%B1 블로그 꼬꼬넷님 코드를 훔쳤다(?) … 정말 감사드린다……똭!!!
이제 테스트…!!!
헐… 또 재부팅이다… 음…
코드를 몇번을 확인해도 문제는 없어 보인다.
커널이 메모리상에 재배치 되는건 문제가 없어 보인다. 그래서 Visual Studio에서 컴파일 할때 옵션이 잘못된듯 해 보여 또 부랴부랴 검색질.
http://wiki.osdev.org/Visual_Studio
요기 이 사이트에서 하라는대로 컴파일 옵션을 수정했다.
그리고 커널 코드도 바꿨다…
int StartKernel(int argc, char* argv[]) { char* hello = "Hello OS!"; unsigned char* vidmem = (unsigned char*)0xB8000; while( *hello != '\0' ) { *vidmem++ = *hello++; *vidmem++ = 7; // 문자 기본 속성 } return 0; }
그리고 컴파일 옵션->고급 에서 진입점을 StartKernel 입력하고 컴파일…
아직까진 간단한 코드니 에러 없이 컴파일 잘 된다!!
자 이제!! 테스트
ㅠㅠ
된다… 와 ! 된다 ㅠㅠ
부트로더, 커널로더 까지 많은 시행 착오 및 병행 학습을 많이 했는데 막상 이렇게 기능상 구현이 된 모습을 보니 간단하다… 누가 이걸 보고 많은 지식이 포함되어 있다는걸 알겠누.. 흠..
이제 어려운 과정(?)은 다 끝난것 같다. 물론 남은 일이 더 남아 있지만, 어셈블리어 메뉴얼 뒤져 보면서 한자 한자 출력 해보면서 테스트 하는 작업은 끝난 듯….
OS의 핵심인 커널은 이것보다 험난 할 듯 보이지만.. 적어도 문법적으로 검증해야 하는 난관이 없다는데 행복함을 느낀다.
커널은 부트로더, 커널 로더 처럼 단일 기능이 아니고 필요할 때마다 학습해서 될 문제는 아닌듯 해서 커널 까지는 다시 학습이 필요 할 것 같다…
학 ………………..습.
'프로그래밍 > OS 만들기' 카테고리의 다른 글
OS 만들기 #16 IDT - 1 (0) | 2015.07.30 |
---|---|
OS 만들기 #15 커널-키보드 입력 (0) | 2015.02.09 |
OS 만들기 #13 보호모드 진입 (0) | 2014.03.27 |
OS 만들기 #12 - PE 파일 포맷 (0) | 2013.09.10 |
OS 만들기 #11 - 리얼모드 & 보호모드 (0) | 2013.08.14 |