provided code
This commit is contained in:
246
specs/freevga/llintro.htm
Normal file
246
specs/freevga/llintro.htm
Normal file
@@ -0,0 +1,246 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user