Defining protected-mode segment-descriptors An example of a protected-mode bootsector application that draws

advertisement

Defining protected-mode segment-descriptors

An example of a protected-mode bootsector application that draws a message to the video display

What will we do once there?

• Let’s explore writing a bootsector program that will do something perceptible while in protected-mode, namely: show a message

• We won’t be able to call BIOS functions

(they’re designed to work in real-mode)

• We must write directly to video memory

Recall PC Memory Layout

0xF0000

0xC0000

0xA0000

ROM-BIOS

VIDEO-BIOS

VRAM

RAM 1-MB

0x00000

0xB8000

0xB0000

0xA0000

Three VRAM zones

COLOR TEXT

MONOCHROME TEXT

GRAPHICS

32-KB

32-KB

64-KB

Array of picture-elements

• Text-mode VRAM is organized as an array

• Each array-element occupies one word

• Word’s LSB holds ascii character-code

• Word’s MSB holds a color-number pair

15 bgcolor

12 11 fgcolor

8 7

ASCII character-code

0 nybble nybble byte

Color-Attribute Byte

Blink

R G B

Intense

R background color attribute

G B foreground color attribute

Screen-element locations

80 columns characters 0..79

characters 80..159

25 rows characters 1920..1999

Video screen

x86 “Little-Endian” storage

• Intel’s x86 CPUs use little-endian storage

• The “little end” of any multibyte value is stored at the smaller operand-address

• Example: EAX = 0x12345678 mov [0x9000], EAX

Memory-addresses occupied by operand

0x78

0x9000

0x56

0x9001

0x34

0x9002

0x12

0x9003

Drawing a character-string

• Setup DS:SI with string’s starting address

• Setup ES:DI with initial address on screen

• Clear DF-bit (Direction Flag) in FLAGS register

• Setup desired color attribute-byte in AH register again: lodsb ; next character to AL or al, al ; is final null-byte?

jz finis stosw jmp again

; yes, exit from loop

; write char & colors

; go back for another finis:

Planning our memory usage

• To draw a screen-message in protectedmode, our program will need to address these memory-segments:

– its code (executable, at 0x07C00)

– its data (readable and writable, at 0x07C00)

– its stack (readable, writable, expand-down)

– the video ram (32KB, writable, at 0xB8000)

• For its return to real-mode, our program will need 64KB code and data segments

31

VRAM segment-descriptor

Base[31..24] G D

R

S

V

A

V

L

Limit

[19..16]

P

D

P

L

C R

S X / /

D W

A Base[23..16]

16

Base[15..0] Limit[15..0]

15 0

VRAM Base-Address = 0x000B8000

VRAM Segment-Limit = 0x07FFF (32-KB)

Segment-attributes: P=1, A=0, S=1, X=0, D=0, W=1

DPL=0, G=0, D=0 (RSV=0, AVL=0)

.WORD

0x7FFF, 0x8000, 0x920B, 0x0000

31

CODE segment-descriptor

Base[31..24] G D

R

S

V

A

V

L

Limit

[19..16]

P

D

P

L

C R

S X / /

D W

A Base[23..16]

16

Base[15..0] Limit[15..0]

15 0

CODE Base-Address = 0x00007C00

CODE Segment-Limit = 0x0FFFF (64-KB)

Segment-attributes: P=1, A=0, S=1, X=1, C=0, R=1

DPL=0, G=0, D=0 (RSV=0, AVL=0)

.WORD

0xFFFF, 0x7C00, 0x9A00, 0x0000

31

DATA segment-descriptor

Base[31..24] G D

R

S

V

A

V

L

Limit

[19..16]

P

D

P

L

C R

S X / /

D W

A Base[23..16]

16

Base[15..0] Limit[15..0]

15 0

DATA Base-Address = 0x00007C00

DATA Segment-Limit = 0x0FFFF (64-KB)

Segment-attributes: P=1, A=0, S=1, X=0, D=0, W=1

DPL=0, G=0, D=0 (RSV=0, AVL=0)

.WORD

0xFFFF, 0x7C00, 0x9200, 0x0000

31

STACK segment-descriptor

16

Base[31..24] G D

R

S

V

A

V

L

Limit

[19..16]

P

D

P

L

C R

S X / /

D W

A Base[23..16]

Base[15..0] Limit[15..0]

15 0

STACK Base-Address = 0x00007C00

STACK Segment-Limit = 0x001FF (512-Bytes)

Segment-attributes: P=1, A=0, S=1, X=0, D=1, W=1

DPL=0, G=0, D=0 (RSV=0, AVL=0)

.WORD

0x01FF, 0x7C00, 0x9600, 0x0000

Setting up the GDT

• Base-Address must be quadword-aligned

.ALIGN

8

• NULL-Descriptor occupies first quadward theGDT: .WORD

0, 0, 0, 0

• GDT base-address and segment-limit: base: #0x00007C00 + #theGDT limit: 8 * (number of descriptors) - 1

Loading register LDTR

GDTR BASE_ADDRESS LIMIT

48-bits

• We can load LDTR from our stack: mov add eax, #0x00007C00 ; boot location eax, #theGDT ; add GDT offset mov push push lgdt add dx, #0x27 eax dx

[esp] esp, #6

; five descriptors

; push bits 47..16

; push bits 15..0

; load 48-bit LDTR

; discard 3 words

Entering protected-mode

• No interrupts from any peripheral devices

(since BIOS’s real-mode ISRs won’t work)

• Set the PE-bit to 1 (in register CR0)

• Do a far-jump (to load the CS attributes)

• Load SS:SP with stacktop and attributes

• Setup DS and ES for data and vram

• Write character-string to video memory

Leaving protected-mode

• Be sure segment-registers are loaded with selectors for descriptors that have suitable segment-limits and segment-attributes for correct execution when back in real-mode

• Reset PE-bit to 0 (in register CR0)

• Do a far-jump (to load CS with paragraph)

• Load SS:SP with real-mode stack-address

• Wait for user’s keypress before rebooting

Demo-program

• We have a bootsector program on website

(‘pmhello.s’) which illustrates the principles just discussed

• Try assembling and installing it:

– $ as86 pmhello.s –b pmhello.b

– $ dd if=pmhello.b of=/dev/fd0

• Restart machine, use the GRUB memu to select this bootsector as execution-option

In-class exercises

• What happens if you changed the ‘code’ descriptor’s access-rights byte from 0x9A to 0x9C (i.e., conforming code-segment)?

• Where exactly in does the ‘expand-down’ stack-segment reside?

– BASE_ADDRESS = 0x00007C00

– SEGMENT_LIMIT = 0x001FF

Download