Real Mode 에서 Protected Mode 로의 전환..

gyxor의 이미지

SysCodeSelector equ 0x08
SysDataSelector equ 0x10
VideoSelector equ 0x18

[bits 16]
[org 7C00h]
mov ax, 0
mov ds, ax

mov ax, 0xB800
mov es, ax
mov di, 0
mov cx, 0x7FF
mov ax, 0
paint:
mov byte [es:di], al ;화면 초기화
add di,2
dec cx
jnz paint

mov di,80 * 0
mov byte [es:di],41h ;'A' 출력

cli
lgdt[gdtr]

mov eax, cr0
or eax, 0x00000001
mov cr0, eax
nop
nop
nop

mov ax,VideoSelector
mov es,ax
mov edi,80 * 2
mov byte [es:edi] , 42h ;'B' 출력

jmp dword SysCodeSelector:PM_Start


[bits 32]
PM_Start:
mov ax,VideoSelector
mov es,ax
mov edi,80 * 4
mov byte [es:edi] , 43h ;'C' 출력

jmp $

gdtr: dw gdt_end-gdt-1
dd gdt
gdt:
dd 0, 0
dd 0x0000FFFF, 0x00CF9A00
dd 0x0000FFFF, 0x00CF9200
dd 0x8000FFFF, 0x0040920B

gdt_end:

위 소스는 Nasm 문법의 어셈블리코드입니다.
어셈블한 실행파일을 RawWriter 라는 프로그램으로 플로피디스크의 0번셋터에 저장한뒤에 부팅을 시키면
화면 왼쪽 상단에
A
B
C
가 찍힙니다.
정상적으로 수행이 되는 소스입니다.
최초 부팅이 되면
Real 모드이고
CS: 0000 IP:7c00h 의 위치에 위 코드가 적재되고
실행이 됩니다.
따라서 org는 7c00으로 했습니다.
video display memory 영역에 ascii값 내용을 전부 0으로 바꿔서 일단 화면을 초기화 합니다.
그런뒤에
A를 출력하고..

CR0 레지스터를 셋팅해서 protected mode로 넘어갑니다.
이후부터는 cs 와 ds등 segment register의 값이 4bit shift되서 offset과 더해지는것이 아니라 아래에 설정된 descriptor에 의해서 base를 잡게 됩니다.

여기서 의문이 생기는것이 바로 CR0를 셋팅한 직후!! 입니다.
protected mode로 전환이 되고난 바로 직후에
cs 레지스터에는 0 이 들어가 있습니다.
실제로 프로그램이 정상 수행되려면
0이 아니라 0x0008 이들어가야 합니다.
code segment의 descriptor offset이 0x0008이기 때문입니다.
실제로 B를 출력한뒤에
Far jmp를 통해서....
jmp dword SysCodeSelector:PM_Start
cs값을 바꿔주고 있습니다.
cs를 통해 얻게 되는 base값은 결국에는 0입니다.
따라서 이 base에 PM_Start offset값을 더하면
org설정으로 인해.. 7c00+알파 일텐데..
정상적으로 PM_Start위치로 점프하게 됩니다.
Far Jmp 이후의 상황은 'C'를 출력하게 됩니다.

하지만 CR0가 셋팅된 이후와 Far Jmp 하기 전까지는
cs값이 셋팅이 안되어있게 되는데요..
어떻게 정상적으로 B가 찍히고.. 이후까지도 정상수행이 되는것인지 모르겠습니다.

추측해보면..
CR0 를 셋팅한 이후에 Protected모드가 되는것은 맞지만..
ds ,ss 등 다른 segment 레지스터에는 바로 적용이 되지만
cs 만큼은 Far Jmp등이 실행될때까지 Real Mode방식으로 유보가 되는것인가요?
안그렇다면.. 사실.. Protected모드로 들어가기전에..
미리 cs를 decriptor값으로 셋팅할 수 도 없고..
protected 모드로 넘어가고 나면 다음 명령을 fetch해 올때..문제가 생기고 ....
CR0 셋팅하는 순간에 동시에 CS가 바뀔수도 없는 노릇이고..
어떻게 구현이 되어있는것인지 모르겠습니다.

자세한 답변부탁드립니다.

fromdj의 이미지

OS만드시나 보네요..
IA32 메뉴얼 보시면 자세한 Sequence 가 나올겁니다.

^^ be cool ~
http://fromdj.pe.kr

Necromancer의 이미지

prefetch queue의 영향입니다.
cr0 세팅 이후에 따라오는 jmp 명령까지는 prefetch queue에서
다 읽혀져서 실행됩니다.

cr0 PE=1 세팅직후
장거리점프를 쓰는 이유는 CS를 로딩할 뿐만 아니라
prefetch queue를 비워서 다음 명령어들(보호모드상에서
실행되는 명령어)이 다시 fetch되도록 하는 역할을 합니다.

