2013年3月14日 星期四

x86 process switch implementation (2) - x86 protected mode verison

我知道, 長很多是吧!除了進入保護模式的差異, 這程式和 x86 process switch implementation (1) - save %ax 做的是一樣的事情。而 int 0x30 就不僅僅是改改位址就好, 需要設定 idt。而且 stack 長度也由 2byte 變為 4byte。

要完全看懂這程式可能很不容易, 但是如果把焦點一樣放在 process switch, 不要管那些保護模式相關的程式碼, 應該還是可以看懂。

L114 ~ 214 都很熟悉吧!和 x86 real mode 版本完全一樣。那我是不是很無聊做了個保護模式的版本, 只是要炫燿, 當然不是, 我需要保護模式的另外一個功能來完成最後的步驟 - stack save/restore。

請看下一篇, A ... 沒下一篇阿!糟糕 xD!!

p_proc.S
  1 # in protected mode, do process switch
  2 
  3 #define STACK_FRAME_OFFSET 6
  4 .code16
  5 .data
  6 .macro Descriptor Base, Limit, Attr
  7     .2byte  \Limit & 0xFFFF
  8     .2byte  \Base & 0xFFFF
  9     .byte   (\Base >> 16) & 0xFF
 10     .2byte  ((\Limit >> 8) & 0xF00) | (\Attr & 0xF0FF)
 11     .byte   (\Base >> 24) & 0xFF
 12 .endm
 13 
 14 .set    DA_386IGate, 0x8E    /* 32-bit Interrupt Gate */
 15 
 16 /* Gate Descriptor data structure.
 17    Usage: Gate Selector, Offset, PCount, Attr
 18     Selector:  2byte
 19     Offset:    4byte
 20     PCount:    byte
 21     Attr:      byte */
 22 .macro Gate  Selector, Offset, PCount, Attr
 23     .2byte     (\Offset & 0xFFFF)
 24     .2byte     \Selector
 25     .2byte     (\PCount & 0x1F) | ((\Attr << 8) & 0xFF00)
 26     .2byte     ((\Offset >> 16) & 0xFFFF)
 27 .endm
 28 
 29 
 30 
 31 .set    DA_32,  0x4000  /* 32-bit segment */
 32 .set    DA_LIMIT_4K, 0x8000     /* 4K */
 33 .set    DA_CR,   0x9A   /* Execute/Read */
 34 .set    DA_DRW,  0x92   /* Read/Write */
 35 
 36 gdt0: Descriptor  0, 0, 0
 37 gdt1: Descriptor  0, 0xfffff, DA_CR | DA_32 | DA_LIMIT_4K
 38 gdt2: Descriptor  0, 0xfffff, DA_DRW | DA_32 | DA_LIMIT_4K
 39 .set gdt_len, (. - gdt0)
 40 gdt_ptr: .2byte (gdt_len -1 ) # limit
 41          .4byte 0             # base
 42 
 43 .set selector_code, (gdt1-gdt0)
 44 .set selector_data, (gdt2-gdt0)
 45 
 46 idt:
 47 .rept 200
 48 Gate selector_code, switch_proc_offset, 0, DA_386IGate
 49 .endr
 50 .set idt_len, (. - idt)  /* IDT Length */
 51 
 52 idt_ptr: .2byte  (idt_len - 1)  /* IDT Limit */
 53          .4byte  0             /* IDT Base */
 54 
 55 
 56 .text
 57 .global begin
 58 begin:
 59   xchg %bx, %bx #bochs magic break point
 60 
 61     /* Initialize 32-bits code segment descriptor. */
 62     xor     %eax, %eax
 63     mov     %cs, %ax
 64     shl     $4, %eax
 65 #    addl    $seg_code32, %eax
 66     movw    %ax, (gdt1 + 2)
 67     shr     $16, %eax
 68     movb    %al, (gdt1 + 4)
 69     movb    %ah, (gdt1 + 7)
 70 
 71     /* Initialize 32-bits data segment descriptor. */
 72     xor     %eax, %eax
 73     mov     %cs, %ax
 74     shl     $4, %eax
 75 #    addl    $seg_code32, %eax
 76     movw    %ax, (gdt2 + 2)
 77     shr     $16, %eax
 78     movb    %al, (gdt2 + 4)
 79     movb    %ah, (gdt2 + 7)
 80 
 81   xor     %eax, %eax
 82   mov     %cs, %ax
 83   shl     $4, %eax
 84   add     $gdt0, %eax      /* eax <- gdt base*/
 85   movl    %eax, (gdt_ptr + 2)
 86   lgdt gdt_ptr
 87 
 88     /* Prepared for loading IDTR */
 89     xor     %eax, %eax
 90     mov     %ds, %ax
 91     shl     $4, %eax
 92     add     $idt, %eax      /* eax <- idt base*/
 93     movl    %eax, (idt_ptr + 2)
 94 
 95   cli
 96 
 97   lidt idt_ptr
 98 
 99   # open a20 line
