NASM 고수분들께 질문입니다.
현재 제가 만들고 있는 부트로더 일부분입니다..VMWare으로 돌리고 있는데요~
잘 실행되다가
mov eax, cr0
or eax, 0x00000001
mov cr0, eax
이부분에서 VMWare가 Stack fault를 일으킵니다..
왜 이런 오류가 일어 납니까? 단순히 cr0의 마지막 비트를 1로 셋팅하고 싶은데요!
도와주세요!
읽어주셔서 감사합니다.
[org 0]
[bits 16]
%define INITSS 0x1000
%define INITSP 0xffff
%define BOOTSEG 0x07c0 ;boot segment: 0x7c00:0x0000
%define INITSEG 0x9000 ;boot loader itself moves to here
%define SETUPSEG 0x9020 ;setup segment: 0x9020:0x0000
%define SYSSEG 0x1000 ;beginning of kernel image
;here we assume cs: 0000h ip:7c00h
;reload
cld
mov ax, INITSEG
mov es, ax
xor di, di
mov ax, BOOTSEG
mov ds, ax
xor si, si
mov cx, 0x100 ;256 * 2byte(movsw) = 512 byte
repz movsw
jmp INITSEG:main
;=========================================
; main procedure
;=========================================
main:
mov ax, cs ;cs has INITSEG:0x9000
mov ds, ax
mov es, ax
;mov ss, ax ;;cs = ds = es = ss
;mov sp, 0x07c0
;init video
mov ax, 0600h
mov bh, 07h
xor cx, cx
mov dx, 1850h ;row:24 column:80
int 10h ;reset window
mov ah, 02h
xor bh, bh
xor dx, dx
int 10h ;set cursor position onto the top-left
;loading msg
mov si, WORD msg_loading
.msg_loop:
lodsb
or al, al
jz .out
mov ah, 0x0e
mov bl, 0x07
int 10h
jmp .msg_loop
.out:
mov ah, 02h
xor bh, bh
inc dh
mov dl, 00h
int 10h
.read_setup:
;read setup from disk
;setup will be loaded at 0x9020:0000
mov ax, SETUPSEG
mov es, ax
mov bx, 0 ;es:bx 0x9020:0000
mov ax, 0x0201
mov cx, 0x0002
mov dx, 0x0000
int 0x13
jc .read_setup
.load_kernel:
;load kernel image into memory
;kernel is loaded at 0x1000:0x0000
mov ax, SYSSEG
mov es, ax
mov bx, 0
mov ax, 0x0201
mov cx, 0x0003
mov dx, 0x0000
int 0x13
jc .load_kernel
mov dx, 0x3F2 ;turn off disk motor
xor al, al
out dx, al
;jump to setup() code 0x9020:0x0000
jmp SETUPSEG:0x0000
;=========================================
; data used by boot procedure
;=========================================
msg_loading db 'Loading...', 0
;==========================================
; boot signature
;==========================================
times 510-($-$$) db 0
dw 0xaa55
[org 0]
[bits 16]
start:
mov ax, cs ;CS has 0x9020:0000
mov ds, ax
xor ax, ax
mov ss, ax
;mov si, WORD msg_setup
;.msg_loop:
; lodsb
; or al, al
; jz .out
; mov ah, 0x0e
; mov bl, 0x07
; int 10h
; jmp .msg_loop
;.out:
cli
lgdt[gdtr]
mov eax, cr0
or eax, 0x00000001
mov cr0, eax
jmp $+2
nop
nop
jmp dword SysCodeSelector:PM_Start
;=========================================
;***********Protected Mode****************
;=========================================
[bits 32]
PM_Start:
mov bx, SysDataSelector
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
mov ss, bx
mov si, WORD msg_starting
.msg_loop:
lodsb
or al, al
jz .out
mov ah, 0x0e
mov bl, 0x07
int 10h
jmp .msg_loop
.out:
jmp $
;=========================================
; **************GDT Table*****************
;=========================================
gdtr:
dw gdt_end-gdt-1 ;limit of GDT
dd gdt+0x90200
;NULL Descriptor
gdt:
dw 0
dw 0
db 0
db 0
db 0
db 0
;Kernel Code Segment Descriptor
SysCodeSelector equ 0x10
dw 0xFFFF ;limit 0xFFFFF
dw 0x9020 ;base 0~15bit
db 0x00 ;base 16~23bit
db 0x9A ;P:1, DPL:0, S:1, Code, Non-Conforming, readable
db 0xCF ;G:1, D:1, limit 16~19 bit:0xF
db 0x00 ;base 24~32bit
;Kernel Data Segment Descriptor
SysDataSelector equ 0x18
dw 0xFFFF ;limit 0xFFFFF
dw 0x0000 ;base 0~15bit
db 0x00 ;base 16~23bit
db 0x92 ;P:1, DPL:0, S:1, Data, expand-up, writable
db 0xCF ;G:1, D:1, limit 16~19 bit:0xF
db 0x00 ;base 24~32bit
;User Code Segment Descriptor
UserCodeSelector equ 0x20
dw 0xFFFF ;limit 0xFFFFF
dw 0x0000 ;base 0~15bit
db 0x00 ;base 16~23bit
db 0xFA ;P:1, DPL:3, S:1, Data, expand-up, writable
db 0xCF ;G:1, D:1, limit 16~19 bit:0xF
db 0x00 ;base 24~32bit
;User Data Segment Descriptor
UserDataSelector equ 0x28
dw 0xFFFF ;limit 0xFFFFF
dw 0x0000 ;base 0~15bit
db 0x00 ;base 16~23bit
db 0x92 ;P:1, DPL:0, Data, expand-up, writable
db 0xCF ;G:1, D:1, limit 16~19 bit:0xF
db 0x00 ;base 24~32bit
gdt_end:
;=========================================
; data used by setup procedure
;=========================================
msg_setup db 'Loaded Setup...', 0
msg_starting db 'PM is Starting...', 0
고수는 아닌데 잠시
고수는 아닌데 잠시 참견 좀 하겠습니다. ;
SysCodeSelector equ 0x10
Descriptor의 index를 통해 계산해 보면 0x08이 맞는 것 같습니다.
모든 selector 값이 2배로 되어 있는 듯 합니다.
그리고 Code Segment Descriptor의 base가 0이 아니어서 far jump의 목적 지점이 다른 곳에 떨어질 수 있을 것 같습니다.
보호모드 전환
대충 보면 세가지 문제가 있는데
하나는 윗분이 말씀하신대로 descriptor 값이 8씩 더해져 있네요.
두번째는 그리고 보호모드 전환 직후에는 CS 레지스터를 갱신하기 위해서 반드시 장거리점프를 해야 합니다.
인텔 메뉴얼에서는 안할경우 비정상 동작할 수 있다고 경고하고 있습니다.
그리고 이를 위해서 현재 코드 세그먼트 범위와 일치하는 보호모드용 16bit 코드 디스크립터를 하나 만들 필요가 있고요.
jmp $+2 대신에
jmp 0x08:$+2를 써야 합니다.
(0x08은 리얼모드 세그먼트와 대응되는 보호모드 셀렉터입니다. 만일 다른 인덱스값이면 그걸 넣어야 하고요)
세번째는 IRQ 처리가 전혀 안되어 있습니다.
보호모드 전환중에는 8259a를 건드려서 IRQ를 모두 막아야 하고요.
전환 후에는 풀어도 되는데 이때 만일 IDT가 제대로 세팅되어 있지 않다면 뻗습니다.
IRQ가 disable 되어 있다면 디스크 입출력이 불가능해지기 때문에 실제 도는 프로그램 만들려면
IRQ 처리가 가능하도록 핸들러를 만들고 IDT를 세팅을 해줘야 합니다.
가장 간단한 거는 IRQ 발생시 리얼모드로 돌아가서 bios 내의 루틴들을 호출하는거죠.
리눅스 커널 소스에 이 예가 있을겁니다.
Written By the Black Knight of Destruction
Written By the Black Knight of Destruction
댓글 달기