Post on 12-Jan-2016
description
Using data conversions
How we can ‘peek’ at regions of system memory, such as the
ROM-BIOS DATA AREA
Our programming tools
• Last time we got some in-class practice at using our software development tools:– The Linux assembler: as– The Linux linker: ld– The low-level copying utility: dd– The UNIX visual text-editor: vi
• We applied these tools to the creation of a ‘boot-sector replacement’ (something we’ll need to know about for writing a mini OS)
X86 ‘real-mode’ memory
DRAM
ROM-BIOS
Expansion ROMs
Video BIOS
VRAM
1-MB
CS:IP
InterruptVectorTable
IVTRBDA
ROM-BIOSDATA AREA
EBDAExtended BIOS Data Area
BOOT_LOCN
Disk Storage
Numerical conversions
• While developing and debugging our own miniature operating system, we will often need to display some numerical values
• The ROM-BIOS does not provide ‘helper’ functions for directly displaying raw data
• But assembly language programmers learn to code efficient algorithms which perform frequently needed conversions
Binary-to-Decimal
• We can use a procedure that converts a value found in register AX into its representation as a string of decimal numerals, suitable for output to the terminal screen or to a printing device
• It’s based on repeatedly dividing the AX value by ten (the radix of our decimal-system) to generate a stream of remainders, which are converted to ascii-codes and then displayed in reverse order
Algorithm’s implementation
ax2dec: # converts value in AX to a string of decimal digits at DS:DI pusha # save contents of registersmov $10, %bx # decimal-system base in BXxor %cx, %cx # initialize CX as digit-counter
nxdiv: xor %dx, %dx # extend AX for next divisiondiv %bx # divide (DX,AX) by the basepush %dx # save remainder on the stackinc %cx # and update our digit-counteror %ax, %ax # was the quotient nonzero?jnz nxdiv # yes, then do another division
nxdgt: pop %dx # recover the newest remainderadd $’0’, %dl # convert number to a numeralmov %dl, (%di) # store numeral in output-bufferinc %di # advance output-buffer indexloop nxdgt # process all the remainderspopa # restore contents of registersret
Left-versus-Right justification
• The foregoing assembly language routine draws the string of decimal-digits using a “left-justified” display-convention:
• But sometimes we prefer the appearance of a “right-justified” display-convention
# left-justified # right-justified 34567 34567 963 963 2468 2468
Our ‘memsize.s’ demo
• We’ve written a boot-sector replacement program that reports the amount of real-mode memory available (in kilobytes)
• It uses a ROM-BIOS function (int 0x12) to obtain this memory-size in the AX register
• Then it uses repeated division by ten to convert the AX value into a right-justified string of decimal numerals for display
Can avoid ‘interrupt-0x12’
• It’s possible for a program to find out the upper limit of real-mode memory without using the ‘int $0x12’ ROM-BIOS function
• The memory-size is among the variables stored in the ROM-BIOS data-area – so we can fetch it directly if we know where it’s located, namely at address 0x00413
• ROM-BIOS is only useful in Real Mode
Fetching value from 0x00413
.code16 # for execution in x86 ‘real-mode’
## Here’s real-mode code that returns the ‘memsize’ value in register AX#get_memory_size:
push %ds # preserve value in DS registermov $0x0040, %ax # address ROM-BIOS DATA-AREAmov $%ax, %ds # using the DS segment-registermov %ds:0x13, %ax # load the ‘memsize’ value into AXpop %ds # recover the former DS valueret # return control to the caller
NOTE: The ‘int $0x12’ instruction can be stored in just two bytes: 0xCD, 0x12(which is good to know if your program-code needs to fit within a small space)
Binary-to-Hexadecimal
• Our ability to see a computer’s binary-data in an understandable format will be vital in exploring hardware or debugging software
• 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 numeral-characters
Our ‘ax2hex’ procedure
• We create an array of the ascii-codes for the sixteen hexadecimal digit-characters
• 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’)
hex: .ascii “0123456789ABCDEF”
A 4-bit leftward-rotation
0 1 0 0 0 1 0 1 0 1 1 0 0 1 1 1
0 1 0 1 0 1 1 0 0 1 1 1 0 1 0 0
AX =
AX =
(Before rotation)
(After rotation)
Hi-nybble
Lo-nybble
A bitwise ‘AND’ opration
0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0BX =
? ? ? ? ? ? ? ? 0 1 1 1 0 1 0 0BX =
Lo-nybble
0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1$0xF =
(Before masking)
(After masking)
(bitmask-value)
& & & & & & & & & & & & & & & &
= = = = = = = = = = = = = = = =
Lo-nybble
BL is copied from ALUnknown bits in BH
Thus the lo-nybble (4-bits) gets ‘zero-extended’ to its equivalent 16-bit value
Array ‘lookup’ operation
‘0’ ‘1’ ‘2’ ‘3’ ‘4’ ‘5’ ‘6’ ‘7’ ‘8’ ‘9’ ‘A’ ‘B’ ‘C’ ‘D’ ‘E’ ‘F’hex:
0004BX =
hex( %bx ) = ‘4’
‘4’buf:
&bufDS:DI =
‘4’DL =
mov hex( %bx ), %dl
mov %dl, %ds:( %di )
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 # save general registersmov $4, %cx # setup digit-count
nxnyb:rol $4, %ax # rotate hi-nybble into ALmov %al, %bl # copy the nybble into BLand $0xF, %bx # isolate the nybble’s bitsmov hex(%bx), %dl # lookup nybble’s ascii-codemov %dl, (%di) # store numeral into bufferinc %di # advance the buffer indexloop nxnyb # generate remaining digitspopa # restore saved registersret # return control to the caller
hex: .ascii “0123456789ABCDEF” # array of hex numerals
Our ‘viewrbda.s’ demo
• We can use this binary-to-hex algorithm to view the contents of regions in memory, such as the ROM-BIOS DATA-AREA
• The RBDA includes a number of variables whose values change with system activity
• For a dynamic view of this memory area, we need to draw and redraw its contents
Direct-Drawing to VRAM
• Our demo-program will perform its 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
Background color
Foreground color
ASCII character-code
Byte at odd-numbered offset Byte at even-numbered offset
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 $0xB800, %ax # address VRAM segmentmov %ax, %es # using the ES registerxor %di, %di # point ES:DI at top-left cellmovb $’A’, %es:0(%di) # draw character-code to VRAMmovb $0x07, %es:1(%di) # draw attribute-codes to VRAM
Organization of VRAM
• The first 80 byte-pairs within video memory (at offsets 0, 2, 4, …, 158) control the top row (row number 0) on the screen, in 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 first gets programmed at startup for ‘standard’ text-mode
‘Real-Mode’ Memory Map
BOOT_LOCN0x00007C00
0x00007E00512 bytes
ROM-BIOS
VRAM
IVT
RAM
Vendor’s Firmware
Video Display Memory
No installed memory
Volatile Program Memory 1-MB
RBDA
0x000000000x000004000x00000500
1024 bytes256 bytes
Extended BIOS DataTop of RAM (= 0x000A0000)
Video-ROM
128 kbytes
64+ kbytes
Several regions of interest
• 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)
In-class exercise #1
• Can you revise our ‘memsize.s’ program so that it would get its word-value directly from the ROM-BIOS DATA AREA, rather than by using an ‘int $0x12’ instruction?
In-class exercise #2
• There is a ROM-BIOS service (int 0x11) which returns a word-value in register AX that is known as the ‘equipment_list’ flag
• It’s a collection of bit-fields, rather than a single number, and gives us information about some of the hardware attached to the system (e.g., floppy drives, mouse)
• Can you display it in hexadecimal format?
The ‘Equipment-List’ flag
Bootable floppy-drive installed (1=yes, 0=no)
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Math coprocessor installed (1=yes, 0=no)
Mouse port installed on system board (1=yes, 0=no)
No of floppy drives (if bit 0 is set to 1) 00=one, 01=two, 10=three, 11= four
Initial video display mode 00 = EGA/VGA 01 = color 40x25 10 = color 80x25 11 = mono 80x25
No of serial-ports (0..4)
No of parallel-ports (0..3)
Modem installed (1=yes, 0=no)