100   inb $0x92, %al
101   orb $0b00000010, %al
102   outb %al, $0x92
103 
104 
105   # enable protect mode
106   movl %cr0, %eax
107   orl $1, %eax
108   movl %eax, %cr0
109 
110 
111   xchg %bx, %bx #bochs magic break point
112   ljmpl $selector_code, $seg_code32
113 
114 .code32
115 seg_code32:
116   mov $selector_data, %ax
117   mov %ax, %ds
118   mov %ax, %ss
119   mov $proc_stack_top, %esp
120 
121 ## set stack frame flag
122   # get flag
123   pushf
124   movl (%esp), %eax
125   popf
126   movl %eax, stack_frame_a+12
127   movl %eax, stack_frame_b+12
128   cli
129 
130 ## set stack frame eip
131   movl $proc_a, stack_frame_a+4
132   movl $proc_b, stack_frame_b+4
133 
134 ## set stack frame cs
135   xor     %eax, %eax
136   movw %cs, %ax
137   movw %ax, stack_frame_a+8
138   movw %ax, stack_frame_b+8
139 
140 
141   movl $stack_frame_a, cur_proc
142   movl cur_proc, %esp
143   popl %eax
144   iret
145 
146 
147 
148 
149   mov $selector_data, %ax
150   int $0x30
151   mov %ax, %ds
152   mov %ax, %es
153   mov %ax, %ss
154   mov $0xb8004, %edi    /* Destination */
155   movb $'P', (%edi)
156   mov $0xb8005, %edi    /* Destination */
157   movb $0x9, (%edi)
158 
159 .global proc_a
160 proc_a:
161 1:
162   mov $0x1, %ax
163   int $0x30
164   jmp 1b
165 
166 .global proc_b
167 proc_b:
168 1:
169   mov $0x2, %al
170   int $0x30
171   jmp 1b
172 
173 
174 .global int0x30
175 int0x30:
176 .set int0x30_offset, (. - seg_code32)
177   mov $0x1, %cx;
178   iret
179 .global switch_proc
180 switch_proc:
181 .set switch_proc_offset, (. - begin+0x100)
182   xchg %bx, %bx #bochs magic break point
183   push %eax
184 
185   movl cur_proc, %edx
186   cmpl $stack_frame_a, %edx
187   je 1f
188   movl $stack_frame_a, cur_proc
189   jmp 2f
190 1:
191   movl $stack_frame_b, cur_proc
192 2:
193 
194 
195   movl cur_proc, %esp
196   pop %eax
197   iret
198 
199 stack_frame_a:
200   .long 0x9# eax
201   .long 0x0# eip
202   .long 0x0# cs
203   .long 0x2# flag
204 
205 stack_frame_b:
206   .long 0x9# ax
207   .long 0x0# eip
208   .long 0x0# cs
209   .long 0x2# flag
210 cur_proc:
211   .long 0x0
212 
213   .space  256, 0
214 proc_stack_top:

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。