(요즘 cpu라면 다른 알고리즘으로 돌아갈지 모르겠네요.
보호모드 처음 도입된 286. 386 시절은 그랬습니다.)

Written By the Black Knight of Destruction

gyxor의 이미지

RealCS equ 0x0000
SysCodeSelector equ 0x08
SysDataSelector equ 0x10
VideoSelector equ 0x18

[bits 16]
[org 7C00h]
start:
mov ax, 0
mov ds, ax

mov ax, 0xB800
mov es, ax
mov di, 0
mov cx, 0x7FF
mov ax, 0
paint:
mov byte [es:di], al ;화면 초기화
add di,2
dec cx
jnz paint

mov di,80 * 0
mov byte [es:di],41h ;'A' 출력

cli
lgdt[gdtr]

mov eax, cr0
or eax, 0x00000001
mov cr0, eax

mov ax,bx ; padding
mov ax,bx ; padding
mov ax,bx ; padding
mov ax,bx ; padding
mov ax,bx ; padding
mov ax,bx ; padding
mov ax,bx ; padding
mov ax,bx ; padding
mov ax,bx ; padding
mov ax,bx ; padding
mov ax,bx ; padding
mov ax,bx ; padding
mov ax,bx ; padding
mov ax,bx ; padding
mov ax,bx ; padding
mov ax,bx ; padding
mov ax,bx ; padding

mov ax,VideoSelector
mov es,ax
mov edi,80 * 2
mov byte [es:edi] , 42h ;'B' 출력

jmp dword SysCodeSelector:PM_Start


[bits 32]
PM_Start:
sti
mov ax,VideoSelector
mov es,ax
mov edi,80 * 4
mov byte [es:edi] , 43h ;'C' 출력

cli
mov eax, cr0
and eax, 0xFFFFFFFE
mov cr0, eax

jmp $+2
nop
nop

jmp RealCS:loop1
loop1:
mov eax, 0h
mov cr3, eax


mov ax,0
mov ds,ax
lidt [idtr]
sti

mov ax, 0xB800
mov es, ax
mov di,80 * 6
mov byte [es:di],44h ;'D' 출력

jmp $
idtr: dw 256*4-1
dd 0
gdtr: dw gdt_end-gdt-1
dd gdt
gdt:
dd 0, 0
dd 0x0000FFFF, 0x00CF9A00
dd 0x0000FFFF, 0x00CF9200
dd 0x8000FFFF, 0x0040920B
gdt_end:

____________________________________________
위 소스는 정상수행되며
화면 왼쪽 상단에
A
B
C
D
를 출력합니다...

IA-32 Intel Architecture Software Developer's Manual, Volume 3
메뉴얼의 9.9페이지에 Protected Mode로의 전환과 다시 되돌아오는 과정이 있었습니다.
하지만 내부적으로 어떻게 처리가 되는지는 나와있지 않았습니다...
제가 못찾은건가요.....
내용을 읽어보면..
결국.. Far JMP는 Protected 모드로 가기 위해 반드시 필요한 명령어이고.. CS register의 셋팅이, Far JMP명령이 읽혀와서 실행되는 순간까지.. 미뤄지는것으로 추측됩니다..
위 소스에서 padding 명령어를 CR0 셋팅이후부터 Far JMP하기전까지 많이 넣어봐도 잘 실행이 되는것을 보면..
결국..
다른 세그먼트 레지스터의 경우,
처리방식이 CR0의 셋팅을 통해 바로 변경이 되는것과는 달리
CS 레지스터의 처리 방식은 CR0가 셋팅이 되더라도 GDT를 참조하지 않고 REAL MODE방식을 유지 했다가 Far JMP명령을 하고 나서야 비로소 Protected mode방식으로 바뀌는것으로 생각됩니다. 제 생각이 맞는것일까요?
메뉴얼을 더 샅샅이 뒤지면 관련 내용이 나올까요?

메뉴얼에.. Real Mode로 돌아가는 내용도 나와있어서..
위 소스코드 마지막에 추가 시켰는데요..
정상적으로 'D' 가 찍히는 것으로 봐서 분명 Real모드로 돌아온것은 분명한데..
왜 ctrl+alt+del 인터럽트가 발생을 안하는것인지 모르겠습니다.
(테스트용 컴퓨터에 reset버튼이 없어서 ctrl+alt+del 기능이 꼭필요한 관계로,,,,해봤습니다.)
lidt 명령을 사용해서 protected mode에서 인터럽테이블의 base와 limit을 설정한것처럼 real mode의 원래 인터럽 테이블 주소인 base : 0 h limit : 256*4-1 를 설정을 했는데요..
결론적으로...
real mode일때는 lidt를 사용하는것인지 아닌지 의문이 남습니다.
답변부탁드립니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.