1 | ;
|
---|
2 | ; SEGMENTS.ASM -- Manage segments
|
---|
3 | ;
|
---|
4 | ; Copyright (c) 1991-1999 by Eberhard Mattes
|
---|
5 | ;
|
---|
6 | ; This file is part of emx.
|
---|
7 | ;
|
---|
8 | ; emx is free software; you can redistribute it and/or modify it
|
---|
9 | ; under the terms of the GNU General Public License as published by
|
---|
10 | ; the Free Software Foundation; either version 2, or (at your option)
|
---|
11 | ; any later version.
|
---|
12 | ;
|
---|
13 | ; emx is distributed in the hope that it will be useful,
|
---|
14 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
15 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
16 | ; GNU General Public License for more details.
|
---|
17 | ;
|
---|
18 | ; You should have received a copy of the GNU General Public License
|
---|
19 | ; along with emx; see the file COPYING. If not, write to
|
---|
20 | ; the Free Software Foundation, 59 Temple Place - Suite 330,
|
---|
21 | ; Boston, MA 02111-1307, USA.
|
---|
22 | ;
|
---|
23 | ; See emx.asm for a special exception.
|
---|
24 | ;
|
---|
25 |
|
---|
26 | __SEGMENTS = 1
|
---|
27 |
|
---|
28 | INCLUDE EMX.INC
|
---|
29 | INCLUDE TABLES.INC
|
---|
30 | INCLUDE MISC.INC
|
---|
31 | INCLUDE PAGING.INC
|
---|
32 | INCLUDE SEGMENTS.INC
|
---|
33 | INCLUDE SIGNAL.INC ; Required by PROCESS.INC
|
---|
34 | INCLUDE PROCESS.INC
|
---|
35 |
|
---|
36 | PUBLIC NEW_TSS, G_PHYS_BASE
|
---|
37 | PUBLIC CREATE_SEG, SEG_SIZE, SEG_BASE, SEG_ATTR, GET_BASE
|
---|
38 | PUBLIC NULL_SEG, GET_LIN, GET_DESC, SV_SEGMENT, ADD_PAGES
|
---|
39 | PUBLIC ACCESS_LOWMEM, MAP_PHYS
|
---|
40 | PUBLIC INIT_DESC, RM_SEG_BASE, RM_SEG_SIZE, INIT_TSS
|
---|
41 |
|
---|
42 | SV_DATA SEGMENT
|
---|
43 |
|
---|
44 | ;
|
---|
45 | ; Base address of G_PHYS_SEL (see also G_PHYS_DESC)
|
---|
46 | ;
|
---|
47 | G_PHYS_BASE DD 0
|
---|
48 | ;
|
---|
49 | ; New TSS (with I/O bitmap) active
|
---|
50 | ;
|
---|
51 | NEW_TSS DB FALSE ; Initially not active
|
---|
52 |
|
---|
53 | SV_DATA ENDS
|
---|
54 |
|
---|
55 |
|
---|
56 | SV_CODE SEGMENT
|
---|
57 |
|
---|
58 | ASSUME CS:SV_CODE, DS:NOTHING
|
---|
59 |
|
---|
60 |
|
---|
61 | ;
|
---|
62 | ; Create a segment (make GDT/LDT entry)
|
---|
63 | ;
|
---|
64 | ; In: SI Pointer to GDT/LDT entry
|
---|
65 | ; AX Segment attributes (A_CODE32, A_DATA32, DPL_0, ..., DPL_3)
|
---|
66 | ; EBX Base address of segment
|
---|
67 | ; ECX Size of segment (limit+1)
|
---|
68 | ;
|
---|
69 | ASSUME DS:NOTHING
|
---|
70 |
|
---|
71 | CREATE_SEG PROC NEAR
|
---|
72 | CALL SEG_ATTR
|
---|
73 | CALL SEG_BASE
|
---|
74 | CALL SEG_SIZE
|
---|
75 | RET
|
---|
76 | CREATE_SEG ENDP
|
---|
77 |
|
---|
78 |
|
---|
79 | ;
|
---|
80 | ; Set the type/attributes of a segment
|
---|
81 | ;
|
---|
82 | ; In: DS:SI Pointer to descriptor
|
---|
83 | ; AX Type / attributes (A_CODE32, A_DATA32, DPL_0, ..., DPL_3)
|
---|
84 | ;
|
---|
85 | SEG_ATTR PROC NEAR
|
---|
86 | AND WORD PTR [SI+5], 0CF00H ; Clear all but G, B|D, limit
|
---|
87 | OR [SI+5], AX ; Set segment type/attributes
|
---|
88 | RET
|
---|
89 | SEG_ATTR ENDP
|
---|
90 |
|
---|
91 |
|
---|
92 | ;
|
---|
93 | ; Set the base address of a segment
|
---|
94 | ;
|
---|
95 | ; In: DS:SI Pointer to GDT entry
|
---|
96 | ; EBX Base address of segment
|
---|
97 | ;
|
---|
98 | ASSUME SI:PTR DESCRIPTOR
|
---|
99 | SEG_BASE PROC NEAR
|
---|
100 | PUSH EBX
|
---|
101 | MOV [SI].BASE_0_15, BX ; Base 0..15
|
---|
102 | SHR EBX, 16
|
---|
103 | MOV [SI].BASE_16_23, BL ; Base 16..23
|
---|
104 | MOV [SI].BASE_24_31, BH ; Base 24..31
|
---|
105 | POP EBX
|
---|
106 | RET
|
---|
107 | ASSUME SI:NOTHING
|
---|
108 | SEG_BASE ENDP
|
---|
109 |
|
---|
110 |
|
---|
111 | ;
|
---|
112 | ; Set the size of a segment
|
---|
113 | ;
|
---|
114 | ; In: DS:SI Pointer to GDT entry (already contains access & other info)
|
---|
115 | ; ECX Size of segment (limit+1)
|
---|
116 | ;
|
---|
117 | ASSUME SI:PTR DESCRIPTOR
|
---|
118 | SEG_SIZE PROC NEAR
|
---|
119 | PUSH ECX
|
---|
120 | AND [SI].GRAN, 70H ; Keep B|0|AVL, clear G|limit
|
---|
121 | CMP ECX, 1 SHL 20 ; Byte granular?
|
---|
122 | JA SHORT SS_BIG ; No -> page granular
|
---|
123 | DEC ECX ; ECX := limit (byte granular)
|
---|
124 | MOV [SI].LIMIT_0_15, CX ; Limit 0..15
|
---|
125 | SHR ECX, 16
|
---|
126 | OR [SI].GRAN, CL ; Limit 16..19
|
---|
127 | JMP SHORT SS_RET
|
---|
128 |
|
---|
129 | SS_BIG: ADD ECX, 0FFFH ; Round up
|
---|
130 | SHR ECX, 12 ; Convert to number of pages
|
---|
131 | DEC ECX ; ECX := limit (page granular)
|
---|
132 | MOV [SI].LIMIT_0_15, CX ; Limit 0..15
|
---|
133 | SHR ECX, 16
|
---|
134 | OR CL, 80H ; Set G
|
---|
135 | OR [SI].GRAN, CL ; Limit 16..19
|
---|
136 | SS_RET: POP ECX
|
---|
137 | RET
|
---|
138 | ASSUME SI:NOTHING
|
---|
139 | SEG_SIZE ENDP
|
---|
140 |
|
---|
141 |
|
---|
142 | ;
|
---|
143 | ; Get the base address of a segment
|
---|
144 | ;
|
---|
145 | ; In: DS:SI Pointer to GDT entry
|
---|
146 | ;
|
---|
147 | ; Out: EBX Base address of segment
|
---|
148 | ;
|
---|
149 | ASSUME SI:PTR DESCRIPTOR
|
---|
150 | GET_BASE PROC NEAR
|
---|
151 | MOV BL, [SI].BASE_16_23 ; Base 16..23
|
---|
152 | MOV BH, [SI].BASE_24_31 ; Base 24..31
|
---|
153 | SHL EBX, 16
|
---|
154 | MOV BX, [SI].BASE_0_15 ; Base 0..15
|
---|
155 | RET
|
---|
156 | ASSUME SI:NOTHING
|
---|
157 | GET_BASE ENDP
|
---|
158 |
|
---|
159 | ;
|
---|
160 | ; Convert virtual address to linear address
|
---|
161 | ;
|
---|
162 | ; In: AX Selector
|
---|
163 | ; EBX Offset
|
---|
164 | ; LDTR Local descriptor table
|
---|
165 | ;
|
---|
166 | ; Out: EBX Linear address
|
---|
167 | ; CY Error
|
---|
168 | ;
|
---|
169 | ASSUME DS:SV_DATA
|
---|
170 | GET_LIN PROC NEAR
|
---|
171 | PUSH EAX
|
---|
172 | PUSH ESI
|
---|
173 | .386P
|
---|
174 | SLDT SI
|
---|
175 | .386
|
---|
176 | CALL GET_DESC
|
---|
177 | MOV EAX, EBX
|
---|
178 | CALL GET_BASE
|
---|
179 | ADD EBX, EAX
|
---|
180 | CLC
|
---|
181 | POP ESI
|
---|
182 | POP EAX
|
---|
183 | RET
|
---|
184 | GET_LIN ENDP
|
---|
185 |
|
---|
186 | ;
|
---|
187 | ; Get LDT/GDT entry
|
---|
188 | ;
|
---|
189 | ; In: AX Selector
|
---|
190 | ; SI Local descriptor table (selector)
|
---|
191 | ;
|
---|
192 | ; Out: SI Pointer to table entry
|
---|
193 | ;
|
---|
194 | ASSUME DS:SV_DATA
|
---|
195 | GET_DESC PROC NEAR
|
---|
196 | PUSH AX
|
---|
197 | TEST AX, 04H ; GDT?
|
---|
198 | JZ SHORT GDES_1 ; Yes ->
|
---|
199 | AND SI, NOT 07H
|
---|
200 | SUB SI, G_LDT_SEL
|
---|
201 | IMUL SI, LDT_ENTRIES
|
---|
202 | LEA SI, LDTS[SI]
|
---|
203 | JMP SHORT GDES_2
|
---|
204 | GDES_1: LEA SI, GDT
|
---|
205 | GDES_2: AND AX, NOT 07H
|
---|
206 | ADD SI, AX
|
---|
207 | POP AX
|
---|
208 | RET
|
---|
209 | GET_DESC ENDP
|
---|
210 |
|
---|
211 | ;
|
---|
212 | ; Create a null segment (make GDT/LDT entry)
|
---|
213 | ;
|
---|
214 | ; In: DS:SI Pointer to GDT/LDT entry
|
---|
215 | ;
|
---|
216 | ASSUME DS:NOTHING
|
---|
217 | NULL_SEG PROC NEAR
|
---|
218 | MOV DWORD PTR [SI+0], 0
|
---|
219 | MOV DWORD PTR [SI+4], 0
|
---|
220 | RET
|
---|
221 | NULL_SEG ENDP
|
---|
222 |
|
---|
223 |
|
---|
224 | ;
|
---|
225 | ; Create supervisor data segment (not swappable)
|
---|
226 | ;
|
---|
227 | ; In: ECX Size (bytes)
|
---|
228 | ; DS:SI Pointer to GDT entry
|
---|
229 | ;
|
---|
230 | ; Out: CY Out of memory
|
---|
231 | ;
|
---|
232 | ; Note: No physical memory is allocated for the pages, so the pages must
|
---|
233 | ; be present if accessed from within the page fault handler (to avoid
|
---|
234 | ; recursion)
|
---|
235 | ;
|
---|
236 | ASSUME DS:SV_DATA
|
---|
237 | SV_SEGMENT PROC NEAR
|
---|
238 | PUSH EAX
|
---|
239 | PUSH EBX
|
---|
240 | PUSH ECX
|
---|
241 | MOV AL, PIDX_SV
|
---|
242 | CALL ALLOC_PAGES ; Get linear addresses
|
---|
243 | CALL INIT_PAGES ; Create page tables
|
---|
244 | JC SHORT SVS_RET ; Out of memory -> return
|
---|
245 | MOV EBX, PAGE_LOCKED ; Create locked pages
|
---|
246 | MOV EDX, PIDX_SV OR SRC_ZERO
|
---|
247 | CALL SET_PAGES
|
---|
248 | MOV EBX, EAX ; Linear address to EBX
|
---|
249 | POP ECX ; Number of bytes
|
---|
250 | PUSH ECX
|
---|
251 | MOV AX, A_DATA32 OR DPL_0 ; Supervisor data segment
|
---|
252 | CALL CREATE_SEG ; Create segment descriptor
|
---|
253 | SVS_RET: POP ECX
|
---|
254 | POP EBX
|
---|
255 | POP EAX
|
---|
256 | RET
|
---|
257 | SV_SEGMENT ENDP
|
---|
258 |
|
---|
259 | ;
|
---|
260 | ; Allocate, initialize and switch to new TSS.
|
---|
261 | ;
|
---|
262 | ; If there isn't enough memory, NEW_TSS stays FALSE.
|
---|
263 | ;
|
---|
264 | ASSUME DS:SV_DATA
|
---|
265 | INIT_TSS PROC NEAR
|
---|
266 | ;
|
---|
267 | ; Allocate memory
|
---|
268 | ;
|
---|
269 | MOV ECX, SIZE TSS_STRUC + 2001H
|
---|
270 | LEA SI, G_TMP1_DESC ; Use temporary descriptor
|
---|
271 | CALL SV_SEGMENT ; Create supervisor segment
|
---|
272 | JC SHORT IT_RET ; Out of memory -> done
|
---|
273 | ;
|
---|
274 | ; Copy initial TSS to new segment
|
---|
275 | ;
|
---|
276 | PUSH DS ; Save DS
|
---|
277 | MOV AX, G_TSS_MEM_SEL
|
---|
278 | MOV DS, AX
|
---|
279 | MOV AX, G_TMP1_SEL
|
---|
280 | MOV ES, AX
|
---|
281 | XOR SI, SI
|
---|
282 | XOR DI, DI
|
---|
283 | MOV CX, SIZE TSS_STRUC
|
---|
284 | REP MOVSB
|
---|
285 | ;
|
---|
286 | ; Initialize I/O bitmap (all 64K ports disabled)
|
---|
287 | ;
|
---|
288 | MOV AX, 0FFH
|
---|
289 | MOV CX, 2001H
|
---|
290 | REP STOSB
|
---|
291 | POP DS ; Restore DS
|
---|
292 | ;
|
---|
293 | ; Copy to G_TSS_MEM_SEL descriptor
|
---|
294 | ;
|
---|
295 | MOV_ES_DS ; ES := DS
|
---|
296 | LEA SI, G_TMP1_DESC
|
---|
297 | LEA DI, G_TSS_MEM_DESC
|
---|
298 | MOVSD
|
---|
299 | MOVSD
|
---|
300 | ;
|
---|
301 | ; Copy to G_TSS_SEL descriptor
|
---|
302 | ;
|
---|
303 | CLI ; Disable interrupts
|
---|
304 | LEA SI, G_TMP1_DESC
|
---|
305 | LEA DI, G_TSS_DESC
|
---|
306 | MOVSD
|
---|
307 | MOVSD
|
---|
308 | LEA SI, G_TSS_DESC
|
---|
309 | MOV AX, A_TSS ; Turn it into a TSS desciptor
|
---|
310 | CALL SEG_ATTR
|
---|
311 | ;
|
---|
312 | ; Switch to new TSS
|
---|
313 | ;
|
---|
314 | AND TSS_BUSY, NOT 2
|
---|
315 | MOV AX, G_TSS_SEL
|
---|
316 | .386P
|
---|
317 | LTR AX
|
---|
318 | .386
|
---|
319 | STI ; Enable interrupts
|
---|
320 | MOV NEW_TSS, NOT FALSE ; New TSS active
|
---|
321 | IT_RET: RET
|
---|
322 | INIT_TSS ENDP
|
---|
323 |
|
---|
324 | ;
|
---|
325 | ; Add some pages of memory to a process. The pages will be added at the
|
---|
326 | ; end of the data segment, above the stack.
|
---|
327 | ;
|
---|
328 | ; In: DI Pointer to process table entry
|
---|
329 | ; ECX Number of pages
|
---|
330 | ;
|
---|
331 | ; Out: EAX Address in process space of the memory (or 0 on failure)
|
---|
332 | ;
|
---|
333 | ASSUME DS:SV_DATA
|
---|
334 | ADD_PAGES PROC NEAR
|
---|
335 | ASSUME DI:PTR PROCESS
|
---|
336 | PUSH SI
|
---|
337 | MOV EAX, [DI].P_DSEG_SIZE
|
---|
338 | ADD EAX, 1000H ; One empty page
|
---|
339 | PUSH EAX ; Save the return value
|
---|
340 | SHL ECX, 12 ; Compute number of bytes
|
---|
341 | ADD EAX, ECX ; Adjust end address
|
---|
342 | JC SHORT AP_FAIL ; Overflow -> fail
|
---|
343 | CMP EAX, [DI].P_LIN_SIZE ; Beyond end of address space?
|
---|
344 | JA SHORT AP_FAIL ; Yes -> fail
|
---|
345 | MOV EDX, EAX ; New data segment size
|
---|
346 | POP EAX ; Address of new pages
|
---|
347 | PUSH EAX
|
---|
348 | PUSH EDX
|
---|
349 | ADD EAX, [DI].P_LINEAR ; Compute linear address
|
---|
350 | SHR ECX, 12 ; Number of pages
|
---|
351 | MOV EBX, PAGE_WRITE OR PAGE_USER
|
---|
352 | MOV EDX, SRC_NONE
|
---|
353 | TEST [DI].P_FLAGS, PF_DONT_ZERO
|
---|
354 | JNZ SHORT AP_1
|
---|
355 | MOV EDX, SRC_ZERO
|
---|
356 | AP_1: MOV DL, [DI].P_PIDX
|
---|
357 | CALL SET_COMMIT ; Set PAGE_ALLOC bit
|
---|
358 | CALL SET_PAGES
|
---|
359 | POP EAX ; New data segment size
|
---|
360 | JC SHORT AP_FAIL
|
---|
361 | MOV [DI].P_DSEG_SIZE, EAX ; Update data segment size
|
---|
362 | MOV ECX, [DI].P_DSEG_SIZE
|
---|
363 | MOV SI, [DI].P_LDT_PTR
|
---|
364 | ADD SI, L_DATA_SEL AND NOT 07H
|
---|
365 | CALL SEG_SIZE
|
---|
366 | POP EAX
|
---|
367 | POP SI
|
---|
368 | RET
|
---|
369 |
|
---|
370 | AP_FAIL: POP EAX
|
---|
371 | POP SI
|
---|
372 | XOR EAX, EAX ; Return 0
|
---|
373 | RET
|
---|
374 | ASSUME DI:NOTHING
|
---|
375 | ADD_PAGES ENDP
|
---|
376 |
|
---|
377 |
|
---|
378 | ;
|
---|
379 | ; Map pages into the address space of a process
|
---|
380 | ;
|
---|
381 | ; In: DI Pointer to process table entry
|
---|
382 | ; EBX Physical address
|
---|
383 | ; ECX Number of pages
|
---|
384 | ;
|
---|
385 | ; Out: EAX Adress in process space (0 if no space)
|
---|
386 | ;
|
---|
387 | ASSUME DS:SV_DATA
|
---|
388 | ASSUME DI:PTR PROCESS
|
---|
389 | MAP_PHYS PROC NEAR
|
---|
390 | MOV EAX, [DI].P_DSEG_SIZE
|
---|
391 | ADD EAX, 1000H
|
---|
392 | PUSH EAX
|
---|
393 | MOV EDX, ECX
|
---|
394 | SHL EDX, 12
|
---|
395 | ADD EAX, EDX
|
---|
396 | JC SHORT MP_FAIL
|
---|
397 | CMP EAX, [DI].P_LIN_SIZE
|
---|
398 | JA SHORT MP_FAIL
|
---|
399 | MOV [DI].P_DSEG_SIZE, EAX
|
---|
400 | SUB EAX, EDX
|
---|
401 | ADD EAX, [DI].P_LINEAR
|
---|
402 | MOV DL, [DI].P_PIDX
|
---|
403 | TEST EBX, NOT 0FFFH ; Is the address = 0?
|
---|
404 | JNZ SHORT MP_MORE ; No -> continue
|
---|
405 | PUSH ECX
|
---|
406 | MOV ECX, 1 ; Set one page table entry
|
---|
407 | CALL SET_PAGES ; This is required because
|
---|
408 | POP ECX ; SET_PAGES doesn't increment
|
---|
409 | DEC ECX ; the address if it is 0
|
---|
410 | JZ SHORT MP_DONE
|
---|
411 | ADD EAX, 1000H
|
---|
412 | ADD EBX, 1000H
|
---|
413 | MP_MORE: CALL SET_PAGES
|
---|
414 | MP_DONE: MOV ECX, [DI].P_DSEG_SIZE
|
---|
415 | MOV SI, [DI].P_LDT_PTR
|
---|
416 | ADD SI, L_DATA_SEL AND NOT 07H
|
---|
417 | CALL SEG_SIZE
|
---|
418 | POP EAX
|
---|
419 | RET
|
---|
420 |
|
---|
421 | MP_FAIL: POP EAX
|
---|
422 | XOR EAX, EAX
|
---|
423 | RET
|
---|
424 | ASSUME DI:NOTHING
|
---|
425 | MAP_PHYS ENDP
|
---|
426 |
|
---|
427 |
|
---|
428 | ;
|
---|
429 | ; Convert real-mode pointer to protected-mode pointer
|
---|
430 | ;
|
---|
431 | ; In: EAX Real-mode Segment:Offset
|
---|
432 | ;
|
---|
433 | ; Out: EBX Offset into G_LOWMEM_SEL segment
|
---|
434 | ; EAX Modified
|
---|
435 | ;
|
---|
436 | ACCESS_LOWMEM PROC NEAR
|
---|
437 | ROL EAX, 16 ; EAX = offset:segment
|
---|
438 | MOVZX EBX, AX ; EBX = segment
|
---|
439 | SHL EBX, 4 ; EBX = base address of segment
|
---|
440 | SHR EAX, 16 ; EAX = offset
|
---|
441 | ADD EBX, EAX
|
---|
442 | RET
|
---|
443 | ACCESS_LOWMEM ENDP
|
---|
444 |
|
---|
445 | SV_CODE ENDS
|
---|
446 |
|
---|
447 |
|
---|
448 |
|
---|
449 | INIT_CODE SEGMENT
|
---|
450 |
|
---|
451 | ASSUME CS:INIT_CODE, DS:NOTHING
|
---|
452 |
|
---|
453 | ;
|
---|
454 | ; Convert the base field of a GDT entry. It already contains the
|
---|
455 | ; offset into the real-mode segment given in AX.
|
---|
456 | ;
|
---|
457 | ; In: AX Real-mode segment
|
---|
458 | ; DI Pointer to descriptor table entry (SV_DATA)
|
---|
459 | ;
|
---|
460 | ASSUME DS:SV_DATA
|
---|
461 | ASSUME DI:PTR DESCRIPTOR
|
---|
462 | INIT_DESC PROC NEAR
|
---|
463 | PUSH EAX
|
---|
464 | PUSH EDX
|
---|
465 | MOVZX EAX, AX
|
---|
466 | SHL EAX, 4
|
---|
467 | MOVZX EDX, [DI].BASE_0_15 ; Get real-mode offset
|
---|
468 | ADD EAX, EDX
|
---|
469 | CALL RM_SEG_BASE ; Set base address
|
---|
470 | POP EDX
|
---|
471 | POP EAX
|
---|
472 | RET
|
---|
473 | ASSUME DI:NOTHING
|
---|
474 | INIT_DESC ENDP
|
---|
475 |
|
---|
476 |
|
---|
477 |
|
---|
478 | ;
|
---|
479 | ; Set the base address of a segment (real-mode version)
|
---|
480 | ;
|
---|
481 | ; In: DS:DI Pointer to GDT entry
|
---|
482 | ; EAX Base address of segment
|
---|
483 | ;
|
---|
484 | ASSUME DS:SV_DATA
|
---|
485 | ASSUME DI:PTR DESCRIPTOR
|
---|
486 | RM_SEG_BASE PROC NEAR
|
---|
487 | PUSH EAX
|
---|
488 | MOV [DI].BASE_0_15, AX ; Base 0..15
|
---|
489 | SHR EAX, 16
|
---|
490 | MOV [DI].BASE_16_23, AL ; Base 16..23
|
---|
491 | MOV [DI].BASE_24_31, AH ; Base 24..31
|
---|
492 | POP EAX
|
---|
493 | RET
|
---|
494 | ASSUME DI:NOTHING
|
---|
495 | RM_SEG_BASE ENDP
|
---|
496 |
|
---|
497 |
|
---|
498 | ;
|
---|
499 | ; Set the size of a segment (real-mode version)
|
---|
500 | ;
|
---|
501 | ; In: DS:DI Pointer to GDT entry
|
---|
502 | ; ECX Size of segment (limit+1)
|
---|
503 | ;
|
---|
504 | ASSUME DS:SV_DATA
|
---|
505 | ASSUME DI:PTR DESCRIPTOR
|
---|
506 | RM_SEG_SIZE PROC NEAR
|
---|
507 | PUSH ECX
|
---|
508 | AND [DI].GRAN, 70H ; Keep B|0|AVL, clear G|limit
|
---|
509 | CMP ECX, 1 SHL 20 ; Byte granular?
|
---|
510 | JA SHORT RSS_BIG ; No -> page granular
|
---|
511 | DEC ECX ; ECX := limit (byte granular)
|
---|
512 | MOV [DI].LIMIT_0_15, CX ; Limit 0..15
|
---|
513 | SHR ECX, 16
|
---|
514 | OR [DI].GRAN, CL ; Limit 16..19
|
---|
515 | JMP SHORT RSS_RET
|
---|
516 |
|
---|
517 | RSS_BIG: ADD ECX, 0FFFH ; Round up
|
---|
518 | SHR ECX, 12 ; Convert to number of pages
|
---|
519 | DEC ECX ; ECX := limit (page granular)
|
---|
520 | MOV [DI].LIMIT_0_15, CX ; Limit 0..15
|
---|
521 | SHR ECX, 16
|
---|
522 | OR CL, 80H ; Set G
|
---|
523 | OR [DI].GRAN, CL ; Limit 16..19
|
---|
524 | RSS_RET: POP ECX
|
---|
525 | RET
|
---|
526 | ASSUME DI:NOTHING
|
---|
527 | RM_SEG_SIZE ENDP
|
---|
528 |
|
---|
529 |
|
---|
530 | INIT_CODE ENDS
|
---|
531 |
|
---|
532 | END
|
---|