247 lines
14 KiB
HTML
247 lines
14 KiB
HTML
<HTML>
|
|
<HEAD>
|
|
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
|
|
<META NAME="Author" CONTENT="Joshua Neal">
|
|
<META NAME="Description" CONTENT="Pure VGA/SVGA hardware programming (registers, identification, and otherlow-level stuff.)">
|
|
<META NAME="KeyWords" CONTENT="VGA SVGA hardware video programming">
|
|
<TITLE>FreeVGA -- Introduction to Low-level Programming</TITLE>
|
|
</HEAD>
|
|
<BODY>
|
|
|
|
<CENTER><A HREF="home.htm">Home</A> <A HREF="#intro">Intro</A> <A HREF="#know">Know</A>
|
|
<A HREF="#why">Why</A> <A HREF="#assembly">Assembly</A> <A HREF="#hex">Hex</A>
|
|
<A HREF="#conventions">Conventions</A> <A HREF="#memory">Memory</A> <A HREF="#access">Accessing</A>
|
|
<A HREF="home.htm#intro">Back</A>
|
|
<HR WIDTH="100%"><B>Hardware Level VGA and SVGA Video Programming Information
|
|
Page</B></CENTER>
|
|
|
|
<CENTER>Introduction to Low-level Programming
|
|
<HR WIDTH="100%"></CENTER>
|
|
|
|
|
|
<P><A NAME="intro"></A><B>Introduction</B>
|
|
<BR> This section is intended
|
|
to give one a general background in low-level programming, specifically
|
|
related to video programming. It assumes that you already know how to program
|
|
in your intended programming environment, and answers questions such as:
|
|
<UL>
|
|
<LI>
|
|
<A HREF="#know">What do I need to know?</A></LI>
|
|
|
|
<LI>
|
|
<A HREF="#why">Why write hardware-level code?</A></LI>
|
|
|
|
<LI>
|
|
<A HREF="#assembly">Do I need to know assembly language?</A></LI>
|
|
|
|
<LI>
|
|
<A HREF="#hex">What are hex and binary numbers?</A></LI>
|
|
|
|
<LI>
|
|
<A HREF="#conventions">What are the numerical conventions used in this
|
|
reference?</A></LI>
|
|
|
|
<LI>
|
|
<A HREF="#memory">How do memory and I/O ports work?</A></LI>
|
|
|
|
<LI>
|
|
<A HREF="#access">How do I access these from my programming environment?</A></LI>
|
|
</UL>
|
|
<A NAME="know"></A><B>What do I need to know?</B>
|
|
<BR><B> </B>To program video
|
|
hardware at the lowest level you should have an understanding of hexadecimal
|
|
and binary numbers, how the CPU accesses memory and I/O ports, and finally
|
|
how to perform these operations in your particular programming environment.
|
|
In addition you need detailed descriptions of the particular graphics chipset
|
|
you are programming.
|
|
|
|
<P><A NAME="why"></A><B>Why write hardware-level code?</B>
|
|
<BR> One reason for writing hardware-level
|
|
code is to develop drivers for operating systems or applications. Another
|
|
reason is when existing drivers do not provide the required performance
|
|
or capabilities for your application, such as for programming games or
|
|
multimedia. Finally, the most important reason is enjoyment. There is a
|
|
whole programming scene dedicated to producing "demos" of what the VGA/SVGA
|
|
can do.
|
|
|
|
<P><A NAME="assembly"></A><B>Do I need to know assembly language?</B>
|
|
<BR> No, but it helps. Assembly
|
|
language is the basis all CPU operations. All functions of the processor
|
|
and computer are potentially accessible from assembly. With crafty use
|
|
of assembly language, one can write software that exceeds greatly the potential
|
|
of higher level languages. However, any programming environment that provides
|
|
direct access to I/O and memory will work.
|
|
|
|
<P><A NAME="hex"></A><B>What are hex and binary numbers?</B>
|
|
<BR> Humans use a number system
|
|
using 10 different digits (0-9), probably because that is the number of
|
|
fingers we have. Each digit represents part of a number with the rightmost
|
|
digit being ones, the second to right being tens, then hundreds, thousands
|
|
and so on. These represent the powers of 10 and is called "base 10" or
|
|
"decimal."
|
|
<BR> Computers are digital (and
|
|
don't usually have fingers) and use two states, either on or off to represent
|
|
numbers. The off state is represented by 0 and the on state is represented
|
|
by 1. Each digit (called a bit, short for Binary digIT) here represents
|
|
a power of 2, such as ones, twos, fours, and doubling each subsequent digit.
|
|
Thus this number system is called "base 2" or "binary."
|
|
<BR> Computer researchers realized
|
|
that binary numbers are unwieldy for humans to deal with; for example,
|
|
a 32-bit number would be represented in binary as 11101101010110100100010010001101.
|
|
Converting decimal to binary or vice versa requires multiplication or division,
|
|
something early computers performed very slowly, and researchers instead
|
|
created a system where the numbers were broken into groups of 3 (such as
|
|
11 101 101 010 110 100 100 010 010 001 101) and assigned a number from
|
|
0-7 based on the triplet's decimal value. This number system is called
|
|
"base 8" or "octal."
|
|
<BR> Computers deal with numbers
|
|
in groups of bits usually a length that is a power of 2, for example, four
|
|
bits is called a "nibble", eight bits is called a "byte", 16 bits is a
|
|
"word", and 32 bits is a "double word." These powers of two are not equally
|
|
divisible by 3, so as you see in the divided example a "double word" is
|
|
represented by 10 complete octal digits plus two-thirds of an octal digit.
|
|
It was then realized that by grouping bits into groups of four, a byte
|
|
could be accurately represented by two digits. Because a group of four
|
|
bits can represent 16 decimal numbers, they could not be represented by
|
|
simply using 0-9, so they simply created more digits, or rather re-used
|
|
the letters A-F (or a-f) to represent 10-15. So for example the rightmost
|
|
digits of our example binary number is 1101, which translates to 13 decimal
|
|
or D in this system, which is called "base 16" or "hexadecimal."
|
|
<BR> Computers nowadays usually
|
|
speak decimal (multiplication and division is much faster now) but when
|
|
it comes to low-level and hardware stuff, hexadecimal or binary is usually
|
|
used instead. Programming environments require you to explicitly specify
|
|
the base a number is in when overriding the default decimal. In most assembler
|
|
packages this is accomplished by appending "h" for hex and "b" for binary
|
|
to end of the number, such as 2A1Eh or 011001b. In addition, if the hex
|
|
value starts with a letter, you have to add a "0" to the beginning of the
|
|
number to allow it to distinguish it from a label or identifier, such as
|
|
0BABEh. In C and many other languages the standard is to append "0x" to
|
|
the beginning of the hex number and to append "%" to the beginning of a
|
|
binary number. Consult your programming environment's documentation for
|
|
how specifically to do this.
|
|
<BR> Historical Note: Another
|
|
possible explanation for the popularity of the octal system is that early
|
|
computers used 12 bit addressing instead of the 16 or 32 bit addressing
|
|
currently used by modern processors. Four octal digits conveniently covers
|
|
this range exactly, thus the historical architecture of early computers
|
|
may have been the cause for octal's popularity.
|
|
|
|
<P><A NAME="conventions"></A><B>What are the numerical conventions used
|
|
in this reference?</B>
|
|
<BR><B> </B>Decimal is used often
|
|
in this reference, as it is conventional to specify certain details about
|
|
the VGA's operation in decimal. Decimal numbers have no letter after them.
|
|
An example you might see would be a video mode described as 640x480z256.
|
|
This means that the video mode has 640 pixels across by 480 pixels down
|
|
with 256 possible simultaneous colors. Similarly an 80x25 text mode means
|
|
that the text mode has 80 characters wide (columns) by 25 characters high
|
|
(rows.) Binary is frequently used to specify fields within a particular
|
|
register and also for bitmap patterns, and has a trailing letter b (such
|
|
as 10011100b) to distinguish it from a decimal number containing only 0's
|
|
and 1's. Octal you are not likely to encounter in this reference, but if
|
|
used has a trailing letter o (such as 145o) to distinguish it from a decimal.
|
|
Hexadecimal is always used for addressing, such as when describing I/O
|
|
ports, memory offsets, or indexes. It is also often used in fields longer
|
|
than 3 bits, although in some cases it is conventional to utilize decimal
|
|
instead (for example in a hypothetical screen-width field.)
|
|
<BR> Note: Decimal numbers in
|
|
the range 0-1 are also binary digits, and if only a single digit is present,
|
|
the decimal and binary numbers are equivalent. Similarly, for octal the
|
|
a single digit between 0-7 is equivalent to the decimal numbers in the
|
|
same range. With hexadecimal, the single-digit numbers 0-9 are equivalent
|
|
to decimal numbers 0-9. Under these circumstances, the number is often
|
|
given as decimal where another format would be conventional, as the number
|
|
is equivalent to the decimal value.
|
|
<BR>
|
|
|
|
<P><A NAME="memory"></A><B>How do memory and I/O ports work?</B>
|
|
<BR> 80x86 machines have both
|
|
a memory address space and an input/output (I/O) address space. Most of
|
|
the memory is provided as system RAM on the motherboard and most of the
|
|
I/O devices are provided by cards (although the motherboard does provide
|
|
quite a bit of I/O capability, varying on the motherboard design.) Also
|
|
some cards also provide memory. The VGA and SVGA display adapters provide
|
|
memory in the form of video memory, and they also handle I/O addresses
|
|
for controlling the display, so you must learn to deal with both. An adapter
|
|
card could perform all of its functions using solely memory or I/O (and
|
|
some do), but I/O is usually used because the decoding circuitry is simpler
|
|
and memory is used when higher performance is required.
|
|
<BR> The original PC design was
|
|
based upon the capabilities of the 8086/8088, which allowed for only 1
|
|
MB of memory, of which a small range (64K) was allotted for graphics memory.
|
|
Designers of high-resolution video cards needed to put more than 64K of
|
|
memory on their video adapters to support higher resolution modes, and
|
|
used a concept called "banking" which made the 64K available to the processor
|
|
into a "window" which shows a 64K chunk of video memory at once. Later
|
|
designs used multiple banks and other techniques to simplify programming.
|
|
Since modern 32-bit processors have 4 gigabytes of address space, some
|
|
designers allow you to map all of the video memory into a "linear frame
|
|
buffer" allowing access to the entire video memory at once without having
|
|
to change the current window pointer (which can be time consuming.) while
|
|
still providing support for the windowed method.
|
|
<BR> Memory can be accessed most
|
|
flexibly as it can be the source and/or target of almost every machine
|
|
language instruction the CPU is capable of executing, as opposed to a very
|
|
limited set of I/O instructions. I/O space is divided into 65536 addresses
|
|
in the range 0-65535. Most I/O devices are configured to use a limited
|
|
set of addresses that cannot conflict with another device. The primary
|
|
instructions for accessing I/O are the assembly instructions "IN" and "OUT",
|
|
simply enough. Most programming environments provide similarly named instructions,
|
|
functions, or procedures for accessing these.
|
|
<BR> Memory can be a bit confusing
|
|
though, because the CPU has two memory addressing modes, Real mode and
|
|
Protected mode. Real mode was the only method available on the 8086 and
|
|
is still the primary addressing mode used in DOS. Unfortunately, real mode
|
|
only provides access to the first 1 MB of memory. Protected mode is used
|
|
on the 80286 and up to allow access to more memory. (There are also other
|
|
details such as protection, virtual memory, and other aspects not particularly
|
|
applicable to this discussion.) Memory is accessed by the 80x86 processors
|
|
using segments and offsets. Segments tell the memory management unit where
|
|
in memory is located, and the offset is the displacement from that address.
|
|
In real mode offsets are limited to 64K, because of the 16-bit nature of
|
|
the 8086. In protected mode, segments can be any size up to the full address
|
|
capability of the machine. Segments are accessed via special segment registers
|
|
in the processor. In real mode, the segment address is shifted left four
|
|
bits and added to the offset, allowing for a 20 bit address (20 bits =
|
|
1 MB); in protected mode segments are offsets into a table in memory which
|
|
tells where the segment is located. Your particular programming environment
|
|
may create code for real and/or protected mode, and it is important to
|
|
know which mode is being used. An added difficulty is the fact that protected
|
|
mode provides for I/O and memory protection (hence protected mode), in
|
|
order to allow multiple programs to share one processor and prevent them
|
|
from corrupting other processes. This means that you may need to interact
|
|
with the operating system to gain rights to access the hardware directly.
|
|
If you write your own protected mode handler for DOS or are using a DOS
|
|
extender, then this should be simple, but it is much more complicated under
|
|
multi-tasking operating systems such as Windows or Linux.
|
|
|
|
<P><A NAME="access"></A><B>How do I access these from my programming environment?</B>
|
|
<BR> That is a very important
|
|
question, one that is very difficult to answer without knowing all of the
|
|
details of your programming environment. The documentation that accompanies
|
|
your particular development environment is best place to look for this
|
|
information, in particular the compiler, operating system, and/or the chip
|
|
specifications for the platform.
|
|
|
|
<P>Details for some common programming environments are given in:
|
|
<UL>
|
|
<LI>
|
|
Eli Zaretskii's <A HREF="http://www.delorie.com/djgpp/v2faq/faq133.html#Low-level">DJGPP
|
|
Frequently-Asked Questions List: Low-level DOS/BIOS and Hardware-oriented
|
|
Programming</A> -- details on accessing hardware in DJGPP, a free 32-bit
|
|
compiler and programming environment for MS-DOS.</LI>
|
|
|
|
<LI>
|
|
There were more links here, but they expired. If anyone wants to write
|
|
an article or has a link on this topic for their favorite environment,
|
|
I will gladly and thankfully put it on this site.</LI>
|
|
</UL>
|
|
Notice: All trademarks used or referred to on this page are the property
|
|
of their respective owners.
|
|
<BR>All pages are Copyright © 1997, 1998, J. D. Neal, except where
|
|
noted. Permission for utilization and distribution is subject to the terms
|
|
of the <A HREF="license.htm">FreeVGA Project Copyright License</A>.
|
|
</BODY>
|
|
</HTML>
|