A ‘protected-mode’ exploration A look at the steps needed to build segment-descriptors for displaying a message while in protected-mode Segment-Descriptor Format 63 32 Base[31..24] RA D CR Limit GDSV P P SX / / A [19..16] VL L DW Base[15..0] Base[23..16] Limit[15..0] 31 0 Legend: DPL = Descriptor Privilege Level (0..3) G = Granularity (0 = byte, 1 = 4KB-page) P = Present (0 = no, 1 = yes) D = Default size (0 = 16-bit, 1 = 32-bit) S = System (0 = yes, 1 = no) X = eXecutable (0 = no, 1 = yes) A = Accessed (0 = no, 1 = yes) code-segments: R = Readable (0 = no, 1 = yes) C = Conforming (0=no, 1=yes) data-segments: W = Writable (0 = no, 1 = yes) D = expands-Down (0=no, 1=yes) RSV = Reserved for future use by Intel AVL = Available for user’s purposes Example: the ‘vram’ segment • The video display-memory for color text occupies a 32KB physical address-range from 0x000B8000 to 0x000BFFFF • It’s segment-limit can be described with ‘byte’ granularity as equal to 0x07FFF (or with ‘page’ granularity as 0x00007 ) • It needs to be a ‘writable’ data-segment • It’s privilege-level ought to be 0 (restricted) Descriptor Implementations 00 0 0 92 0B 8000 7FFF Using ‘byte’ granularity 00 8 8000 0 92 0B 0007 Using ‘page’ granularity # vram-segment descriptor using ‘byte’ granularity .word 0x7FFF, 0x8000, 0x920B, 0x0000 # vram-segment descriptor using ‘page’ granularity .word 0x0007, 0x8000, 0x920B, 0x0080 Code and data segments • Our program’s code and data will reside at the base memory-address: 0x00010000 • For simplicity when returning to real-mode, we can keep segment-limits as: 0x0FFFF • Both segments can retain privilege-level 0 • Code-segment: ‘readable’ + ‘executable’ • Data-segment: ‘writable’ + ‘readable’ Descriptors implemented data-segment descriptor code-segment descriptor 00 00 0 0 92 01 0000 FFFF Using ‘byte’ granularity 0 0000 0 9A 01 FFFF Using ‘byte’ granularity # data-segment descriptor using ‘byte’ granularity .word 0xFFFF, 0x0000, 0x9201, 0x0000 # code-segment descriptor using ‘byte’ granularity .word 0xFFFF, 0x0000, 0x9A01, 0x0000 Global Descriptor Table • We can put all of our segment-descriptors into the Global Descriptor Table • Our program executes at privilege-level 0 • Every GDT must have a ‘null’ descriptor • Thus our GDT will need four descriptors .align theGDT: .word .word .word .word 8 # the Pentium requires ‘quadword’ alignment 0x0000, 0x0000, 0x0000, 0x0000 # ‘null’ descriptor 0xFFFF, 0x0000, 0x9A01, 0x0000 # code-descriptor 0xFFFF, 0x0000, 0x9201, 0x0000 # data-descriptor 0x7FFF, 0x8000, 0x920B, 0x0000 # vram-descriptor GDTR register-format 47 16 15 0 Segment Base-Address Segment Limit 32 bits 16 bits The register-image (48-bits) is prepared in a memory-location… regGDT: .word 0x001F, theGDT, 0x0001 # register-image for GDTR … then the register gets loaded from memory via a special instruction lgdt regGDT # initializes register GDTR segment-selector format 15 INDEX 3 2 1 0 T RPL I 16 bits Legend: RPL = Requested Privilege Level (0..3) TI = Table Indicator (0 = GDT, 1 = LDT) INDEX * 8 = number of bytes in table that precede the descriptor segment-selectors defined • Assembly language source-code is easier for humans to read if meaningful symbols are used as names for ‘magic’ numbers # These ‘equates’ provide symbolic names for our segment-selectors .equ .equ ,equ sel_cs0, 0x0008 sel_ds0, 0x0010 sel_es0, 0x0018 # code-segment selector # data-segment selector # vram-segment selector Our ‘pmhello.s’ demo • Use these commands to assemble, link, and install our ‘demo’ program (in class): $ as pmhello.s –o pmhello.o $ ld pmhello.o -T ldscript -o pmhello.b $ dd if=pmhello.b of=/dev/sda4 seek=1 • It also needs a ‘boot-sector’ program that can ‘load’ it at the proper memory-address and then transfer control to its ‘entry-point’ Our ‘quikload.s’ loader • We have provided a ‘boot-sector’ program that you can use in our classroom or labs (it’s not designed to work at other places), or you can use your own ‘loader’ program • Here’s how to assemble, link, and install our ‘quikload.s’ example: $ as quikload.s -o quikload.o $ ld quickload.o -T ldscript -o quikload.b $ dd if=quikloab.b of=/dev/sda4 In-class exercise-set #1 • Find out what will happen if you modify the segment-descriptor for video memory so it uses ‘page’ granularity for its limit-field • Find out what will happen if you do NOT set the ES-register’s segment-limit to 64K before clearing the PE-bit in register CR0 • Find out what will happen if you change the DPL and/or RPL to values other than 0 In-class exercise-set #2 • Redesign the ‘pmhello.s’ program so that it expects to be loaded at a higher address: – Say at address: 0x00040000 (i.e., at 256KB) – Say at address: 0x01000000 (i.e., at 16MB) • You will need to change the ‘disk-address packet’ in our ‘quikload.s’ program so that it will transfer your ‘pmhello.b’ code from the disk to your higher memory address