Viewing 8086 memory-areas A peek into the video display memory,

advertisement
Viewing 8086 memory-areas
A peek into the video display memory,
the real-mode Interrupt Vector Table,
and the ROM-BIOS DATA AREA
Hexadecimal displays
• The ability to exhibit computer-data in a
form that’s understandable will be vital for
exploring (and for debugging) our system
• The easiest scheme for doing it will be to
show binary values in hexadecimal format
• Let’s look at a straightforward algorithm to
convert any 16-bit number into a string of
(four) hexadecimal numerals
Our ‘ax2hex’ procedure
• We create an array of the ascii-codes for
the sixteen hexadecimal digit-characters
hex: .ascii “0123456789ABCDEF”
• Our procedure expects the binary value to
be in register AX and the memory-address
for the hex-string is in registers DS:DI
• Our procedure will preserve the contents
of the CPU’s registers (no ‘side-effects’)
A 4-bit left-rotation
Hi-nybble
AX =
0 1 0 0 0 1 0 1 0 1 1 0 0 1 1 1
(Before rotation)
AX =
0 1 0 1 0 1 1 0 0 1 1 1 0 1 0 0
(After rotation)
Lo-nybble
A bitwise ‘AND’ opration
BL is copied from AL
Unknown bits in BH
BX =
Lo-nybble
? ? ? ? ? ? ? ? 0 1 1 1 0 1 0 0
(Before masking)
& & & & & & & & & & & & & & & &
$0xF =
0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1
(bitmask-value)
= = = = = = = = = = = = = = = =
BX =
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
(After masking)
Lo-nybble
Thus the lo-nybble (4-bits) gets ‘zero-extended’ to its equivalent 16-bit value
Array ‘lookup’ operation
hex:
‘0’ ‘1’ ‘2’ ‘3’ ‘4’ ‘5’ ‘6’ ‘7’ ‘8’ ‘9’ ‘A’ ‘B’ ‘C’ ‘D’ ‘E’ ‘F’
hex( %bx ) = ‘4’
mov hex( %bx ), %dl
BX = 0004
DL =
DS:DI = &buf
‘4’
mov %dl, %ds:( %di )
buf:
‘4’
So the number 4 in BX gets
converted to the numeral ‘4’
in the ‘buf’ array-cell at DS:DI
Algorithm implementation
ax2hex: # converts the word-value in AX to a hex-string at DS:DI
pusha
mov
$4, %cx
# save general registers
# setup digit-count
nxnyb:
hex:
rol
mov
and
mov
mov
inc
loop
popa
ret
$4, %ax
%al, %bl
$0xF, %bx
hex(%bx), %dl
%dl, (%di)
%di
nxnyb
# rotate hi-nybble into AL
# copy the nybble into BL
# isolate the nybble’s bits
# lookup nybble’s ascii-code
# store numeral into buffer
# advance the buffer index
# generate remaining digits
# restore saved registers
# return control to the caller
.ascii
“0123456789ABCDEF”
# array of hex numerals
Algorithm applications
• We can use this binary-to-hex algorithm to view
the contents of two memory-regions which
ROM-BIOS startup-code initializes:
– The table of ‘real-mode’ interrupt vectors
– The values in the ROM-BIOS DATA-AREA
• Two ‘boot-sector’ demo-programs are named
‘viewivt.s’ and ‘viewrbda.s’
• They are on the CS 630 website:
<http://cs.usfca.edu/~cruse/cs630>
Direct-Drawing to VRAM
• Both demo-programs perform their display
by writing character-codes directly into the
text-mode video-display memory-region (it
starts at memory-address 0x000B8000)
• Each onscreen character is controlled by a
pair of adjacent bytes in the video memory
Byte at odd-numbered offset
Background
color
Foreground
color
Byte at even-numbered offset
ASCII
character-code
Drawing ‘A’ in top-left corner
• Here’s a fragment of assembly-language
code that draws an uppercase letter ‘A’ in
the top-left corner of the screen (using the
normal ‘white-on-black’ color-attributes):
mov
mov
xor
movb
movb
$0xB800, %ax
%ax, %es
%di, %di
$’A’, %es:0(%di)
$0x07, %es:1(%di)
# address VRAM segment
# using the ES register
# point ES:DI at top-left cell
# draw character-code to VRAM
# draw attribute-codes to VRAM
Organization of VRAM
• The first 80 byte-pairs in video memory (at
offsets 0, 2, 4, …, 158) control the top row (row
0) on the screen (left-to-right order)
• Then the next 80 byte-pairs (offsets 160, 162,
164, …, 318) control the next row of text on the
screen (i.e., row number 1)
• Altogether there are 25 rows of text, with 80
characters per row, when the display is
programmed at startup for ‘standard’ text-mode
We need more rows for IVT
• The real-mode Interrupt Vector Table has
room for 256 ‘pointers’ (each pointer being
a doubleword segment-and-offset value)
• Not enough cells in the 80x25 text mode to
view all 256 of the ‘vectors’ simultaneously
• We need 9 characters for each vector (i.e.,
8 hex-digits, plus a space for separation),
but 256 x 9 is greater than 80 x 25 =2000
Solution
• We can invoke a ROM-BIOS function that
reprograms the display-hardware to show
twice as many rows (in smaller-size text)
• Here’s a code-fragment to accomplish it:
mov
int
$0x0003, %ax
$0x10
# set standard 80x25 textmode
# invoke BIOS video service
mov
int
$0x1112, %ax
$0x10
# load 80x50 character-glyphs
# invoke BIOS video service
Code ‘reuse’
• Our earlier ‘ax2hex’ procedure converts a
word into a string of hexadecimal digits
• But each interrupt-vector is a doubleword!
• We could use a new procedure: ‘eax2hex’
• But it’s easier if we just call ‘ax2hex’ twice
• This requires us to clearly understand the
Pentium’s scheme for addressing memory
(i.e., the ‘little-endian’ storage convention)
‘Little endian’ versus ‘Big endian’
EAX =
0x0369CF25
Power-PC processor uses
‘big-endian’ convention
0
1
2
3
25
CF
69
03
‘Little endian’
convention
(least-significant
byte is at lowest
memory-address)
Intel x86 CPU’s
use ‘little endian’
storage contention
0
1
2
3
03
69
CF
25
‘Big endian’
convention
(most-significant
byte is at lowest
memory-address)
Example: convert vector 0 to hex
“xxxxxxxx”
buf:
.ascii
# room for 8 hex-digits
xor
mov
%bx, %bx
%bx, %fs
# address bottom of memory
# using register-pair FS:BX
mov
lea
call
%fs:0(%bx), %ax
buf+4, %di
ax2hex
# fetch vector’s low-word
# point DS:DI to position
# convert AX to hex-string
mov
lea
call
%fs:2(%bx)m %ax
buf+0, %di
ax2hex
# fetch vector’s high-word
# point DS:DI to position
# convert AX to hex-string
Vector0:
# OK, ‘buf’ now holds the 8-digit hex-string representing vector 0
‘Real-Mode’ Memory Map
Vendor’s Firmware
ROM-BIOS
64+ kbytes
No installed memory
Video-ROM
Video Display Memory
Top of RAM (= 0x000A0000)
Volatile Program Memory
0x00007E00
0x00007C00
0x00000500
0x00000400
0x00000000
VRAM
128 kbytes
Extended BIOS Data
1-MB
RAM
BOOT_LOCN 512 bytes
RBDA
IVT
256 bytes
1024 bytes
Tool for exploring 8086 memory
• We have written a Linux device-driver, and
a companion application-program, that lets
you view the bottom megabyte of memory
• First you have to compile, and then install,
the ‘8086.c’ device-driver kernel-object:
$ mmake 8086
$ /sbin/insmod 8086.ko
• Then you can execute our ‘fileview’ tool:
$ ./fileview /dev/8086
‘fileview’ commands
• You use arrow-keys to navigate memory,
or <ENTER> to enter specific addresses
• You can adjust the hexadecimal formatting
(‘B’ = byte, ‘W’ = word, ‘D’ = doubleword)
• You can quit by hitting the <ESCAPE>-key
Examples
•
•
•
•
•
•
•
View ROM-BIOS code at 0xF0000
View Interrupt Vectors at 0x00000
View ROM-BIOS DATA at 0x00400
View Text-mode VRAM at 0xB8000
View Video ROM-BIOS at 0xC0000
View the BOOT_LOCN at 0x07C00
(Note: Linux may have ‘overwritten’ some
areas that ROM-BIOS startup-code set up)
Question
• The Extended BIOS Data Area resides in
a portion of RAM that’s usually just below
the VRAM memory-area (at 0x000A0000)
• This portion of RAM is subtracted from the
total RAM available to operating systems
• So where’s the top of the ‘unused’ portion
of the installed RAM?
BIOS ‘Get MemSize’ function
• There’s a function your real-mode code
can call to find out where ‘top-of-ram’ is
• This function requires no arguments; it
merely returns a value in the AX register
• That value gives the size of the memory
(in kilobytes) that lies below ‘top-of-ram’
• You call this routine using: int $0x12
Our ‘memsize.s’ demo
• If you assemble, link, and install our demo,
it will show you the size of ‘free’ memory
when you reboot your workstation
$ cp /home/web/cruse/cs630/memsize.s .
$ as memsize.s –o memsize.o
$ ld memsize.o -T ldscript -o memsize.b
$ dd if=memsize.b of=/dev/sda4
Now boot from the GRUB ‘CS 630 partition’
Download