아주 간단한 보호 모드 진입 코드입니다...왜 안될까요? T.T
글쓴이: kkojiband / 작성시간: 토, 2003/07/19 - 11:32오전
- boot.asm
[org 0] jmp start start: mov ax, 7C0h mov ds, ax mov ax, 08000h mov es, ax xor dh, dh xor ch, ch mov cl, 2 mov al, 1 xor bx, bx mov dl, 0 mov ah, 2 int 13h mov ax, 0B800h mov es, ax xor di, di mov al, 'M' stosb mov ax, 9000h mov es, ax xor di, di xor si, si mov cl, 32 rep movsb cli lidt [ds:idt_48] lgdt [ds:gdt_48] mov ecx, CR0 inc cx mov CR0, ecx db 66h, 0EAh dw 0 dw 8 dw 10h gdt: dw 0, 0, 0, 0 dw 0, 0, 0, 0 dw 0FFFFh dw 0 dw 8A00h dw 0CFh dw 0FFFFh dw 0 dw 8200h dw 0CFh gdt_48: dw 8000h db 0, 0, 9, 0 idt_48: dw 0 dw 0, 0
- run.asm
[bits 32] mov ax, 10h mov ds, ax mov es, ax mov edi, 0B8000h mov al, 'I' stosb hang: jmp hang
boot.asm 가 부트 코드이고, run.asm 은 보호 모드 하에서 문자 I 를 출력하는 아주 간단한 프로그램입니다...
먼저 일단 보호 모드로 들어가는게 목적이기 때문에 인터럽트는 disable 시키고, 그 뒤엔 전혀 사용치 않았습니다...
근데 계속 리부팅 됩니다...T.T
아시는 분들 좀 도와주세요~
Forums:
GDT, IDT구조체..............
OS환경도 궁금하네요. 도스상인가요?
그리고 주소 정확히 세팅 하셨는지. 보니까 프로그램이 로드된
세그먼트가 어느위치인지 고려 안했군요. (CS레지스터에서
주소계산해서 원주소값에 더하는 과정이 필요합니다)
디스크립터 타입값도 틀리고요.
level 0 코드 디스크립터는 타입이 9ah, 데이터의 경우 92h입니다
그리고 디스크립터의 특권 레벨은 타입값 bit 5-6에 표시됩니다.
정학히 세팅 안하고 cr0 PE 비트를 세팅하면 바로 리부팅입니다.
Written By the Black Knight of Destruction
추가..
보호모드 공부하시려면 DJGPP라는 도스용 gcc와 함께
배포되는 DPMI386.EXE의 소스를 뒤지는게 좋을꺼라 생각됩니다.
그리고 인텔 cpu 메뉴얼은 아주 필수고요. ralf brown의 인터럽트 리스트도
절대로 필요하고요. (부트로더 작성시에도 꼭 필요합니다)
Written By the Black Knight of Destruction
먼저 답변 감사드립니다~리눅스상에서 vmware 4.0 을 사용해
먼저 답변 감사드립니다~
리눅스상에서 vmware 4.0 을 사용해서 실험해보고 있습니다...
위에 보시면 es = 0x8000 bx = 0 위치에 프로그램을 로드시켰구요,
jmp 시에는 10h 셀렉터의 0x80000 위치로 점프를 시켰거든요...
워낙 간단한 프로그램이라서 적어도 안될 이유는 없을것같은데 계속 리부팅이 되네요...답답...T.T
이에 대해 어떻게 생각하시나요?? 먼가가 잘못됐으니까 안되는거겠죠...T.T
도와주세요~ 죄송...-_-;;;
이제 졸업이다...사랑하는 SKKULUG 후배들아 안녕~
답변해주실 분 안계신가요?? T.T그럼 혹시 이에 관련된 공부를
답변해주실 분 안계신가요?? T.T
그럼 혹시 이에 관련된 공부를 할수있는 책이라도 추천 좀...부탁드릴께요~
한글로 된 책이면 더더욱 좋구요...--;
이제 졸업이다...사랑하는 SKKULUG 후배들아 안녕~
음... CR0를 설정한뒤 기계어로 점프를 하시쟎아요그런데 중요한것은
음... CR0를 설정한뒤 기계어로 점프를 하시쟎아요
그런데 중요한것은 어디로 점프하는거예요?
run.asm이 8000h에 읽혀지는건가요?
그리고 run.asm에서 cld 명령 잊으셨군요.
더 자세히 봐드리고 싶지만 솔직히 이거 표보면서 해야 되는 불편함이 있군요.
좀 의도를 주석으로 달아주시면 좋겠네요.
예를 들어 디스크립터의 limit=xxxx, base=xxxx, G=0, 이런식으로.......
한가지 더 물어볼께 있는데 run.asm은 32bit 로 컴파일 하신거죠?
먼저 답변 감사드립니다...^^디스크립터는 리눅스에서 사용하는 K
먼저 답변 감사드립니다...^^
디스크립터는 리눅스에서 사용하는 KERNEL_CS 와 KERNEL_DS 를 그대로 사용했습니다...
그리고 run 이 읽혀지는 곳은 8000h:0 이구요...jump 는 10h(base=0, limit=4G):80000h 로 했구요...
근데 run.asm 에서 cld 를 해주라는 건 무슨 말씀이신지요??
cld, std 는 es:edi 나 ds:esi 사용할때 edi, esi 가 자라는 방향을 정하는 명령어 아닌가요??
제가 아는게 짧아서 님께서 해주신 말씀이 무슨 의도인지를 모르겠습니다...T.T
그리고 32bit 로 컴파일 할때 'bits 32' 만 붙여주면 안되는건가요??
컴파일 할때는 그냥 nasm -o run run.asm 으로 똑같이 했거든요...
허접한게 멋모르고 덤볐다가 아주 골머리만 썩고 있습니다...--...죄송...T.T
이제 졸업이다...사랑하는 SKKULUG 후배들아 안녕~
설마 이건 아니겠지라는 생각은 들지만 -_-;;부트코드의 마지막 두바
설마 이건 아니겠지라는 생각은 들지만 -_-;;
부트코드의 마지막 두바이트에 0xAA55가 없네요. -_-a
그리고 비디오 메모리에 직접 문자를 찍어보면서 정확하게 어디서 재부팅이 되는 지 보는 것이 좋습니다.
앞으로도 많은 작업을 하실 꺼라면 제 경험상 계속 해서 코드만 보고 어디서 문제가 생기는 지 알기 힘듭니다.
좋은 하루되세요. ^_^
nasm의 문법 및 사용법은 잘 몰라서 뭐라고 예기하기 어렵네요.그냥
nasm의 문법 및 사용법은 잘 몰라서 뭐라고 예기하기 어렵네요.
그냥 TASM/MASM 용으로 제가 만들었던것의 일부를 올립니다.
이것은 보호모드로 진입후 할거 하고 다시 리얼모드로 돌아오도록
합니다. 이거 다시 손보면서 기억이 새록새록 나는군요....
사실상 대부분 공개된 소스 보면 리얼모드로 돌아오는 방법이 묘사되지
않아서 그냥 만들어 본겁니다.
감사합니다...T.T일단 먼저 간단히 봤는데, 이해가 안되지만..
감사합니다...T.T
일단 먼저 간단히 봤는데, 이해가 안되지만...-_-;
첨 어셈 공부할때 masm 으로해서 masm 이 그리 낯설지는 않네요...^^;
있다 집에 가서 이거보고 오늘은 기필코 보호 모드의 세계로 들어가바야겠네요...과연...-_-;;;
신경써주셔서 정말 감사드립니다...좋은 하루 되세요~!
이제 졸업이다...사랑하는 SKKULUG 후배들아 안녕~
nasm이면 출력하는 디폴트 오브젝트 포맷은 elf인데..bin 포맷
nasm이면 출력하는 디폴트 오브젝트 포맷은 elf인데..
bin 포맷으로 출력하시고, 소스코드는 반드시 단일 파일로 합치시기 바랍니다.
elf는 32bit밖에 안되는걸로 알고, 또 거기다 링크과정이 필요하며
실행시작시 OS가 프로그램로딩후 실행 전에 조작을 가해야 하는 부분이 있습니다.
(일명 relocation이라고 하죠)
bin 포맷으로 만들려면 -f bin 하면 됩니다. 또한 바로 쓸 수 있고요.
저도 nasm으로 만들어둔게 있긴 하지만 이건 회사 프로젝트라서 공개하기가 영 곤란하네요.
나중에 시간 되면 별도로 만들어서 공개해야죠.
Written By the Black Knight of Destruction
Re: 아주 간단한 보호 모드 진입 코드입니다...왜 안될까요? T.T
여기서 처음 2바이트는 Limit이고 뒤의 4바이트는 Base인데,
왜 Base를 0,0,9,0으로 하셨는지요..-_-ㅋ
뒤의 4바이트는 gdt의 물리적 주소가 되어야 합니다.
따라서 0x7C00+gdt가 되어야 하겠군요..
org
org 0]
jmp start
start:
mov ax, 7C0h
mov ds, ax
mov ax, 08000h
mov es, ax
xor dh, dh
xor ch, ch
mov cl, 2
mov al, 1
xor bx, bx
mov dl, 0
mov ah, 2
int 13h
cld <------ 반대방향으로 들어가는것을 막기위해 direction flag를 클리어해주세요^^
mov ax, 0B800h
mov es, ax
xor di, di
mov al, 'M'
stosb
mov ax, 9000h
mov es, ax
xor di, di
xor si, si
mov cl, 32
rep movsb
cli
lidt [ds:idt_48]
lgdt [ds:gdt_48]
mov ecx, CR0
inc cx
mov CR0, ecx
jmp next <------------------- CPU는 항상 실행코드이전에 예비코드를 읽어들입니다.
next: <------------------- 32bit Protected mode에서 16비트 코드를 실행시키
nop <------------------- 는 것은 불안정적이므로 일부러 사석을 좀 달아봤습니
nop <------------------- 다.^^;;;
db 66h, 0EAh
dw 0
dw 8
dw 10h
gdt:
dw 0, 0, 0, 0
dw 0, 0, 0, 0
dw 0FFFFh
dw 0
dw 8A00h
dw 0CFh
dw 0FFFFh
dw 0
dw 8200h
dw 0CFh
gdt_48:
dw 8000h
db 0, 0, 9, 0
idt_48:
dw 0
dw 0, 0
times 510-($-$$) db 0 <------이부분은 nasm에서 소스에서 509번지까지 0으로 채우고
dw 0xaa55 <-------부트 스트랩이라는 것을 bios에게 알려주는 ID코드를
넣어봤습니다.
그리고 중간에 기계어 코드부분인
db 66h, 0EAh
dw 0
dw 8
dw 10h
이부분은 jmp 0x08:목적지주소로 바꿔주시는것이 더 낳을것 같습니다.
0x08은 셀렉터중에서
dw 0FFFFh
dw 0
dw 8A00h
dw 0CFh
바로 이부분을 가르킵니다.
이부분이 코드 세크멘트 디스크립터를 말하는 부분인것 같습니다.
쓸모없는 초보가 한번 적어봤습니다.
댓글 달기